Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
Diff: targets/TARGET_STM/can_api.c
- Revision:
- 174:b96e65c34a4d
- Parent:
- 172:7d866c31b3c5
--- a/targets/TARGET_STM/can_api.c Fri Sep 15 14:59:18 2017 +0100
+++ b/targets/TARGET_STM/can_api.c Mon Oct 02 15:33:19 2017 +0100
@@ -25,10 +25,21 @@
#include <math.h>
#include <string.h>
-static CAN_HandleTypeDef CanHandle;
static uint32_t can_irq_ids[CAN_NUM] = {0};
static can_irq_handler irq_handler;
+static void can_registers_init(can_t *obj)
+{
+ if (HAL_CAN_Init(&obj->CanHandle) != HAL_OK) {
+ error("Cannot initialize CAN");
+ }
+
+ // Set initial CAN frequency to specified frequency
+ if (can_frequency(obj, obj->hz) != 1) {
+ error("Can frequency could not be set\n");
+ }
+}
+
void can_init(can_t *obj, PinName rd, PinName td)
{
can_init_freq(obj, rd, td, 100000);
@@ -38,16 +49,16 @@
{
CANName can_rd = (CANName)pinmap_peripheral(rd, PinMap_CAN_RD);
CANName can_td = (CANName)pinmap_peripheral(td, PinMap_CAN_TD);
+ CANName can = (CANName)pinmap_merge(can_rd, can_td);
- obj->can = (CANName)pinmap_merge(can_rd, can_td);
- MBED_ASSERT((int)obj->can != NC);
+ MBED_ASSERT((int)can != NC);
- if (obj->can == CAN_1) {
+ if (can == CAN_1) {
__HAL_RCC_CAN1_CLK_ENABLE();
obj->index = 0;
}
#if defined(CAN2_BASE) && (CAN_NUM == 2)
- else if (obj->can == CAN_2) {
+ else if (can == CAN_2) {
__HAL_RCC_CAN1_CLK_ENABLE(); // needed to set filters
__HAL_RCC_CAN2_CLK_ENABLE();
obj->index = 1;
@@ -67,33 +78,30 @@
pin_mode(td, PullUp);
}
- CanHandle.Instance = (CAN_TypeDef *)(obj->can);
+ /* Use default values for rist init */
+ obj->CanHandle.Instance = (CAN_TypeDef *)can;
+ obj->CanHandle.Init.TTCM = DISABLE;
+ obj->CanHandle.Init.ABOM = DISABLE;
+ obj->CanHandle.Init.AWUM = DISABLE;
+ obj->CanHandle.Init.NART = DISABLE;
+ obj->CanHandle.Init.RFLM = DISABLE;
+ obj->CanHandle.Init.TXFP = DISABLE;
+ obj->CanHandle.Init.Mode = CAN_MODE_NORMAL;
+ obj->CanHandle.Init.SJW = CAN_SJW_1TQ;
+ obj->CanHandle.Init.BS1 = CAN_BS1_6TQ;
+ obj->CanHandle.Init.BS2 = CAN_BS2_8TQ;
+ obj->CanHandle.Init.Prescaler = 2;
- CanHandle.Init.TTCM = DISABLE;
- CanHandle.Init.ABOM = DISABLE;
- CanHandle.Init.AWUM = DISABLE;
- CanHandle.Init.NART = DISABLE;
- CanHandle.Init.RFLM = DISABLE;
- CanHandle.Init.TXFP = DISABLE;
- CanHandle.Init.Mode = CAN_MODE_NORMAL;
- CanHandle.Init.SJW = CAN_SJW_1TQ;
- CanHandle.Init.BS1 = CAN_BS1_6TQ;
- CanHandle.Init.BS2 = CAN_BS2_8TQ;
- CanHandle.Init.Prescaler = 2;
+ /* Store frequency to be restored in case of reset */
+ obj->hz = hz;
- if (HAL_CAN_Init(&CanHandle) != HAL_OK) {
- error("Cannot initialize CAN");
- }
+ can_registers_init(obj);
- // Set initial CAN frequency to specified frequency
- if (can_frequency(obj, hz) != 1) {
- error("Can frequency could not be set\n");
- }
-
- uint32_t filter_number = (obj->can == CAN_1) ? 0 : 14;
+ uint32_t filter_number = (can == CAN_1) ? 0 : 14;
can_filter(obj, 0, 0, CANStandard, filter_number);
}
+
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
{
irq_handler = handler;
@@ -102,7 +110,7 @@
void can_irq_free(can_t *obj)
{
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
can->IER &= ~(CAN_IT_FMP0 | CAN_IT_FMP1 | CAN_IT_TME | \
CAN_IT_ERR | CAN_IT_EPV | CAN_IT_BOF);
@@ -111,14 +119,15 @@
void can_free(can_t *obj)
{
+ CANName can = (CANName) obj->CanHandle.Instance;
// Reset CAN and disable clock
- if (obj->can == CAN_1) {
+ if (can == CAN_1) {
__HAL_RCC_CAN1_FORCE_RESET();
__HAL_RCC_CAN1_RELEASE_RESET();
__HAL_RCC_CAN1_CLK_DISABLE();
}
#if defined(CAN2_BASE) && (CAN_NUM == 2)
- if (obj->can == CAN_2) {
+ if (can == CAN_2) {
__HAL_RCC_CAN2_FORCE_RESET();
__HAL_RCC_CAN2_RELEASE_RESET();
__HAL_RCC_CAN2_CLK_DISABLE();
@@ -196,7 +205,7 @@
{
int pclk = HAL_RCC_GetPCLK1Freq();
int btr = can_speed(pclk, (unsigned int)f, 1);
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
uint32_t tickstart = 0;
int status = 1;
@@ -211,7 +220,11 @@
}
}
if (status != 0) {
- can->BTR = btr;
+ /* Do not erase all BTR registers (e.g. silent mode), only the
+ * ones calculated in can_speed */
+ can->BTR &= ~(CAN_BTR_TS2 | CAN_BTR_TS1 | CAN_BTR_SJW | CAN_BTR_BRP);
+ can->BTR |= btr;
+
can->MCR &= ~(uint32_t)CAN_MCR_INRQ;
/* Get tick */
tickstart = HAL_GetTick();
@@ -236,7 +249,7 @@
int can_write(can_t *obj, CAN_Message msg, int cc)
{
uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
/* Select one empty transmit mailbox */
if ((can->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
@@ -279,7 +292,7 @@
{
//handle is the FIFO number
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
// check FPM0 which holds the pending message count in FIFO 0
// if no message is pending, return 0
@@ -324,46 +337,61 @@
void can_reset(can_t *obj)
{
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
+
+ /* Reset IP and delete errors */
can->MCR |= CAN_MCR_RESET;
can->ESR = 0x0;
+
+ /* restore registers state as saved in obj context */
+ can_registers_init(obj);
}
unsigned char can_rderror(can_t *obj)
{
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
return (can->ESR >> 24) & 0xFF;
}
unsigned char can_tderror(can_t *obj)
{
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
return (can->ESR >> 16) & 0xFF;
}
void can_monitor(can_t *obj, int silent)
{
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
-
- can->MCR |= CAN_MCR_INRQ ;
- while ((can->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
+ CanMode mode = MODE_NORMAL;
+ /* Update current state w/ or w/o silent */
+ if(silent) {
+ switch (obj->CanHandle.Init.Mode) {
+ case CAN_MODE_LOOPBACK:
+ case CAN_MODE_SILENT_LOOPBACK:
+ mode = MODE_TEST_SILENT;
+ break;
+ default:
+ mode = MODE_SILENT;
+ break;
+ }
+ } else {
+ switch (obj->CanHandle.Init.Mode) {
+ case CAN_MODE_LOOPBACK:
+ case CAN_MODE_SILENT_LOOPBACK:
+ mode = MODE_TEST_LOCAL;
+ break;
+ default:
+ mode = MODE_NORMAL;
+ break;
+ }
}
- if (silent) {
- can->BTR |= ((uint32_t)1 << 31);
- } else {
- can->BTR &= ~((uint32_t)1 << 31);
- }
-
- can->MCR &= ~(uint32_t)CAN_MCR_INRQ;
- while ((can->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) {
- }
+ can_mode(obj, mode);
}
int can_mode(can_t *obj, CanMode mode)
{
int success = 0;
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
can->MCR |= CAN_MCR_INRQ ;
while ((can->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
@@ -371,21 +399,25 @@
switch (mode) {
case MODE_NORMAL:
+ obj->CanHandle.Init.Mode = CAN_MODE_NORMAL;
can->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM);
success = 1;
break;
case MODE_SILENT:
+ obj->CanHandle.Init.Mode = CAN_MODE_SILENT;
can->BTR |= CAN_BTR_SILM;
can->BTR &= ~CAN_BTR_LBKM;
success = 1;
break;
case MODE_TEST_GLOBAL:
case MODE_TEST_LOCAL:
+ obj->CanHandle.Init.Mode = CAN_MODE_LOOPBACK;
can->BTR |= CAN_BTR_LBKM;
can->BTR &= ~CAN_BTR_SILM;
success = 1;
break;
case MODE_TEST_SILENT:
+ obj->CanHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
can->BTR |= (CAN_BTR_SILM | CAN_BTR_LBKM);
success = 1;
break;
@@ -407,7 +439,6 @@
// filter for CANAny format cannot be configured for STM32
if ((format == CANStandard) || (format == CANExtended)) {
- CanHandle.Instance = (CAN_TypeDef *)(obj->can);
CAN_FilterConfTypeDef sFilterConfig;
sFilterConfig.FilterNumber = handle;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
@@ -429,7 +460,7 @@
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14 + handle;
- HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig);
+ HAL_CAN_ConfigFilter(&obj->CanHandle, &sFilterConfig);
retval = handle;
}
return retval;
@@ -438,6 +469,7 @@
static void can_irq(CANName name, int id)
{
uint32_t tmp1 = 0, tmp2 = 0, tmp3 = 0;
+ CAN_HandleTypeDef CanHandle;
CanHandle.Instance = (CAN_TypeDef *)name;
if (__HAL_CAN_GET_IT_SOURCE(&CanHandle, CAN_IT_TME)) {
@@ -535,13 +567,12 @@
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
{
-
- CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
+ CAN_TypeDef *can = obj->CanHandle.Instance;
IRQn_Type irq_n = (IRQn_Type)0;
uint32_t vector = 0;
uint32_t ier;
- if (obj->can == CAN_1) {
+ if ((CANName) can == CAN_1) {
switch (type) {
case IRQ_RX:
ier = CAN_IT_FMP0;
@@ -573,7 +604,7 @@
}
}
#if defined(CAN2_BASE) && (CAN_NUM == 2)
- else if (obj->can == CAN_2) {
+ else if ((CANName) can == CAN_2) {
switch (type) {
case IRQ_RX:
ier = CAN_IT_FMP0;
