Untested transition to interrupt-based CAN communication

This commit is contained in:
Ethan Zonca 2016-08-12 17:12:52 -04:00
parent 037e7a9c6d
commit 90be8b3524
8 changed files with 113 additions and 62 deletions

View File

@ -23,8 +23,8 @@ void can_enable(void);
void can_disable(void); void can_disable(void);
void can_set_bitrate(enum can_bitrate bitrate); void can_set_bitrate(enum can_bitrate bitrate);
void can_set_silent(uint8_t silent); void can_set_silent(uint8_t silent);
uint32_t can_tx(CanTxMsgTypeDef *tx_msg, uint32_t timeout); uint32_t can_tx(CanTxMsgTypeDef *tx_msg);
uint32_t can_rx(CanRxMsgTypeDef *rx_msg, uint32_t timeout); //uint32_t can_rx(CanRxMsgTypeDef *rx_msg, uint32_t timeout);
uint8_t is_can_msg_pending(uint8_t fifo); uint8_t is_can_msg_pending(uint8_t fifo);
#endif // _CAN_H #endif // _CAN_H

View File

@ -6,11 +6,19 @@
#define LED_BLUE_Port GPIOB #define LED_BLUE_Port GPIOB
#define LED_BLUE LED_BLUE_Port , LED_BLUE_Pin #define LED_BLUE LED_BLUE_Port , LED_BLUE_Pin
#define LED_GREEN_Pin GPIO_PIN_1
#define LED_GREEN_Port GPIOB
#define LED_GREEN LED_GREEN_Port , LED_GREEN_Pin
#define LED_DURATION 50 #define LED_DURATION 50
void led_init(); void led_init();
void led_on(void); void led_blue_blink(uint8_t numblinks);
void led_green_on(void);
void led_green_of(void);
void led_blue_on(void);
void led_process(void); void led_process(void);
#endif #endif

View File

@ -46,7 +46,7 @@
extern USBD_HandleTypeDef hUsbDeviceFS; extern USBD_HandleTypeDef hUsbDeviceFS;
/* USB_Device init function */ /* USB_Device init function */
void MX_USB_DEVICE_Init(void); void usb_init(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -3,13 +3,15 @@
// //
#include "stm32f0xx_hal.h" #include "stm32f0xx_hal.h"
#include "slcan.h"
#include "usbd_cdc_if.h"
#include "can.h" #include "can.h"
#include "led.h" #include "led.h"
CAN_HandleTypeDef hcan; static CAN_HandleTypeDef can_handle;
CAN_FilterConfTypeDef filter; static CAN_FilterConfTypeDef filter;
uint32_t prescaler; static uint32_t prescaler;
enum can_bus_state bus_state; enum can_bus_state bus_state;
@ -45,7 +47,7 @@ void can_init(void)
// default to 125 kbit/s // default to 125 kbit/s
prescaler = 48; prescaler = 48;
hcan.Instance = CAN; can_handle.Instance = CAN;
bus_state = OFF_BUS; bus_state = OFF_BUS;
} }
@ -55,21 +57,26 @@ void can_enable(void)
{ {
if (bus_state == OFF_BUS) if (bus_state == OFF_BUS)
{ {
hcan.Init.Prescaler = prescaler; can_handle.Init.Prescaler = prescaler;
hcan.Init.Mode = CAN_MODE_NORMAL; can_handle.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SJW = CAN_SJW_1TQ; can_handle.Init.SJW = CAN_SJW_1TQ;
hcan.Init.BS1 = CAN_BS1_4TQ; can_handle.Init.BS1 = CAN_BS1_4TQ;
hcan.Init.BS2 = CAN_BS2_3TQ; can_handle.Init.BS2 = CAN_BS2_3TQ;
hcan.Init.TTCM = DISABLE; can_handle.Init.TTCM = DISABLE;
hcan.Init.ABOM = DISABLE; can_handle.Init.ABOM = DISABLE;
hcan.Init.AWUM = DISABLE; can_handle.Init.AWUM = DISABLE;
hcan.Init.NART = DISABLE; can_handle.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE; can_handle.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE; can_handle.Init.TXFP = DISABLE;
hcan.pTxMsg = NULL; can_handle.pTxMsg = NULL;
HAL_CAN_Init(&hcan); HAL_CAN_Init(&can_handle);
HAL_CAN_ConfigFilter(&hcan, &filter); HAL_CAN_ConfigFilter(&can_handle, &filter);
bus_state = ON_BUS; bus_state = ON_BUS;
HAL_NVIC_SetPriority(CEC_CAN_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CEC_CAN_IRQn);
HAL_CAN_Receive_IT(&can_handle, CAN_FIFO0);
} }
} }
@ -80,8 +87,12 @@ void can_disable(void)
if (bus_state == ON_BUS) if (bus_state == ON_BUS)
{ {
// do a bxCAN reset (set RESET bit to 1) // do a bxCAN reset (set RESET bit to 1)
hcan.Instance->MCR |= CAN_MCR_RESET; can_handle.Instance->MCR |= CAN_MCR_RESET;
bus_state = OFF_BUS; bus_state = OFF_BUS;
HAL_NVIC_DisableIRQ(CEC_CAN_IRQn);
HAL_CAN_DeInit(&can_handle);
} }
HAL_GPIO_WritePin(LED_BLUE, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_BLUE, GPIO_PIN_RESET);
} }
@ -139,38 +150,48 @@ void can_set_silent(uint8_t silent)
} }
if (silent) if (silent)
{ {
hcan.Init.Mode = CAN_MODE_SILENT; can_handle.Init.Mode = CAN_MODE_SILENT;
} else { } else {
hcan.Init.Mode = CAN_MODE_NORMAL; can_handle.Init.Mode = CAN_MODE_NORMAL;
} }
} }
// Send a message on the CAN bus (blocking) // Send a message on the CAN bus (blocking)
uint32_t can_tx(CanTxMsgTypeDef *tx_msg, uint32_t timeout) uint32_t can_tx(CanTxMsgTypeDef *tx_msg)
{ {
uint32_t status; uint32_t status;
// transmit can frame // transmit can frame
hcan.pTxMsg = tx_msg; can_handle.pTxMsg = tx_msg;
status = HAL_CAN_Transmit(&hcan, timeout); status = HAL_CAN_Transmit_IT(&can_handle);
led_on(); led_blue_on();
return status; return status;
} }
// CAN rxcomplete callback TODO: Move to interrupts?
// Receive a message from the CAN bus (blocking) void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *hcan)
uint32_t can_rx(CanRxMsgTypeDef *rx_msg, uint32_t timeout)
{ {
uint32_t status; led_blue_on();
hcan.pRxMsg = rx_msg; // TODO: Store this message in a buffer and defer CDC send to main loop
CanRxMsgTypeDef* rxmsg = hcan->pRxMsg;
uint8_t msg_buf[SLCAN_MTU];
uint32_t numbytes = slcan_parse_frame(msg_buf, rxmsg);
CDC_Transmit_FS(msg_buf, numbytes);
status = HAL_CAN_Receive(&hcan, CAN_FIFO0, timeout); HAL_CAN_Receive_IT(&can_handle, CAN_FIFO0);
}
led_on(); void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef *hcan)
return status; {
}
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
//error_assert(ERR_CANBUS);
} }
@ -181,5 +202,12 @@ uint8_t is_can_msg_pending(uint8_t fifo)
{ {
return 0; return 0;
} }
return (__HAL_CAN_MSG_PENDING(&hcan, fifo) > 0); return (__HAL_CAN_MSG_PENDING(&can_handle, fifo) > 0);
}
// Return reference to CAN handle
CAN_HandleTypeDef* can_gethandle(void)
{
return &can_handle;
} }

View File

@ -23,3 +23,9 @@ void SysTick_Handler(void)
HAL_SYSTICK_IRQHandler(); HAL_SYSTICK_IRQHandler();
} }
// Handle CAN interrupts
void CEC_CAN_IRQHandler(void)
{
HAL_CAN_IRQHandler(can_gethandle());
}

View File

@ -23,8 +23,35 @@ void led_init()
} }
// Turn green LED on
void led_green_on(void)
{
HAL_GPIO_WritePin(LED_GREEN, 1);
}
// Turn green LED on
void led_green_off(void)
{
HAL_GPIO_WritePin(LED_GREEN, 0);
}
// Blink blue LED (blocking)
void led_blue_blink(uint8_t numblinks)
{
uint8_t i;
for(i=0; i<numblinks; i++)
{
HAL_GPIO_WritePin(LED_BLUE, 1);
HAL_Delay(100);
HAL_GPIO_WritePin(LED_BLUE, 0);
HAL_Delay(100);
}
}
// Attempt to turn on status LED // Attempt to turn on status LED
void led_on(void) void led_blue_on(void)
{ {
// Make sure the LED has been off for at least LED_DURATION before turning on again // Make sure the LED has been off for at least LED_DURATION before turning on again
// This prevents a solid status LED on a busy canbus // This prevents a solid status LED on a busy canbus

View File

@ -5,7 +5,6 @@
#include "stm32f0xx_hal.h" #include "stm32f0xx_hal.h"
#include "usb_device.h" #include "usb_device.h"
#include "usbd_cdc_if.h"
#include "can.h" #include "can.h"
#include "slcan.h" #include "slcan.h"
#include "system.h" #include "system.h"
@ -15,34 +14,17 @@
int main(void) int main(void)
{ {
HAL_Init(); HAL_Init();
system_init(); system_init();
can_init(); can_init();
led_init(); led_init();
MX_USB_DEVICE_Init(); usb_init();
// turn on green LED led_green_on();
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); led_blue_blink(3);
// blink red LED for test
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
CanRxMsgTypeDef rx_msg;
uint8_t msg_buf[SLCAN_MTU];
while(1) while(1)
{ {
if(is_can_msg_pending(CAN_FIFO0) && can_rx(&rx_msg, 2) == HAL_OK)
{
uint32_t numbytes = slcan_parse_frame(msg_buf, &rx_msg);
CDC_Transmit_FS(msg_buf, numbytes);
}
led_process(); led_process();
} }
} }

View File

@ -45,7 +45,7 @@
USBD_HandleTypeDef hUsbDeviceFS; USBD_HandleTypeDef hUsbDeviceFS;
/* init function */ /* init function */
void MX_USB_DEVICE_Init(void) void usb_init(void)
{ {
/* Init Device Library,Add Supported Class and Start the library*/ /* Init Device Library,Add Supported Class and Start the library*/
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS); USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);