Here is a patch to
-remove a wrong comment in atmel mcan ioctl -add ioctls to set/get bit timing in stm32l4 -add ioctl hooks to allow future management of can id filters.
This commit is contained in:
parent
951c71041d
commit
8b1a607671
@ -2602,8 +2602,6 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
break;
|
||||
}
|
||||
|
||||
/* No CAN ioctls are supported */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -6333,21 +6333,21 @@ config STM32_USB_ITRMP
|
||||
F3 family and selects the use of the dedicated USB interrupts.
|
||||
|
||||
menu "CAN driver configuration"
|
||||
depends on STM32_CAN1 || STM32_CAN2
|
||||
depends on STM32_CAN
|
||||
|
||||
config CAN1_BAUD
|
||||
int "CAN1 BAUD"
|
||||
default 250000
|
||||
depends on STM32_CAN1
|
||||
---help---
|
||||
CAN1 BAUD rate. Required if STM32_CAN1 is defined.
|
||||
CAN1 BAUD rate. Required if CONFIG_STM32_CAN1 is defined.
|
||||
|
||||
config CAN2_BAUD
|
||||
int "CAN2 BAUD"
|
||||
default 250000
|
||||
depends on STM32_CAN2
|
||||
---help---
|
||||
CAN2 BAUD rate. Required if STM32_CAN2 is defined.
|
||||
CAN2 BAUD rate. Required if CONFIG_STM32_CAN2 is defined.
|
||||
|
||||
config CAN_TSEG1
|
||||
int "TSEG1 quanta"
|
||||
@ -6360,6 +6360,15 @@ config CAN_TSEG2
|
||||
default 7
|
||||
---help---
|
||||
The number of CAN time quanta in segment 2. Default: 7
|
||||
|
||||
config STM32_CAN_REGDEBUG
|
||||
bool "CAN Register level debug"
|
||||
depends on DEBUG_CAN_INFO
|
||||
default n
|
||||
---help---
|
||||
Output detailed register-level CAN device debug information.
|
||||
Requires also CONFIG_DEBUG_CAN_INFO.
|
||||
|
||||
endmenu
|
||||
|
||||
if STM32_LTDC
|
||||
|
@ -871,7 +871,7 @@ config CAN1_BAUD
|
||||
default 250000
|
||||
depends on STM32L4_CAN1
|
||||
---help---
|
||||
CAN1 BAUD rate. Required if STM32L4_CAN1 is defined.
|
||||
CAN1 BAUD rate. Required if CONFIG_STM32L4_CAN1 is defined.
|
||||
|
||||
config CAN_TSEG1
|
||||
int "TSEG1 quanta"
|
||||
@ -884,6 +884,15 @@ config CAN_TSEG2
|
||||
default 7
|
||||
---help---
|
||||
The number of CAN time quanta in segment 2. Default: 7
|
||||
|
||||
config STM32L4_CAN_REGDEBUG
|
||||
bool "CAN Register level debug"
|
||||
depends on DEBUG_CAN_INFO
|
||||
default n
|
||||
---help---
|
||||
Output detailed register-level CAN device debug information.
|
||||
Requires also CONFIG_DEBUG_CAN_INFO.
|
||||
|
||||
endmenu
|
||||
|
||||
endif # ARCH_CHIP_STM32L4
|
||||
|
@ -83,7 +83,7 @@
|
||||
#define CAN_BIT_QUANTA (CONFIG_CAN_TSEG1 + CONFIG_CAN_TSEG2 + 1)
|
||||
|
||||
#ifndef CONFIG_DEBUG_CAN_INFO
|
||||
# undef CONFIG_STM32_CAN_REGDEBUG
|
||||
# undef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
@ -107,14 +107,14 @@ struct stm32l4_can_s
|
||||
|
||||
/* CAN Register access */
|
||||
|
||||
static uint32_t can_getreg(struct stm32l4_can_s *priv, int offset);
|
||||
static uint32_t can_getfreg(struct stm32l4_can_s *priv, int offset);
|
||||
static void can_putreg(struct stm32l4_can_s *priv, int offset, uint32_t value);
|
||||
static void can_putfreg(struct stm32l4_can_s *priv, int offset, uint32_t value);
|
||||
#ifdef CONFIG_STM32_CAN_REGDEBUG
|
||||
static void can_dumpctrlregs(struct stm32l4_can_s *priv, FAR const char *msg);
|
||||
static void can_dumpmbregs(struct stm32l4_can_s *priv, FAR const char *msg);
|
||||
static void can_dumpfiltregs(struct stm32l4_can_s *priv, FAR const char *msg);
|
||||
static uint32_t can_getreg(FAR struct stm32l4_can_s *priv, int offset);
|
||||
static uint32_t can_getfreg(FAR struct stm32l4_can_s *priv, int offset);
|
||||
static void can_putreg(FAR struct stm32l4_can_s *priv, int offset, uint32_t value);
|
||||
static void can_putfreg(FAR struct stm32l4_can_s *priv, int offset, uint32_t value);
|
||||
#ifdef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
static void can_dumpctrlregs(FAR struct stm32l4_can_s *priv, FAR const char *msg);
|
||||
static void can_dumpmbregs(FAR struct stm32l4_can_s *priv, FAR const char *msg);
|
||||
static void can_dumpfiltregs(FAR struct stm32l4_can_s *priv, FAR const char *msg);
|
||||
#else
|
||||
# define can_dumpctrlregs(priv,msg)
|
||||
# define can_dumpmbregs(priv,msg)
|
||||
@ -136,14 +136,23 @@ static bool can_txempty(FAR struct can_dev_s *dev);
|
||||
|
||||
/* CAN interrupt handling */
|
||||
|
||||
static int can_rx0interrupt(int irq, void *context);
|
||||
static int can_txinterrupt(int irq, void *context);
|
||||
static int can_rx0interrupt(int irq, FAR void *context);
|
||||
static int can_txinterrupt(int irq, FAR void *context);
|
||||
|
||||
/* Initialization */
|
||||
|
||||
static int can_bittiming(struct stm32l4_can_s *priv);
|
||||
static int can_cellinit(struct stm32l4_can_s *priv);
|
||||
static int can_filterinit(struct stm32l4_can_s *priv);
|
||||
static int can_enterinitmode(FAR struct stm32l4_can_s *priv);
|
||||
static int can_exitinitmode(FAR struct stm32l4_can_s *priv);
|
||||
static int can_bittiming(FAR struct stm32l4_can_s *priv);
|
||||
static int can_cellinit(FAR struct stm32l4_can_s *priv);
|
||||
static int can_filterinit(FAR struct stm32l4_can_s *priv);
|
||||
|
||||
/* Filtering (todo) */
|
||||
|
||||
static int stm32l4_can_addextfilter(FAR struct stm32l4_can_s *priv, FAR struct canioc_extfilter_s *arg);
|
||||
static int stm32l4_can_delextfilter(FAR struct stm32l4_can_s *priv, int arg);
|
||||
static int stm32l4_can_addstdfilter(FAR struct stm32l4_can_s *priv, FAR struct canioc_stdfilter_s *arg);
|
||||
static int stm32l4_can_delstdfilter(FAR struct stm32l4_can_s *priv, int arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@ -201,7 +210,7 @@ static struct can_dev_s g_can1dev =
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_CAN_REGDEBUG
|
||||
#ifdef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
static uint32_t can_vgetreg(uint32_t addr)
|
||||
{
|
||||
static uint32_t prevaddr = 0;
|
||||
@ -255,23 +264,23 @@ static uint32_t can_vgetreg(uint32_t addr)
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint32_t can_getreg(struct stm32l4_can_s *priv, int offset)
|
||||
static uint32_t can_getreg(FAR struct stm32l4_can_s *priv, int offset)
|
||||
{
|
||||
return can_vgetreg(priv->base + offset);
|
||||
}
|
||||
|
||||
static uint32_t can_getfreg(struct stm32l4_can_s *priv, int offset)
|
||||
static uint32_t can_getfreg(FAR struct stm32l4_can_s *priv, int offset)
|
||||
{
|
||||
return can_vgetreg(priv->fbase + offset);
|
||||
}
|
||||
|
||||
#else
|
||||
static uint32_t can_getreg(struct stm32l4_can_s *priv, int offset)
|
||||
static uint32_t can_getreg(FAR struct stm32l4_can_s *priv, int offset)
|
||||
{
|
||||
return getreg32(priv->base + offset);
|
||||
}
|
||||
|
||||
static uint32_t can_getfreg(struct stm32l4_can_s *priv, int offset)
|
||||
static uint32_t can_getfreg(FAR struct stm32l4_can_s *priv, int offset)
|
||||
{
|
||||
return getreg32(priv->fbase + offset);
|
||||
}
|
||||
@ -295,7 +304,7 @@ static uint32_t can_getfreg(struct stm32l4_can_s *priv, int offset)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_CAN_REGDEBUG
|
||||
#ifdef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
static void can_vputreg(uint32_t addr, uint32_t value)
|
||||
{
|
||||
/* Show the register value being written */
|
||||
@ -307,23 +316,23 @@ static void can_vputreg(uint32_t addr, uint32_t value)
|
||||
putreg32(value, addr);
|
||||
}
|
||||
|
||||
static void can_putreg(struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
static void can_putreg(FAR struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
{
|
||||
can_vputreg(priv->base + offset, value);
|
||||
}
|
||||
|
||||
static void can_putfreg(struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
static void can_putfreg(FAR struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
{
|
||||
can_vputreg(priv->fbase + offset, value);
|
||||
}
|
||||
|
||||
#else
|
||||
static void can_putreg(struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
static void can_putreg(FAR struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
{
|
||||
putreg32(value, priv->base + offset);
|
||||
}
|
||||
|
||||
static void can_putfreg(struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
static void can_putfreg(FAR struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
{
|
||||
putreg32(value, priv->fbase + offset);
|
||||
}
|
||||
@ -343,8 +352,8 @@ static void can_putfreg(struct stm32l4_can_s *priv, int offset, uint32_t value)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_CAN_REGDEBUG
|
||||
static void can_dumpctrlregs(struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
#ifdef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
static void can_dumpctrlregs(FAR struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
@ -387,8 +396,8 @@ static void can_dumpctrlregs(struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_CAN_REGDEBUG
|
||||
static void can_dumpmbregs(struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
#ifdef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
static void can_dumpmbregs(FAR struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
@ -447,8 +456,8 @@ static void can_dumpmbregs(struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32_CAN_REGDEBUG
|
||||
static void can_dumpfiltregs(struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
#ifdef CONFIG_STM32L4_CAN_REGDEBUG
|
||||
static void can_dumpfiltregs(FAR struct stm32l4_can_s *priv, FAR const char *msg)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -724,9 +733,241 @@ static void can_txint(FAR struct can_dev_s *dev, bool enable)
|
||||
|
||||
static int can_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
{
|
||||
/* No CAN ioctls are supported */
|
||||
FAR struct stm32l4_can_s *priv;
|
||||
int ret = -ENOTTY;
|
||||
|
||||
return -ENOTTY;
|
||||
caninfo("cmd=%04x arg=%lu\n", cmd, arg);
|
||||
|
||||
DEBUGASSERT(dev && dev->cd_priv);
|
||||
priv = dev->cd_priv;
|
||||
|
||||
/* Handle the command */
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
/* CANIOC_GET_BITTIMING:
|
||||
* Description: Return the current bit timing settings
|
||||
* Argument: A pointer to a write-able instance of struct
|
||||
* canioc_bittiming_s in which current bit timing values
|
||||
* will be returned.
|
||||
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
|
||||
* is returned with the errno variable set to indicate the
|
||||
* nature of the error.
|
||||
* Dependencies: None
|
||||
*/
|
||||
|
||||
case CANIOC_GET_BITTIMING:
|
||||
{
|
||||
FAR struct canioc_bittiming_s *bt =
|
||||
(FAR struct canioc_bittiming_s *)arg;
|
||||
uint32_t regval;
|
||||
uint32_t brp;
|
||||
|
||||
DEBUGASSERT(bt != NULL);
|
||||
regval = can_getreg(priv, STM32L4_CAN_BTR_OFFSET);
|
||||
bt->bt_sjw = ((regval & CAN_BTR_SJW_MASK) >> CAN_BTR_SJW_SHIFT) + 1;
|
||||
bt->bt_tseg1 = ((regval & CAN_BTR_TS1_MASK) >> CAN_BTR_TS1_SHIFT) + 1;
|
||||
bt->bt_tseg2 = ((regval & CAN_BTR_TS2_MASK) >> CAN_BTR_TS2_SHIFT) + 1;
|
||||
|
||||
brp = ((regval & CAN_BTR_BRP_MASK) >> CAN_BTR_BRP_SHIFT) + 1;
|
||||
bt->bt_baud = STM32L4_PCLK1_FREQUENCY /
|
||||
(brp * (bt->bt_tseg1 + bt->bt_tseg2 + 1));
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
/* CANIOC_SET_BITTIMING:
|
||||
* Description: Set new current bit timing values
|
||||
* Argument: A pointer to a read-able instance of struct
|
||||
* canioc_bittiming_s in which the new bit timing values
|
||||
* are provided.
|
||||
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
|
||||
* is returned with the errno variable set to indicate the
|
||||
* nature of the error.
|
||||
* Dependencies: None
|
||||
*
|
||||
* REVISIT: There is probably a limitation here: If there are multiple
|
||||
* threads trying to send CAN packets, when one of these threads reconfigures
|
||||
* the bitrate, the MCAN hardware will be reset and the context of operation
|
||||
* will be lost. Hence, this IOCTL can only safely be executed in quiescent
|
||||
* time periods.
|
||||
*/
|
||||
|
||||
case CANIOC_SET_BITTIMING:
|
||||
{
|
||||
FAR const struct canioc_bittiming_s *bt =
|
||||
(FAR const struct canioc_bittiming_s *)arg;
|
||||
uint32_t brp;
|
||||
uint32_t can_bit_quanta;
|
||||
uint32_t tmp;
|
||||
|
||||
DEBUGASSERT(bt != NULL);
|
||||
DEBUGASSERT(bt->bt_baud < STM32L4_PCLK1_FREQUENCY);
|
||||
DEBUGASSERT(bt->bt_sjw > 0 && bt->bt_sjw <= 4);
|
||||
DEBUGASSERT(bt->bt_tseg1 > 0 && bt->bt_tseg1 <= 16);
|
||||
DEBUGASSERT(bt->bt_tseg2 > 0 && bt->bt_tseg2 <= 8);
|
||||
|
||||
/* Extract bit timing data */
|
||||
/* tmp is in clocks per bit time */
|
||||
|
||||
tmp = STM32L4_PCLK1_FREQUENCY / bt->bt_baud;
|
||||
|
||||
/* This value is dynamic as requested by user */
|
||||
|
||||
can_bit_quanta = bt->bt_tseg1 + bt->bt_tseg2 + 1;
|
||||
|
||||
if (tmp < can_bit_quanta)
|
||||
{
|
||||
#if 0
|
||||
/* At the smallest brp value (1), there are already too few
|
||||
* bit times (PCLK1 / baud) to meet our goal. brp must be one
|
||||
* and we need make some reasonable guesses about ts1 and ts2.
|
||||
*/
|
||||
|
||||
brp = 1;
|
||||
|
||||
/* In this case, we have to guess a good value for ts1 and ts2 */
|
||||
|
||||
tseg1 = (tmp - 1) >> 1; /* cut available time in half */
|
||||
tseg2 = tmp - tseg1 - 1; /* ts2 uses the rest minus one */
|
||||
|
||||
/* if we can, try to approximate the CAN requirements,
|
||||
* which are not exactly "cut baud time in half"
|
||||
*/
|
||||
|
||||
if (tseg1 == tseg2 && tseg1 > 1 && tseg2 < CAN_BTR_TSEG2_MAX)
|
||||
{
|
||||
tseg1--;
|
||||
tseg2++;
|
||||
}
|
||||
#else
|
||||
ret = -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Otherwise, nquanta is can_bit_quanta, ts1 and ts2 are provided
|
||||
* by the user and we calculate brp to achieve can_bit_quanta
|
||||
* quanta in the bit time
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
brp = (tmp + (can_bit_quanta/2)) / can_bit_quanta;
|
||||
DEBUGASSERT(brp >= 1 && brp <= CAN_BTR_BRP_MAX);
|
||||
}
|
||||
|
||||
caninfo("TS1: %d TS2: %d BRP: %d\n", bt->bt_tseg1, bt->bt_tseg2, brp);
|
||||
|
||||
/* Configure bit timing. This also does the following, less obvious
|
||||
* things. Unless loopback mode is enabled, it:
|
||||
*
|
||||
* - Disables silent mode.
|
||||
* - Disables loopback mode.
|
||||
*
|
||||
*/
|
||||
|
||||
tmp = ((brp - 1) << CAN_BTR_BRP_SHIFT) |
|
||||
((bt->bt_tseg1 - 1) << CAN_BTR_TS1_SHIFT) |
|
||||
((bt->bt_tseg2 - 1) << CAN_BTR_TS2_SHIFT) |
|
||||
((bt->bt_sjw - 1) << CAN_BTR_SJW_SHIFT);
|
||||
#ifdef CONFIG_CAN_LOOPBACK
|
||||
tmp |= CAN_BTR_LBKM;
|
||||
#endif
|
||||
|
||||
/* Bit timing can only be configured in init mode.
|
||||
* No registers are changed.
|
||||
*/
|
||||
|
||||
ret = can_enterinitmode(priv);
|
||||
if (ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
can_putreg(priv, STM32L4_CAN_BTR_OFFSET, tmp);
|
||||
ret = can_exitinitmode(priv);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
priv->baud = STM32L4_PCLK1_FREQUENCY / (brp * (bt->bt_tseg1 + bt->bt_tseg2 + 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_CAN_EXTID
|
||||
/* CANIOC_ADD_EXTFILTER:
|
||||
* Description: Add an address filter for a extended 29 bit
|
||||
* address.
|
||||
* Argument: A reference to struct canioc_extfilter_s
|
||||
* Returned Value: A non-negative filter ID is returned on success.
|
||||
* Otherwise -1 (ERROR) is returned with the errno
|
||||
* variable set to indicate the nature of the error.
|
||||
*/
|
||||
|
||||
case CANIOC_ADD_EXTFILTER:
|
||||
{
|
||||
DEBUGASSERT(arg != 0);
|
||||
ret = stm32l4_can_addextfilter(priv, (FAR struct canioc_extfilter_s *)arg);
|
||||
}
|
||||
break;
|
||||
|
||||
/* CANIOC_DEL_EXTFILTER:
|
||||
* Description: Remove an address filter for a standard 29 bit address.
|
||||
* Argument: The filter index previously returned by the
|
||||
* CANIOC_ADD_EXTFILTER command
|
||||
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
|
||||
* is returned with the errno variable set to indicate the
|
||||
* nature of the error.
|
||||
*/
|
||||
|
||||
case CANIOC_DEL_EXTFILTER:
|
||||
{
|
||||
DEBUGASSERT(arg <= priv->config->nextfilters);
|
||||
ret = stm32l4_can_delextfilter(priv, (int)arg);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* CANIOC_ADD_STDFILTER:
|
||||
* Description: Add an address filter for a standard 11 bit
|
||||
* address.
|
||||
* Argument: A reference to struct canioc_stdfilter_s
|
||||
* Returned Value: A non-negative filter ID is returned on success.
|
||||
* Otherwise -1 (ERROR) is returned with the errno
|
||||
* variable set to indicate the nature of the error.
|
||||
*/
|
||||
|
||||
case CANIOC_ADD_STDFILTER:
|
||||
{
|
||||
DEBUGASSERT(arg != 0);
|
||||
ret = stm32l4_can_addstdfilter(priv, (FAR struct canioc_stdfilter_s *)arg);
|
||||
}
|
||||
break;
|
||||
|
||||
/* CANIOC_DEL_STDFILTER:
|
||||
* Description: Remove an address filter for a standard 11 bit address.
|
||||
* Argument: The filter index previously returned by the
|
||||
* CANIOC_ADD_STDFILTER command
|
||||
* Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR)
|
||||
* is returned with the errno variable set to indicate the
|
||||
* nature of the error.
|
||||
*/
|
||||
|
||||
case CANIOC_DEL_STDFILTER:
|
||||
{
|
||||
DEBUGASSERT(arg <= priv->config->nstdfilters);
|
||||
ret = stm32l4_can_delstdfilter(priv, (int)arg);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Unsupported/unrecognized command */
|
||||
|
||||
default:
|
||||
canerr("ERROR: Unrecognized command: %04x\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -996,7 +1237,7 @@ static bool can_txempty(FAR struct can_dev_s *dev)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int can_rx0interrupt(int irq, void *context)
|
||||
static int can_rx0interrupt(int irq, FAR void *context)
|
||||
{
|
||||
FAR struct can_dev_s *dev = NULL;
|
||||
FAR struct stm32l4_can_s *priv;
|
||||
@ -1107,7 +1348,7 @@ errout:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int can_txinterrupt(int irq, void *context)
|
||||
static int can_txinterrupt(int irq, FAR void *context)
|
||||
{
|
||||
FAR struct can_dev_s *dev = NULL;
|
||||
FAR struct stm32l4_can_s *priv;
|
||||
@ -1227,6 +1468,7 @@ static int can_txinterrupt(int irq, void *context)
|
||||
* Tbs1 = Tq * ts1
|
||||
* Tbs2 = Tq * ts2
|
||||
* Tq = brp * Tpclk1
|
||||
* baud = Fpclk1 / (brp * (1 + ts1 + ts2)))
|
||||
*
|
||||
* Where:
|
||||
* Tpclk1 is the period of the APB1 clock (PCLK1).
|
||||
@ -1239,7 +1481,7 @@ static int can_txinterrupt(int irq, void *context)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int can_bittiming(struct stm32l4_can_s *priv)
|
||||
static int can_bittiming(FAR struct stm32l4_can_s *priv)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t brp;
|
||||
@ -1324,10 +1566,12 @@ static int can_bittiming(struct stm32l4_can_s *priv)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: can_cellinit
|
||||
* Name: can_enterinitmode
|
||||
*
|
||||
* Description:
|
||||
* CAN cell initialization
|
||||
* Put the CAN cell in Initialization mode. This only disconnects the CAN
|
||||
* peripheral, no registers are changed. The initialization mode is
|
||||
* required to change the baud rate.
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
@ -1337,27 +1581,17 @@ static int can_bittiming(struct stm32l4_can_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int can_cellinit(struct stm32l4_can_s *priv)
|
||||
static int can_enterinitmode(FAR struct stm32l4_can_s *priv)
|
||||
{
|
||||
volatile uint32_t timeout;
|
||||
uint32_t regval;
|
||||
volatile uint32_t timeout;
|
||||
int ret;
|
||||
|
||||
caninfo("CAN%d\n", priv->port);
|
||||
|
||||
/* Exit from sleep mode */
|
||||
|
||||
regval = can_getreg(priv, STM32L4_CAN_MCR_OFFSET);
|
||||
regval &= ~CAN_MCR_SLEEP;
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
|
||||
/* Configure CAN behavior. Priority driven request order, not message ID. */
|
||||
|
||||
regval |= CAN_MCR_TXFP;
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
|
||||
/* Enter initialization mode */
|
||||
|
||||
regval = can_getreg(priv, STM32L4_CAN_MCR_OFFSET);
|
||||
regval |= CAN_MCR_INRQ;
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
|
||||
@ -1382,30 +1616,29 @@ static int can_cellinit(struct stm32l4_can_s *priv)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Disable the following modes:
|
||||
*
|
||||
* - Time triggered communication mode
|
||||
* - Automatic bus-off management
|
||||
* - Automatic wake-up mode
|
||||
* - No automatic retransmission
|
||||
* - Receive FIFO locked mode
|
||||
* - Transmit FIFO priority
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
regval = can_getreg(priv, STM32L4_CAN_MCR_OFFSET);
|
||||
regval &= ~(CAN_MCR_TXFP | CAN_MCR_RFLM | CAN_MCR_NART | CAN_MCR_AWUM | CAN_MCR_ABOM | CAN_MCR_TTCM);
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
/****************************************************************************
|
||||
* Name: can_exitinitmode
|
||||
*
|
||||
* Description:
|
||||
* Put the CAN cell out of the Initialization mode (to Normal mode)
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Configure bit timing. */
|
||||
static int can_exitinitmode(FAR struct stm32l4_can_s *priv)
|
||||
{
|
||||
uint32_t regval;
|
||||
volatile uint32_t timeout;
|
||||
|
||||
ret = can_bittiming(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
canerr("ERROR: Failed to set bit timing: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Exit initialization mode */
|
||||
/* Exit Initialization mode, enter Normal mode */
|
||||
|
||||
regval = can_getreg(priv, STM32L4_CAN_MCR_OFFSET);
|
||||
regval &= ~CAN_MCR_INRQ;
|
||||
@ -1432,7 +1665,72 @@ static int can_cellinit(struct stm32l4_can_s *priv)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: can_cellinit
|
||||
*
|
||||
* Description:
|
||||
* CAN cell initialization
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int can_cellinit(FAR struct stm32l4_can_s *priv)
|
||||
{
|
||||
uint32_t regval;
|
||||
int ret;
|
||||
|
||||
caninfo("CAN%d\n", priv->port);
|
||||
|
||||
/* Exit from sleep mode */
|
||||
|
||||
regval = can_getreg(priv, STM32L4_CAN_MCR_OFFSET);
|
||||
regval &= ~CAN_MCR_SLEEP;
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
|
||||
/* Configure CAN behavior. Priority driven request order, not message ID. */
|
||||
|
||||
regval |= CAN_MCR_TXFP;
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
|
||||
ret = can_enterinitmode(priv);
|
||||
if(ret != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable the following modes:
|
||||
*
|
||||
* - Time triggered communication mode
|
||||
* - Automatic bus-off management
|
||||
* - Automatic wake-up mode
|
||||
* - No automatic retransmission
|
||||
* - Receive FIFO locked mode
|
||||
* - Transmit FIFO priority
|
||||
*/
|
||||
|
||||
regval = can_getreg(priv, STM32L4_CAN_MCR_OFFSET);
|
||||
regval &= ~(CAN_MCR_TXFP | CAN_MCR_RFLM | CAN_MCR_NART | CAN_MCR_AWUM |
|
||||
CAN_MCR_ABOM | CAN_MCR_TTCM);
|
||||
can_putreg(priv, STM32L4_CAN_MCR_OFFSET, regval);
|
||||
|
||||
/* Configure bit timing. */
|
||||
|
||||
ret = can_bittiming(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
canerr("ERROR: Failed to set bit timing: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return can_exitinitmode(priv);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1452,7 +1750,7 @@ static int can_cellinit(struct stm32l4_can_s *priv)
|
||||
* finer control of the filtering.
|
||||
*
|
||||
* There is no need to set up one filter for each CAN since STM32L4 only
|
||||
* contains one CAN devices. If one day some STM32L4 has 2 CANs, then
|
||||
* contains one CAN device. If one day some STM32L4 has 2 CANs, then
|
||||
* code will have to be imported from the STM32 port.
|
||||
*
|
||||
* 32-bit IdMask mode is configured. However, both the ID and the MASK
|
||||
@ -1467,7 +1765,7 @@ static int can_cellinit(struct stm32l4_can_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int can_filterinit(struct stm32l4_can_s *priv)
|
||||
static int can_filterinit(FAR struct stm32l4_can_s *priv)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t bitmask;
|
||||
@ -1529,6 +1827,98 @@ static int can_filterinit(struct stm32l4_can_s *priv)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_can_addextfilter
|
||||
*
|
||||
* Description:
|
||||
* Add a filter for extended CAN IDs
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
* arg - A pointer to a structure describing the filter
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-negative filter ID is returned on success.
|
||||
* Otherwise -1 (ERROR) is returned with the errno
|
||||
* set to indicate the nature of the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32l4_can_addextfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_extfilter_s *arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_can_delextfilter
|
||||
*
|
||||
* Description:
|
||||
* Remove a filter for extended CAN IDs
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
* arg - The filter index previously returned by the
|
||||
* CANIOC_ADD_EXTFILTER command
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR)
|
||||
* returned with the errno variable set to indicate the
|
||||
* of the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32l4_can_delextfilter(FAR struct stm32l4_can_s *priv, int arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_can_addextfilter
|
||||
*
|
||||
* Description:
|
||||
* Add a filter for standard CAN IDs
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
* arg - A pointer to a structure describing the filter
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-negative filter ID is returned on success.
|
||||
* Otherwise -1 (ERROR) is returned with the errno
|
||||
* set to indicate the nature of the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32l4_can_addstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_stdfilter_s *arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_can_delstdfilter
|
||||
*
|
||||
* Description:
|
||||
* Remove a filter for standard CAN IDs
|
||||
*
|
||||
* Input Parameter:
|
||||
* priv - A pointer to the private data structure for this CAN block
|
||||
* arg - The filter index previously returned by the
|
||||
* CANIOC_ADD_STDFILTER command
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. Otherwise -1 (ERROR)
|
||||
* returned with the errno variable set to indicate the
|
||||
* of the error.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32l4_can_delstdfilter(FAR struct stm32l4_can_s *priv, int arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -1549,7 +1939,7 @@ static int can_filterinit(struct stm32l4_can_s *priv)
|
||||
|
||||
FAR struct can_dev_s *stm32l4_caninitialize(int port)
|
||||
{
|
||||
struct can_dev_s *dev = NULL;
|
||||
FAR struct can_dev_s *dev = NULL;
|
||||
|
||||
caninfo("CAN%d\n", port);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user