Port STM32L4 CAN IOCTLs to STM32
This commit is contained in:
parent
613e3b0b2c
commit
d3441668ee
@ -125,6 +125,17 @@ static void stm32can_dumpfiltregs(FAR struct stm32_can_s *priv,
|
||||
# define stm32can_dumpfiltregs(priv,msg)
|
||||
#endif
|
||||
|
||||
/* Filtering (todo) */
|
||||
|
||||
static int stm32l4can_addextfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_extfilter_s *arg);
|
||||
static int stm32l4can_delextfilter(FAR struct stm32l4_can_s *priv,
|
||||
int arg);
|
||||
static int stm32l4can_addstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_stdfilter_s *arg);
|
||||
static int stm32l4can_delstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
int arg);
|
||||
|
||||
/* CAN driver methods */
|
||||
|
||||
static void stm32can_reset(FAR struct can_dev_s *dev);
|
||||
@ -786,9 +797,295 @@ static void stm32can_txint(FAR struct can_dev_s *dev, bool enable)
|
||||
|
||||
static int stm32can_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
|
||||
{
|
||||
/* No CAN ioctls are supported */
|
||||
FAR struct stm32_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 = stm32can_getreg(priv, STM32_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 = STM32_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 thenature 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;
|
||||
uint32_t regval;
|
||||
|
||||
DEBUGASSERT(bt != NULL);
|
||||
DEBUGASSERT(bt->bt_baud < STM32_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);
|
||||
|
||||
regval = stm32can_getreg(priv, STM32_CAN_BTR_OFFSET);
|
||||
|
||||
/* Extract bit timing data */
|
||||
/* tmp is in clocks per bit time */
|
||||
|
||||
tmp = STM32_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)
|
||||
{
|
||||
/* This timing is not possible */
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* 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 times
|
||||
*/
|
||||
|
||||
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. */
|
||||
|
||||
regval &= ~(CAN_BTR_BRP_MASK | CAN_BTR_TS1_MASK | CAN_BTR_TS2_MASK | CAN_BTR_SJW_MASK);
|
||||
regval |= ((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);
|
||||
|
||||
/* Bit timing can only be configured in init mode. */
|
||||
|
||||
ret = stm32can_enterinitmode(priv);
|
||||
if (ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
stm32can_putreg(priv, STM32_CAN_BTR_OFFSET, regval);
|
||||
|
||||
ret = stm32can_exitinitmode(priv);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
priv->baud = STM32_PCLK1_FREQUENCY / (brp * (bt->bt_tseg1 + bt->bt_tseg2 + 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* CANIOC_GET_CONNMODES:
|
||||
* Description: Get the current bus connection modes
|
||||
* Argument: A pointer to a write-able instance of struct
|
||||
* canioc_connmodes_s in which the new bus modes 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_CONNMODES:
|
||||
{
|
||||
FAR struct canioc_connmodes_s *bm =
|
||||
(FAR struct canioc_connmodes_s *)arg;
|
||||
uint32_t regval;
|
||||
|
||||
DEBUGASSERT(bm != NULL);
|
||||
|
||||
regval = stm32can_getreg(priv, STM32_CAN_BTR_OFFSET);
|
||||
|
||||
bm->bm_loopback = ((regval & CAN_BTR_LBKM) == CAN_BTR_LBKM);
|
||||
bm->bm_silent = ((regval & CAN_BTR_SILM) == CAN_BTR_SILM);
|
||||
ret = OK;
|
||||
break;
|
||||
}
|
||||
|
||||
/* CANIOC_SET_CONNMODES:
|
||||
* Description: Set new bus connection modes values
|
||||
* Argument: A pointer to a read-able instance of struct
|
||||
* canioc_connmodes_s in which the new bus modes
|
||||
* 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
|
||||
*/
|
||||
|
||||
case CANIOC_SET_CONNMODES:
|
||||
{
|
||||
FAR struct canioc_connmodes_s *bm =
|
||||
(FAR struct canioc_connmodes_s *)arg;
|
||||
uint32_t regval;
|
||||
|
||||
DEBUGASSERT(bm != NULL);
|
||||
|
||||
regval = stm32can_getreg(priv, STM32_CAN_BTR_OFFSET);
|
||||
|
||||
if (bm->bm_loopback)
|
||||
{
|
||||
regval |= CAN_BTR_LBKM;
|
||||
}
|
||||
else
|
||||
{
|
||||
regval &= ~CAN_BTR_LBKM;
|
||||
}
|
||||
|
||||
if (bm->bm_silent)
|
||||
{
|
||||
regval |= CAN_BTR_SILM;
|
||||
}
|
||||
else
|
||||
{
|
||||
regval &= ~CAN_BTR_SILM;
|
||||
}
|
||||
|
||||
/* This register can only be configured in init mode. */
|
||||
|
||||
ret = stm32can_enterinitmode(priv);
|
||||
if (ret != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
stm32can_putreg(priv, STM32_CAN_BTR_OFFSET, regval);
|
||||
|
||||
ret = stm32can_exitinitmode(priv);
|
||||
}
|
||||
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 = stm32can_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 = stm32can_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 = stm32can_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 = stm32can_delstdfilter(priv, (int)arg);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Unsupported/unrecognized command */
|
||||
|
||||
default:
|
||||
canerr("ERROR: Unrecognized command: %04x\n", cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1669,6 +1966,98 @@ static int stm32can_filterinit(FAR struct stm32_can_s *priv)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32can_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 stm32can_addextfilter(FAR struct stm32_can_s *priv,
|
||||
FAR struct canioc_extfilter_s *arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32can_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 stm32can_delextfilter(FAR struct stm32_can_s *priv, int arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32can_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 stm32can_addstdfilter(FAR struct stm32_can_s *priv,
|
||||
FAR struct canioc_stdfilter_s *arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32can_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 stm32can_delstdfilter(FAR struct stm32_can_s *priv, int arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -128,6 +128,17 @@ static void stm32l4can_dumpfiltregs(FAR struct stm32l4_can_s *priv,
|
||||
# define stm32l4can_dumpfiltregs(priv,msg)
|
||||
#endif
|
||||
|
||||
/* Filtering (todo) */
|
||||
|
||||
static int stm32l4can_addextfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_extfilter_s *arg);
|
||||
static int stm32l4can_delextfilter(FAR struct stm32l4_can_s *priv,
|
||||
int arg);
|
||||
static int stm32l4can_addstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_stdfilter_s *arg);
|
||||
static int stm32l4can_delstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
int arg);
|
||||
|
||||
/* CAN driver methods */
|
||||
|
||||
static void stm32l4can_reset(FAR struct can_dev_s *dev);
|
||||
@ -157,17 +168,6 @@ static int stm32l4can_bittiming(FAR struct stm32l4_can_s *priv);
|
||||
static int stm32l4can_cellinit(FAR struct stm32l4_can_s *priv);
|
||||
static int stm32l4can_filterinit(FAR struct stm32l4_can_s *priv);
|
||||
|
||||
/* Filtering (todo) */
|
||||
|
||||
static int stm32l4can_addextfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_extfilter_s *arg);
|
||||
static int stm32l4can_delextfilter(FAR struct stm32l4_can_s *priv,
|
||||
int arg);
|
||||
static int stm32l4can_addstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
FAR struct canioc_stdfilter_s *arg);
|
||||
static int stm32l4can_delstdfilter(FAR struct stm32l4_can_s *priv,
|
||||
int arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
@ -855,9 +855,9 @@ static int stm32l4can_ioctl(FAR struct can_dev_s *dev, int cmd,
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
/* Otherwise, nquanta is stm32l4can_bit_quanta, ts1 and ts2 are
|
||||
/* Otherwise, nquanta is can_bit_quanta, ts1 and ts2 are
|
||||
* provided by the user and we calculate brp to achieve
|
||||
* stm32l4can_bit_quanta quanta in the bit times
|
||||
* can_bit_quanta quanta in the bit times
|
||||
*/
|
||||
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user