From 75c812756eb5f1969597cac5912706531574ef62 Mon Sep 17 00:00:00 2001 From: Sergey Lisinchuk Date: Tue, 2 May 2017 12:30:12 +0300 Subject: [PATCH] Moved to circle buffer receive Added return statement to USBD_CDC_ReceivePacket Added USB receive error handler --- .gitignore | 1 + Inc/slcan.h | 19 +- .../Class/CDC/Src/usbd_cdc.c | 5 +- Src/main.c | 53 ++- Src/slcan.c | 365 +++++++++++------- Src/usbd_cdc_if.c | 23 +- 6 files changed, 281 insertions(+), 185 deletions(-) diff --git a/.gitignore b/.gitignore index a007fea..f430707 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build/* +MDK_ARM/* \ No newline at end of file diff --git a/Inc/slcan.h b/Inc/slcan.h index 5066824..ede6e73 100644 --- a/Inc/slcan.h +++ b/Inc/slcan.h @@ -1,11 +1,26 @@ #ifndef _SLCAN_H #define _SLCAN_H +#include + int8_t slcan_parse_frame(uint8_t *buf, CanRxMsgTypeDef *frame); -int8_t slcan_parse_str(uint8_t *buf, uint8_t len); +int8_t slcan_parse_str(uint8_t newbyte); + +typedef enum{ + GET_MSG_TYPE = 0, + GET_FRAME_STD_ID, + GET_FRAME_EXT_ID, + GET_FRAME_DATA, + GET_OPEN_COMMAND, + GET_CLOSE_COMMAND, + GET_BITRATE_COMMAND, + GET_MODE_COMMAND, + GET_FILTER_COMMAND, + GET_MASK_COMMAND +} slcan_usb2can_fsm; /* maximum rx buffer len: extended CAN frame with timestamp */ -#define SLCAN_MTU 30// (sizeof("T1111222281122334455667788EA5F\r")+1) +#define SLCAN_MTU 128// (sizeof("T1111222281122334455667788EA5F\r")+1) #define SLCAN_STD_ID_LEN 3 #define SLCAN_EXT_ID_LEN 8 diff --git a/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c index 328f9fd..46a66c0 100644 --- a/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +++ b/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c @@ -876,7 +876,7 @@ uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) if(pdev->dev_speed == USBD_SPEED_HIGH ) { /* Prepare Out endpoint to receive next packet */ - USBD_LL_PrepareReceive(pdev, + return USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer, CDC_DATA_HS_OUT_PACKET_SIZE); @@ -884,12 +884,11 @@ uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) else { /* Prepare Out endpoint to receive next packet */ - USBD_LL_PrepareReceive(pdev, + return USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, hcdc->RxBuffer, CDC_DATA_FS_OUT_PACKET_SIZE); } - return USBD_OK; } else { diff --git a/Src/main.c b/Src/main.c index c4d1534..bfa199b 100644 --- a/Src/main.c +++ b/Src/main.c @@ -63,16 +63,19 @@ static void led_init(void); /* USER CODE END PFP */ /* USER CODE BEGIN 0 */ - +uint8_t circle_buffer[SLCAN_MTU]; +uint8_t rx_point = 0; +uint8_t tx_point = 0; +uint8_t need_update; /* USER CODE END 0 */ - -volatile int i=0; int main(void) { /* USER CODE BEGIN 1 */ - + CanRxMsgTypeDef rx_msg; + uint8_t msg_buf[SLCAN_MTU]; + int8_t status; /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ @@ -99,30 +102,38 @@ int main(void) // blink red LED for test HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); - HAL_Delay(100); + HAL_Delay(100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); - HAL_Delay(100); + HAL_Delay(100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); - HAL_Delay(100); + HAL_Delay(100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); + // loop forever - CanRxMsgTypeDef rx_msg; - uint32_t status; - uint8_t msg_buf[SLCAN_MTU]; - - for (;;) { - while (!is_can_msg_pending(CAN_FIFO0)) - led_process(); - status = can_rx(&rx_msg, 3); - if (status == HAL_OK) { - status = slcan_parse_frame((uint8_t *)&msg_buf, &rx_msg); - CDC_Transmit_FS(msg_buf, status); - } - led_process(); + //Read circle buffer for commands and messages + while (!is_can_msg_pending(CAN_FIFO0)){ + if (tx_point != rx_point) { + slcan_parse_str(circle_buffer[tx_point]); + tx_point = (tx_point + 1) % SLCAN_MTU; + } + led_process(); + } + //Get CAN-messages and parse them to USB buffer + if (can_rx(&rx_msg, 0) == HAL_OK){ + status = slcan_parse_frame((uint8_t *)&msg_buf, &rx_msg); + CDC_Transmit_FS(msg_buf, status); + } + led_process(); + + //If fault has occured, try to fix this on the fly + if (need_update){ + need_update = 0; + if (USBD_CDC_ReceivePacket(&hUsbDeviceFS) != USBD_OK) need_update = 1; + } } - + /* USER CODE END 3 */ } diff --git a/Src/slcan.c b/Src/slcan.c index 243cfa7..368746d 100644 --- a/Src/slcan.c +++ b/Src/slcan.c @@ -2,17 +2,24 @@ #include "can.h" #include "slcan.h" -static uint32_t current_filter_id = 0; -static uint32_t current_filter_mask = 0; + +slcan_usb2can_fsm usb2canfsm; +CanTxMsgTypeDef frame; +uint8_t counter; +uint8_t bitrate = 9; +uint8_t mode = 0; +uint32_t current_filter_id = 0; +uint32_t current_filter_temp = 0; +uint32_t current_mask_id = 0; +uint32_t current_mask_temp = 0; int8_t slcan_parse_frame(uint8_t *buf, CanRxMsgTypeDef *frame) { uint8_t i = 0; uint8_t id_len, j; uint32_t tmp; - - for (j=0; j < SLCAN_MTU; j++) { - buf[j] = '\0'; - } + + //warning: buf has to be smaller or equal to SLCAN_MTU. Potential bug + memset(buf, '\0', SLCAN_MTU); // add character for frame type if (frame->RTR == CAN_RTR_DATA) { @@ -66,155 +73,225 @@ int8_t slcan_parse_frame(uint8_t *buf, CanRxMsgTypeDef *frame) { return i; } -int8_t slcan_parse_str(uint8_t *buf, uint8_t len) { - CanTxMsgTypeDef frame; - uint8_t i; - - // convert from ASCII (2nd character to end) - for (i = 1; i < len; i++) { - // lowercase letters - if(buf[i] >= 'a') - buf[i] = buf[i] - 'a' + 10; - // uppercase letters - else if(buf[i] >= 'A') - buf[i] = buf[i] - 'A' + 10; - // numbers - else - buf[i] = buf[i] - '0'; +slcan_usb2can_fsm parse_command_type(uint8_t command_type){ + switch (command_type){ + case 'O': + return GET_OPEN_COMMAND; + case 'C': + return GET_CLOSE_COMMAND; + case 'S': + return GET_BITRATE_COMMAND; + case 'm': + case 'M': + return GET_MODE_COMMAND; + case 'F': + return GET_FILTER_COMMAND; + case 'K': + return GET_MASK_COMMAND; + case 't': + frame.RTR = CAN_RTR_DATA; + frame.IDE = CAN_ID_STD; + return GET_FRAME_STD_ID; + case 'r': + frame.RTR = CAN_RTR_REMOTE; + frame.IDE = CAN_ID_STD; + return GET_FRAME_STD_ID; + case 'T': + frame.RTR = CAN_RTR_DATA; + frame.IDE = CAN_ID_EXT; + return GET_FRAME_EXT_ID; + case 'R': + frame.RTR = CAN_RTR_REMOTE; + frame.IDE = CAN_ID_EXT; + return GET_FRAME_EXT_ID; + default: + return GET_MSG_TYPE; } +} - if (buf[0] == 'O') { - // open channel command - can_enable(); - return 0; +uint8_t ASCII2byte(char ASCII_symbol){ + // convert from ASCII (2nd character to end) + + // lowercase letters + if (ASCII_symbol >= 'a') + return (ASCII_symbol - 'a' + 10); + // uppercase letters + else if(ASCII_symbol >= 'A') + return (ASCII_symbol - 'A' + 10); + // numbers + else if ((ASCII_symbol <= '9') && (ASCII_symbol >= '0')) + return ASCII_symbol - '0'; + else + return 0xFF; +} - } else if (buf[0] == 'C') { - // close channel command - can_disable(); - return 0; +uint8_t switch_bitrate_command(uint8_t bitrate){ + switch(bitrate) { + case 0: + can_set_bitrate(CAN_BITRATE_10K); + break; + case 1: + can_set_bitrate(CAN_BITRATE_20K); + break; + case 2: + can_set_bitrate(CAN_BITRATE_50K); + break; + case 3: + can_set_bitrate(CAN_BITRATE_100K); + break; + case 4: + can_set_bitrate(CAN_BITRATE_125K); + break; + case 5: + can_set_bitrate(CAN_BITRATE_250K); + break; + case 6: + can_set_bitrate(CAN_BITRATE_500K); + break; + case 7: + can_set_bitrate(CAN_BITRATE_750K); + break; + case 8: + can_set_bitrate(CAN_BITRATE_1000K); + break; + default: + // invalid setting + return 0xFF; + } + return 0; +} - } else if (buf[0] == 'S') { - // set bitrate command - switch(buf[1]) { - case 0: - can_set_bitrate(CAN_BITRATE_10K); - break; - case 1: - can_set_bitrate(CAN_BITRATE_20K); - break; - case 2: - can_set_bitrate(CAN_BITRATE_50K); - break; - case 3: - can_set_bitrate(CAN_BITRATE_100K); - break; - case 4: - can_set_bitrate(CAN_BITRATE_125K); - break; - case 5: - can_set_bitrate(CAN_BITRATE_250K); - break; - case 6: - can_set_bitrate(CAN_BITRATE_500K); - break; - case 7: - can_set_bitrate(CAN_BITRATE_750K); - break; - case 8: - can_set_bitrate(CAN_BITRATE_1000K); - break; - default: - // invalid setting - return -1; +int8_t slcan_parse_str(uint8_t newbyte) { + static volatile char byte; + byte = (char)newbyte; + + if ((usb2canfsm != GET_MSG_TYPE) && (newbyte != '\r')) + newbyte = ASCII2byte(newbyte); + + switch (usb2canfsm){ + case GET_MSG_TYPE: + //check which message type came + usb2canfsm = parse_command_type(newbyte); + + break; + case GET_OPEN_COMMAND: + //if next byte is '\r', open channel and reset fsm + if (newbyte == '\r'){ + can_enable(); } + usb2canfsm = GET_MSG_TYPE; return 0; - - } else if (buf[0] == 'm' || buf[0] == 'M') { - // set mode command - if (buf[1] == 1) { - // mode 1: silent - can_set_silent(1); - } else { - // default to normal mode - can_set_silent(0); + case GET_CLOSE_COMMAND: + //if next byte is '\r', open channel and reset fsm + if (newbyte == '\r'){ + can_disable(); } + usb2canfsm = GET_MSG_TYPE; return 0; - - } else if (buf[0] == 'F') { - // set filter command - uint32_t id = 0; - for (i = 1; i < len; i++) { - id *= 16; - id += buf[i]; - } - current_filter_id = id; - can_set_filter(current_filter_id, current_filter_mask); - - } else if (buf[0] == 'K') { - // set mask command - uint32_t mask = 0; - for (i = 1; i < len; i++) { - mask *= 16; - mask += buf[i]; - } - current_filter_mask = mask; - can_set_filter(current_filter_id, current_filter_mask); - - } else if (buf[0] == 't' || buf[0] == 'T') { - // transmit data frame command - frame.RTR = CAN_RTR_DATA; - - } else if (buf[0] == 'r' || buf[0] == 'R') { - // transmit remote frame command - frame.RTR = CAN_RTR_REMOTE; - - } else { - // error, unknown command - return -1; - } - - if (buf[0] == 't' || buf[0] == 'r') { - frame.IDE = CAN_ID_STD; - } else if (buf[0] == 'T' || buf[0] == 'R') { - frame.IDE = CAN_ID_EXT; - } else { - // error - return -1; - } - - frame.StdId = 0; - frame.ExtId = 0; - if (frame.IDE == CAN_ID_EXT) { - uint8_t id_len = SLCAN_EXT_ID_LEN; - i = 1; - while (i <= id_len) { - frame.ExtId *= 16; - frame.ExtId += buf[i++]; + case GET_BITRATE_COMMAND: + if (counter >= 1){ + if (newbyte == '\r') + switch_bitrate_command(bitrate); + counter = 0; + usb2canfsm = GET_MSG_TYPE; + return 0; + } else{ + counter++; + bitrate = newbyte; } - } - else { - uint8_t id_len = SLCAN_STD_ID_LEN; - i = 1; - while (i <= id_len) { - frame.StdId *= 16; - frame.StdId += buf[i++]; + break; + case GET_MODE_COMMAND: + if (counter >= 1){ + if (newbyte == '\r') + can_set_silent(mode); + counter = 0; + usb2canfsm = GET_MSG_TYPE; + return 0; + } else{ + counter++; + mode = newbyte; } + break; + case GET_FILTER_COMMAND: + if (counter >= 5){ + if (newbyte == '\r'){ + current_filter_id = current_filter_temp; + can_set_filter(current_filter_id, current_mask_id); + } + current_filter_temp = 0; + counter = 0; + usb2canfsm = GET_MSG_TYPE; + return 0; + } else{ + counter++; + current_filter_temp = (current_filter_temp << 4) | newbyte; + } + break; + case GET_MASK_COMMAND: + if (counter >= 5){ + if (newbyte == '\r'){ + current_mask_id = current_mask_temp; + can_set_filter(current_filter_id, current_mask_id); + } + current_mask_temp = 0; + counter = 0; + usb2canfsm = GET_MSG_TYPE; + return 0; + } else{ + counter++; + current_mask_temp = (current_mask_temp << 4) | newbyte; + } + break; + case GET_FRAME_STD_ID: + if (counter >= 3){ + if ((newbyte <= 8) && (newbyte > 0)) { + frame.DLC = newbyte; + usb2canfsm = GET_FRAME_DATA; + } else + usb2canfsm = GET_MSG_TYPE; + counter = 0; + } else{ + counter++; + frame.StdId = (frame.StdId << 4) | newbyte; + } + break; + case GET_FRAME_EXT_ID: + if (counter >= 9){ + if (newbyte <= 8) { + frame.DLC = newbyte; + usb2canfsm = GET_FRAME_DATA; + } else + usb2canfsm = GET_MSG_TYPE; + counter = 0; + } else{ + counter++; + frame.ExtId = (frame.ExtId << 4) | newbyte; + } + break; + case GET_FRAME_DATA: + if (counter >= (frame.DLC*2)){ + if (newbyte == '\r'){ + can_tx(&frame, 0); + } + memset(&frame, 0x00, sizeof(frame)); + counter = 0; + usb2canfsm = GET_MSG_TYPE; + return 0; + } else{ + frame.Data[counter/2] = (frame.Data[counter/2] << 4) | newbyte; + counter++; + } + break; + default: + usb2canfsm = GET_MSG_TYPE; + break; } - - - frame.DLC = buf[i++]; - if (frame.DLC < 0 || frame.DLC > 8) { - return -1; - } - - uint8_t j; - for (j = 0; j < frame.DLC; j++) { - frame.Data[j] = (buf[i] << 4) + buf[i+1]; - i += 2; + + if (byte == '\r'){ + usb2canfsm = GET_MSG_TYPE; + counter = 0; + return 0; } - // send the message - can_tx(&frame, 10); - - return 0; + return 1; } diff --git a/Src/usbd_cdc_if.c b/Src/usbd_cdc_if.c index 0ff1710..3bf9598 100644 --- a/Src/usbd_cdc_if.c +++ b/Src/usbd_cdc_if.c @@ -73,6 +73,9 @@ * @{ */ /* USER CODE BEGIN 2 */ +extern uint8_t circle_buffer[SLCAN_MTU]; +extern uint8_t rx_point; +extern uint8_t need_update; /* USER CODE END 2 */ /** * @} @@ -244,29 +247,19 @@ static int8_t CDC_Control_FS (uint8_t cmd, uint8_t* pbuf, uint16_t length) * @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL */ -uint8_t slcan_str[SLCAN_MTU]; -uint8_t slcan_str_index = 0; - static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 7 */ uint8_t n = *Len; uint8_t i; for (i = 0; i < n; i++) { - if (Buf[i] == '\r') { - slcan_parse_str(slcan_str, slcan_str_index); - slcan_str_index = 0; - } else { - slcan_str[slcan_str_index++] = Buf[i]; - } + circle_buffer[rx_point] = Buf[i]; + rx_point = (rx_point + 1) % SLCAN_MTU; } - - // prepare for next read - //USBD_CDC_SetRxBuffer(hUsbDevice_0, UserRxBufferFS); - USBD_CDC_ReceivePacket(hUsbDevice_0); - - return (USBD_OK); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); + if (USBD_CDC_ReceivePacket(&hUsbDeviceFS) != USBD_OK) need_update = 1; /* USER CODE END 7 */ + return (USBD_OK); } /**