mbed
Fork of mbed-dev by
Diff: targets/TARGET_STM/can_api.c
- Revision:
- 175:b96e65c34a4d
- Parent:
- 173:7d866c31b3c5
- Child:
- 179:79309dc6340a
diff -r e131a1973e81 -r b96e65c34a4d targets/TARGET_STM/can_api.c --- 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;