Add support for extended (29-bit) CAN IDs

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4319 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-01-20 21:52:35 +00:00
parent a6d160ea4b
commit 400935a2af
3 changed files with 86 additions and 40 deletions

View File

@ -745,20 +745,39 @@ static int can_remoterequest(FAR struct can_dev_s *dev, uint16_t id)
static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->cd_priv;
uint32_t tid = CAN_ID(msg->cm_hdr);
uint32_t tfi = CAN_DLC(msg->cm_hdr) << 16;
uint32_t tid = (uint32_t)msg->cm_hdr.ch_id;
uint32_t tfi = (uint32_t)msg->cm_hdr.ch_dlc << 16;
uint32_t regval;
irqstate_t flags;
int ret = OK;
canvdbg("CAN%d ID: %d DLC: %d\n",
priv->port, CAN_ID(msg->cm_hdr), CAN_DLC(msg->cm_hdr));
canvdbg("CAN%d ID: %d DLC: %d\n", priv->port, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc);
if (CAN_RTR(msg->cm_hdr))
if (msg->cm_hdr.ch_rtr)
{
tfi |= CAN_TFI_RTR;
}
/* Set the FF bit in the TFI register if this message should be sent with
* the extended frame format (and 29-bit extened ID).
*/
#ifdef CONFIG_CAN_EXTID
if (msg->cm_hdr.ch_extid)
{
/* The provided ID should be 29 bits */
DEBUGASSERT((tid & ~CAN_TID_ID29_MASK) == 0);
tfi |= CAN_TFI_FF;
}
else
#endif
{
/* The provided ID should be 11 bits */
DEBUGASSERT((tid & ~CAN_TID_ID11_MASK) == 0);
}
flags = irqsave();
/* Pick a transmit buffer */
@ -927,14 +946,11 @@ static bool can_txempty(FAR struct can_dev_s *dev)
static void can_interrupt(FAR struct can_dev_s *dev)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->cd_priv;
struct can_hdr_s hdr;
uint32_t data[2];
uint32_t rfs;
uint32_t rid;
uint32_t regval;
uint16_t hdr;
uint16_t id;
uint16_t dlc;
uint16_t rtr;
/* Read the interrupt and capture register (also clearing most status bits) */
@ -956,14 +972,23 @@ static void can_interrupt(FAR struct can_dev_s *dev)
/* Construct the CAN header */
id = rid & CAN_RID_ID11_MASK;
dlc = (rfs & CAN_RFS_DLC_MASK) >> CAN_RFS_DLC_SHIFT;
rtr = ((rfs & CAN_RFS_RTR) != 0);
hdr = CAN_HDR(id, rtr, dlc);
hdr.ch_id = rid;
hdr.ch_rtr = ((rfs & CAN_RFS_RTR) != 0);
hdr.ch_dlc = (rfs & CAN_RFS_DLC_MASK) >> CAN_RFS_DLC_SHIFT;
#ifdef CONFIG_CAN_EXTID
hdr.ch_extid = ((rfs & CAN_RFS_FF) != 0);
#else
if ((rfs & CAN_RFS_FF) != 0)
{
canlldbg("ERROR: Received message with extended identifier. Dropped\n");
}
else
#endif
{
/* Process the received CAN packet */
/* Process the received CAN packet */
can_receive(dev, hdr, (uint8_t *)data);
can_receive(dev, &hdr, (uint8_t *)data);
}
}
/* Check for TX buffer 1 complete */

View File

@ -367,8 +367,8 @@
#define CAN_TIR_TXRQ (1 << 0) /* Bit 0: Transmit Mailbox Request */
#define CAN_TIR_RTR (1 << 1) /* Bit 1: Remote Transmission Request */
#define CAN_TIR_IDE (1 << 2) /* Bit 2: Identifier Extension */
#define CAN_TIR_EXID_SHIFT (3) /* Bit 3-20: Extended Identifier */
#define CAN_TIR_EXID_MASK (0x0003ffff << CAN_TIR_EXID_SHIFT)
#define CAN_TIR_EXID_SHIFT (3) /* Bit 3-31: Extended Identifier */
#define CAN_TIR_EXID_MASK (0x1fffffff << CAN_TIR_EXID_SHIFT)
#define CAN_TIR_STID_SHIFT (21) /* Bits 21-31: Standard Identifier */
#define CAN_TIR_STID_MASK (0x07ff << CAN_TIR_STID_SHIFT)
@ -406,8 +406,8 @@
#define CAN_RIR_RTR (1 << 1) /* Bit 1: Remote Transmission Request */
#define CAN_RIR_IDE (1 << 2) /* Bit 2: Identifier Extension */
#define CAN_RIR_EXID_SHIFT (3) /* Bit 3-20: Extended Identifier */
#define CAN_RIR_EXID_MASK (0x0003ffff << CAN_RIR_EXID_SHIFT)
#define CAN_RIR_EXID_SHIFT (3) /* Bit 3-31: Extended Identifier */
#define CAN_RIR_EXID_MASK (0x1fffffff << CAN_RIR_EXID_SHIFT)
#define CAN_RIR_STID_SHIFT (21) /* Bits 21-31: Standard Identifier */
#define CAN_RIR_STID_MASK (0x07ff << CAN_RIR_STID_SHIFT)

View File

@ -783,8 +783,7 @@ static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
int dlc;
int txmb;
canllvdbg("CAN%d ID: %d DLC: %d\n",
priv->port, CAN_ID(msg->cm_hdr), CAN_DLC(msg->cm_hdr));
canllvdbg("CAN%d ID: %d DLC: %d\n", priv->port, msg->cm_hdr.ch_id, msg->cm_hdr.ch_dlc);
/* Select one empty transmit mailbox */
@ -813,20 +812,29 @@ static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
regval &= ~(CAN_TIR_TXRQ | CAN_TIR_RTR | CAN_TIR_IDE | CAN_TIR_EXID_MASK | CAN_TIR_STID_MASK);
can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
/* Set up the ID. Only standard (11-bit) CAN identifiers are supported
* (the STM32 supports extended, 29-bit identifiers, but this method does
* not).
*
* Get the 11-bit identifier from the header bits 0-7 and 13-15.
*/
/* Set up the ID, standard 11-bit or extended 29-bit. */
#ifdef CONFIG_CAN_EXTID
regval &= ~CAN_TIR_EXID_MASK;
if (msg->cm_hdr.ch_extid)
{
DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 29));
regval |= (msg->cm_hdr.ch_id << CAN_TIR_EXID_SHIFT) | CAN_TIR_IDE;
}
else
{
DEBUGASSERT(msg->cm_hdr.ch_id < (1 << 11));
regval |= msg->cm_hdr.ch_id << CAN_TIR_STID_SHIFT;
}
#else
regval &= ~CAN_TIR_STID_MASK;
regval |= (uint32_t)CAN_ID(msg->cm_hdr) << CAN_TIR_STID_SHIFT;
regval |= (uint32_t)msg->cm_hdr.ch_id << CAN_TIR_STID_SHIFT;
#endif
can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
/* Set up the DLC */
dlc = CAN_DLC(msg->cm_hdr);
dlc = msg->cm_hdr.ch_dlc;
regval = can_getreg(priv, STM32_CAN_TDTR_OFFSET(txmb));
regval &= ~(CAN_TDTR_DLC_MASK | CAN_TDTR_TGT);
regval |= (uint32_t)dlc << CAN_TDTR_DLC_SHIFT;
@ -989,12 +997,10 @@ static int can_rx0interrupt(int irq, void *context)
{
FAR struct can_dev_s *dev = NULL;
FAR struct stm32_can_s *priv;
struct can_hdr_s hdr;
uint8_t data[CAN_MAXDATALEN];
uint32_t regval;
int npending;
int id;
int rtr;
int dlc;
int ret;
#if defined(CONFIG_STM32_CAN1) && defined(CONFIG_STM32_CAN2)
@ -1029,9 +1035,21 @@ static int can_rx0interrupt(int irq, void *context)
can_dumpmbregs(priv, "RX0 interrupt");
/* Get the CAN identifier. Only standard 11-bit IDs are supported */
/* Get the CAN identifier. */
regval = can_getreg(priv, STM32_CAN_RI0R_OFFSET);
#ifdef CONFIG_CAN_EXTID
if ((regval & CAN_RIR_IDE) != 0)
{
hdr.ch_id = (regval & CAN_RIR_EXID_MASK) >> CAN_RIR_EXID_SHIFT;
hdr.ch_extid = true;
}
else
{
hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
hdr.ch_extid = false;
}
#else
if ((regval & CAN_RIR_IDE) != 0)
{
canlldbg("ERROR: Received message with extended identifier. Dropped\n");
@ -1039,16 +1057,17 @@ static int can_rx0interrupt(int irq, void *context)
goto errout;
}
id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
hdr.ch_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
#endif
/* Get the Remote Transmission Request (RTR) */
/* Extract the RTR bit */
rtr = (regval & CAN_RIR_RTR) != 0 ? 1 : 0;
hdr.ch_rtr = (regval & CAN_RIR_RTR) != 0 ? true : false;
/* Get the DLC */
regval = can_getreg(priv, STM32_CAN_RDT0R_OFFSET);
dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT;
regval = can_getreg(priv, STM32_CAN_RDT0R_OFFSET);
hdr.ch_dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT;
/* Save the message data */
@ -1066,11 +1085,13 @@ static int can_rx0interrupt(int irq, void *context)
/* Provide the data to the upper half driver */
ret = can_receive(dev, (uint16_t)CAN_HDR(id, rtr, dlc), data);
ret = can_receive(dev, &hdr, data);
/* Release the FIFO0 */
#ifndef CONFIG_CAN_EXTID
errout:
#endif
regval = can_getreg(priv, STM32_CAN_RF0R_OFFSET);
regval |= CAN_RFR_RFOM;
can_putreg(priv, STM32_CAN_RF0R_OFFSET, regval);