can speed optimizations
This commit is contained in:
parent
9585e59df1
commit
162522b3b2
120
lib/stm32/can.c
120
lib/stm32/can.c
@ -192,12 +192,9 @@ void can_filter_init(u32 canport, u32 nr, bool scale_32bit, bool id_list_mode,
|
|||||||
{
|
{
|
||||||
u32 filter_select_bit = 0x00000001 << nr;
|
u32 filter_select_bit = 0x00000001 << nr;
|
||||||
|
|
||||||
/* Request initialization "enter". */
|
/* Request initialization "enter". */
|
||||||
CAN_FMR(canport) |= CAN_FMR_FINIT;
|
CAN_FMR(canport) |= CAN_FMR_FINIT;
|
||||||
|
|
||||||
CAN_FMR(canport) &= (~0x3fUL)<<8;
|
|
||||||
CAN_FMR(canport) |= (14UL)<<8;
|
|
||||||
|
|
||||||
/* Deactivate the filter. */
|
/* Deactivate the filter. */
|
||||||
CAN_FA1R(canport) &= ~filter_select_bit;
|
CAN_FA1R(canport) &= ~filter_select_bit;
|
||||||
|
|
||||||
@ -344,8 +341,12 @@ selected. -1 if no mailbox was available and no transmission got queued.
|
|||||||
*/
|
*/
|
||||||
int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
|
int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
|
||||||
{
|
{
|
||||||
int ret = 0, i;
|
int ret = 0;
|
||||||
u32 mailbox = 0;
|
u32 mailbox = 0;
|
||||||
|
union {
|
||||||
|
u8 data8[4];
|
||||||
|
u32 data32;
|
||||||
|
}tdlxr,tdhxr;
|
||||||
|
|
||||||
/* Check which transmit mailbox is empty if any. */
|
/* Check which transmit mailbox is empty if any. */
|
||||||
if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
if ((CAN_TSR(canport) & CAN_TSR_TME0) == CAN_TSR_TME0) {
|
||||||
@ -362,36 +363,59 @@ int can_transmit(u32 canport, u32 id, bool ext, bool rtr, u8 length, u8 *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we have no empty mailbox return with an error. */
|
/* If we have no empty mailbox return with an error. */
|
||||||
if (ret == -1)
|
if (ret == -1) {
|
||||||
return ret;
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear stale register bits */
|
|
||||||
CAN_TIxR(canport, mailbox) = 0;
|
|
||||||
if (ext) {
|
if (ext) {
|
||||||
/* Set extended ID. */
|
/* Set extended ID. */
|
||||||
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_EXID_SHIFT;
|
CAN_TIxR(canport, mailbox) = (id << CAN_TIxR_EXID_SHIFT) | CAN_TIxR_IDE;
|
||||||
/* Set extended ID indicator bit. */
|
|
||||||
CAN_TIxR(canport, mailbox) |= CAN_TIxR_IDE;
|
|
||||||
} else {
|
} else {
|
||||||
/* Set standard ID. */
|
/* Set standard ID. */
|
||||||
CAN_TIxR(canport, mailbox) |= id << CAN_TIxR_STID_SHIFT;
|
CAN_TIxR(canport, mailbox) = id << CAN_TIxR_STID_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set/clear remote transmission request bit. */
|
/* Set/clear remote transmission request bit. */
|
||||||
if (rtr)
|
if (rtr){
|
||||||
CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */
|
CAN_TIxR(canport, mailbox) |= CAN_TIxR_RTR; /* Set */
|
||||||
|
}
|
||||||
/* Set the DLC. */
|
/* Set the DLC. */
|
||||||
CAN_TDTxR(canport, mailbox) &= 0xFFFFFFF0;
|
CAN_TDTxR(canport, mailbox) &= ~CAN_TDTxR_DLC_MASK;
|
||||||
CAN_TDTxR(canport, mailbox) |= length & CAN_TDTxR_DLC_MASK;
|
CAN_TDTxR(canport, mailbox) |= (length & CAN_TDTxR_DLC_MASK);
|
||||||
|
|
||||||
|
switch(length) {
|
||||||
|
case 8:
|
||||||
|
tdhxr.data8[3] = data[7];
|
||||||
|
/* no break */
|
||||||
|
case 7:
|
||||||
|
tdhxr.data8[2] = data[6];
|
||||||
|
/* no break */
|
||||||
|
case 6:
|
||||||
|
tdhxr.data8[1] = data[5];
|
||||||
|
/* no break */
|
||||||
|
case 5:
|
||||||
|
tdhxr.data8[0] = data[4];
|
||||||
|
/* no break */
|
||||||
|
case 4:
|
||||||
|
tdlxr.data8[3] = data[3];
|
||||||
|
/* no break */
|
||||||
|
case 3:
|
||||||
|
tdlxr.data8[2] = data[2];
|
||||||
|
/* no break */
|
||||||
|
case 2:
|
||||||
|
tdlxr.data8[1] = data[1];
|
||||||
|
/* no break */
|
||||||
|
case 1:
|
||||||
|
tdlxr.data8[0] = data[0];
|
||||||
|
/* no break */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* Set the data. */
|
/* Set the data. */
|
||||||
CAN_TDLxR(canport, mailbox) = 0;
|
|
||||||
CAN_TDHxR(canport, mailbox) = 0;
|
CAN_TDLxR(canport, mailbox) = tdlxr.data32;
|
||||||
for (i = 0; (i < 4) && (i < length); i++)
|
CAN_TDHxR(canport, mailbox) = tdhxr.data32;
|
||||||
CAN_TDLxR(canport, mailbox) |= (u32)data[i] << (8 * i);
|
|
||||||
for (i = 4; (i < 8) && (i < length); i++)
|
|
||||||
CAN_TDHxR(canport, mailbox) |= (u32)data[i] << (8 * (i - 4));
|
|
||||||
|
|
||||||
/* Request transmission. */
|
/* Request transmission. */
|
||||||
CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ;
|
CAN_TIxR(canport, mailbox) |= CAN_TIxR_TXRQ;
|
||||||
@ -430,12 +454,13 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
|
|||||||
bool *rtr, u32 *fmi, u8 *length, u8 *data)
|
bool *rtr, u32 *fmi, u8 *length, u8 *data)
|
||||||
{
|
{
|
||||||
u32 fifo_id = 0;
|
u32 fifo_id = 0;
|
||||||
int i;
|
union {
|
||||||
|
u8 data8[4];
|
||||||
|
u32 data32;
|
||||||
|
}rdlxr,rdhxr;
|
||||||
|
const u32 fifoid_array[2] = {CAN_FIFO0,CAN_FIFO1};
|
||||||
|
|
||||||
if (fifo == 0)
|
fifo_id = fifoid_array[fifo];
|
||||||
fifo_id = CAN_FIFO0;
|
|
||||||
else
|
|
||||||
fifo_id = CAN_FIFO1;
|
|
||||||
|
|
||||||
/* Get type of CAN ID and CAN ID. */
|
/* Get type of CAN ID and CAN ID. */
|
||||||
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
|
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_IDE) {
|
||||||
@ -450,11 +475,15 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
|
|||||||
CAN_RIxR_STID_SHIFT);
|
CAN_RIxR_STID_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get request transmit flag. */
|
/* Get remote transmit flag. */
|
||||||
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR)
|
if (CAN_RIxR(canport, fifo_id) & CAN_RIxR_RTR)
|
||||||
|
{
|
||||||
*rtr = true;
|
*rtr = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
*rtr = false;
|
*rtr = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get filter match ID. */
|
/* Get filter match ID. */
|
||||||
*fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >>
|
*fmi = ((CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_FMI_MASK) >>
|
||||||
@ -462,17 +491,36 @@ void can_receive(u32 canport, u8 fifo, bool release, u32 *id, bool *ext,
|
|||||||
|
|
||||||
/* Get data length. */
|
/* Get data length. */
|
||||||
*length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK;
|
*length = CAN_RDTxR(canport, fifo_id) & CAN_RDTxR_DLC_MASK;
|
||||||
|
/* accelerate reception by copying the CAN data from the controller memory to
|
||||||
|
* the fast internal RAM */
|
||||||
|
|
||||||
/* Get data. */
|
rdlxr.data32 = CAN_RDLxR(canport, fifo_id);
|
||||||
for (i = 0; (i < 4) && (i < *length); i++)
|
rdhxr.data32 = CAN_RDHxR(canport, fifo_id);
|
||||||
data[i] = (CAN_RDLxR(canport, fifo_id) >> (8 * i)) & 0xFF;
|
/* */
|
||||||
|
/* Get data.
|
||||||
for (i = 4; (i < 8) && (i < *length); i++)
|
* Byte wise copy is needed because we do not know the alignment
|
||||||
data[i] = (CAN_RDHxR(canport, fifo_id) >> (8 * (i - 4))) & 0xFF;
|
* of the input buffer.
|
||||||
|
* Here copying 8 bytes each is faster than using loop
|
||||||
|
*
|
||||||
|
* It is OK to copy all 8 bytes because the upper layer must be
|
||||||
|
* prepared that the data length of the CAN frame is bigger
|
||||||
|
* than expected. In contrary the driver has no clue what is expected.
|
||||||
|
* This could be different if the max length would be handed over
|
||||||
|
* to the function, but it is not the case
|
||||||
|
*/
|
||||||
|
data[0] = rdlxr.data8[0];
|
||||||
|
data[1] = rdlxr.data8[1];
|
||||||
|
data[2] = rdlxr.data8[2];
|
||||||
|
data[3] = rdlxr.data8[3];
|
||||||
|
data[4] = rdhxr.data8[0];
|
||||||
|
data[5] = rdhxr.data8[1];
|
||||||
|
data[6] = rdhxr.data8[2];
|
||||||
|
data[7] = rdhxr.data8[3];
|
||||||
|
|
||||||
/* Release the FIFO. */
|
/* Release the FIFO. */
|
||||||
if (release)
|
if (release){
|
||||||
can_fifo_release(canport, fifo);
|
can_fifo_release(canport, fifo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_available_mailbox(u32 canport)
|
bool can_available_mailbox(u32 canport)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user