diff --git a/CMakeLists.txt b/CMakeLists.txt index 5108571b..a9f5e9a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ add_link_options( -mthumb LINKER:--gc-sections LINKER:--print-memory-usage + LINKER:-Map=foo.map ) add_subdirectory(libs/STM32_HAL) diff --git a/include/usbd_gs_can.h b/include/usbd_gs_can.h index 3a7fe641..f3c824b3 100644 --- a/include/usbd_gs_can.h +++ b/include/usbd_gs_can.h @@ -56,14 +56,13 @@ struct gs_host_frame_object { typedef struct { uint8_t ep0_buf[CAN_CMD_PACKET_SIZE]; - __IO uint32_t TxState; - USBD_SetupReqTypedef last_setup_request; struct list_head list_frame_pool; struct list_head list_to_host; struct gs_host_frame_object *from_host_buf; + struct gs_host_frame_object *to_host_buf; can_data_t channels[NUM_CAN_CHANNEL]; @@ -93,10 +92,10 @@ typedef struct { uint8_t USBD_GS_CAN_Init(USBD_GS_CAN_HandleTypeDef *hcan, USBD_HandleTypeDef *pdev); void USBD_GS_CAN_SuspendCallback(USBD_HandleTypeDef *pdev); void USBD_GS_CAN_ResumeCallback(USBD_HandleTypeDef *pdev); -bool USBD_GS_CAN_TxReady(USBD_HandleTypeDef *pdev); bool USBD_GS_CAN_CustomDeviceRequest(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); bool USBD_GS_CAN_CustomInterfaceRequest(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); bool USBD_GS_CAN_DfuDetachRequested(USBD_HandleTypeDef *pdev); -uint8_t USBD_GS_CAN_SendFrame(USBD_HandleTypeDef *pdev, struct gs_host_frame *frame); -uint8_t USBD_GS_CAN_Transmit(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len); + +uint8_t USBD_GS_CAN_SendToHost(USBD_HandleTypeDef *pdev); +uint8_t USBD_GS_CAN_ReceiveFromHost(USBD_HandleTypeDef *pdev); diff --git a/src/main.c b/src/main.c index 12e51815..bb48e9e6 100644 --- a/src/main.c +++ b/src/main.c @@ -49,21 +49,6 @@ static void SystemClock_Config(void); static USBD_GS_CAN_HandleTypeDef hGS_CAN; static USBD_HandleTypeDef hUSB = {0}; -static void send_to_host(void) -{ - struct gs_host_frame_object *frame_object; - - frame_object = list_first_entry_or_null_locked(&hGS_CAN.list_to_host, - struct gs_host_frame_object, - list); - if (!frame_object) - return; - - if (USBD_GS_CAN_SendFrame(&hUSB, &frame_object->frame) == USBD_OK) { - list_move_tail_locked(&frame_object->list, &hGS_CAN.list_frame_pool); - } -} - int main(void) { HAL_Init(); @@ -72,9 +57,6 @@ int main(void) gpio_init(); timer_init(); - can_init(channel, CAN_INTERFACE); - can_disable(channel); - INIT_LIST_HEAD(&hGS_CAN.list_frame_pool); INIT_LIST_HEAD(&hGS_CAN.list_to_host); @@ -134,9 +116,8 @@ int main(void) } } - if (USBD_GS_CAN_TxReady(&hUSB)) { - send_to_host(); - } + USBD_GS_CAN_ReceiveFromHost(&hUSB); + USBD_GS_CAN_SendToHost(&hUSB); if (can_is_rx_pending(channel)) { frame_object = list_first_entry_or_null_locked(&hGS_CAN.list_frame_pool, diff --git a/src/usbd_gs_can.c b/src/usbd_gs_can.c index 7d54952c..b1cbe7a0 100644 --- a/src/usbd_gs_can.c +++ b/src/usbd_gs_can.c @@ -238,6 +238,8 @@ static const struct gs_device_bt_const USBD_GS_CAN_btconst = { 1, // brp increment; }; +uint8_t USBD_GS_CAN_SendFrame(USBD_HandleTypeDef *pdev, struct gs_host_frame *frame); + /* It's unclear from the documentation, but it appears that the USB library is * not safely reentrant. It attempts to signal errors via return values if it is * reentered, but that code is not interrupt-safe and the error values are @@ -532,10 +534,14 @@ static uint8_t USBD_GS_CAN_EP0_RxReady(USBD_HandleTypeDef *pdev) { } static uint8_t USBD_GS_CAN_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { + USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*)pdev->pClassData; (void) epnum; - USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*)pdev->pClassData; - hcan->TxState = 0; + bool was_irq_enabled = disable_irq(); + list_add_tail(&hcan->to_host_buf->list, &hcan->list_frame_pool); + hcan->to_host_buf = NULL; + restore_irq(was_irq_enabled); + return USBD_OK; } @@ -663,29 +669,60 @@ bool USBD_GS_CAN_CustomInterfaceRequest(USBD_HandleTypeDef *pdev, USBD_SetupReqT return USBD_GS_CAN_CustomDeviceRequest(pdev, req); } -bool USBD_GS_CAN_TxReady(USBD_HandleTypeDef *pdev) +void USBD_GS_CAN_FillFromHost(USBD_HandleTypeDef *pdev) { USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*)pdev->pClassData; + + /* first check w/o lock */ + if (hcan->from_host_buf) + return; + bool was_irq_enabled = disable_irq(); + + if (hcan->from_host_buf) + return; + + hcan->from_host_buf = list_first_entry_or_null(&hcan->list_frame_pool, + struct gs_host_frame_object, + list); if (!hcan->from_host_buf) { - hcan->from_host_buf = list_first_entry_or_null(&hcan->list_frame_pool, - struct gs_host_frame_object, - list); - if (hcan->from_host_buf) { - list_del(&hcan->from_host_buf->list); - USBD_GS_CAN_PrepareReceive(pdev); - } + restore_irq(was_irq_enabled); + return; } - bool result = hcan->TxState == 0; + + list_del(&hcan->from_host_buf->list); restore_irq(was_irq_enabled); - return result; + + USBD_GS_CAN_PrepareReceive(pdev); } -uint8_t USBD_GS_CAN_Transmit(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len) +uint8_t USBD_GS_CAN_SendToHost(USBD_HandleTypeDef *pdev) { USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*)pdev->pClassData; - if (hcan->TxState == 0 && (false == is_usb_suspend_cb)) { - hcan->TxState = 1; + + bool was_irq_enabled = disable_irq(); + if (hcan->to_host_buf) { + restore_irq(was_irq_enabled); + return USBD_BUSY; + } + + hcan->to_host_buf = list_first_entry_or_null(&hcan->list_to_host, + struct gs_host_frame_object, + list); + if (hcan->to_host_buf) { + list_del(&hcan->to_host_buf->list); + restore_irq(was_irq_enabled); + + USBD_GS_CAN_SendFrame(pdev, &hcan->to_host_buf->frame); + } else { + restore_irq(was_irq_enabled); + } + return USBD_OK; +} + +uint8_t USBD_GS_CAN_Transmit(USBD_HandleTypeDef *pdev, uint8_t *buf, uint16_t len) +{ + if (false == is_usb_suspend_cb) { USBD_LL_Transmit(pdev, GSUSB_ENDPOINT_IN, buf, len); return USBD_OK; } else { @@ -719,10 +756,7 @@ uint8_t USBD_GS_CAN_SendFrame(USBD_HandleTypeDef *pdev, struct gs_host_frame *fr len = sizeof(buf); } - bool was_irq_enabled = disable_irq(); - uint8_t result = USBD_GS_CAN_Transmit(pdev, send_addr, len); - restore_irq(was_irq_enabled); - return result; + return USBD_GS_CAN_Transmit(pdev, send_addr, len); } bool USBD_GS_CAN_DfuDetachRequested(USBD_HandleTypeDef *pdev) @@ -753,7 +787,6 @@ void USBD_GS_CAN_SuspendCallback(USBD_HandleTypeDef *pdev) void USBD_GS_CAN_ResumeCallback(USBD_HandleTypeDef *pdev) { - USBD_GS_CAN_HandleTypeDef *hcan = (USBD_GS_CAN_HandleTypeDef*) pdev->pClassData; - hcan->TxState = 0; + (void)pdev; is_usb_suspend_cb = false; }