Merge pull request #57 from Wetmelon/usb_thread

Async USB Handling and printf blocking
This commit is contained in:
Oskar Weigl
2017-11-08 17:24:01 -08:00
committed by GitHub
7 changed files with 109 additions and 47 deletions
+4
View File
@@ -4,10 +4,14 @@
// List of semaphore
osSemaphoreId sem_usb_irq;
osSemaphoreId sem_uart_dma;
osSemaphoreId sem_usb_rx;
osSemaphoreId sem_usb_tx;
// List of threads
osThreadId thread_motor_0;
osThreadId thread_motor_1;
osThreadId thread_cmd_parse;
osThreadId thread_usb_pump;
#endif /* __FREERTOS_H */
@@ -62,6 +62,8 @@
#include "usbd_cdc.h"
#include "usbd_desc.h"
#include "usbd_ctlreq.h"
#include <cmsis_os.h>
#include <freertos_vars.h>
/** @addtogroup STM32_USB_DEVICE_LIBRARY
@@ -669,7 +671,7 @@ static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)
{
hcdc->TxState = 0;
osSemaphoreRelease(sem_usb_tx);
return USBD_OK;
}
else
+35 -9
View File
@@ -4,6 +4,7 @@
#include <usart.h>
#include <gpio.h>
#include <freertos_vars.h>
#include <usbd_cdc.h>
extern PCD_HandleTypeDef hpcd_USB_OTG_FS;
@@ -21,6 +22,10 @@ SerialPrintf_t serial_printf_select = SERIAL_PRINTF_IS_NONE;
static const GpioMode_t gpio_mode = GPIO_MODE_UART; //GPIO 1,2 is UART Tx,Rx
// static const GpioMode_t gpio_mode = GPIO_MODE_STEP_DIR; //GPIO 1,2 is M0 Step,Dir
static uint8_t* usb_buf;
static uint32_t usb_len;
extern USBD_HandleTypeDef hUsbDeviceFS;
// variables exposed to usb/serial interface via set/get/monitor
// Note: this will be depricated soon
static float* const exposed_floats[] = {
@@ -163,6 +168,10 @@ void motor_parse_cmd(uint8_t* buffer, int len, SerialPrintf_t response_interface
if (numscan == 2 && motor_number < num_motors) {
set_current_setpoint(&motors[motor_number], current_feed_forward);
}
} else if(buffer[0] == 'e'){
int val = printf("Test 1\n");
int val2 = printf("test 2\n");
val = 0;
} else if (buffer[0] == 'g') { // GET
// g <0:float,1:int,2:bool,3:uint16> index
int type = 0;
@@ -338,18 +347,35 @@ void cmd_parse_thread(void const * argument) {
// When we reach here, we are out of immediate characters to fetch out of UART buffer
// Now we check if there is any USB processing to do: we wait for up to 1 ms,
// before going back to checking UART again.
int USB_check_timeout = 1;
// Wait for signalling from USB interrupt (OTG_FS_IRQHandler)
osStatus semaphore_status = osSemaphoreWait(sem_usb_irq, USB_check_timeout);
if (semaphore_status == osOK) {
// We have a new incoming USB transmission: handle it
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
// Let the irq (OTG_FS_IRQHandler) fire again.
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
const uint32_t usb_check_timeout = 1; // ms
osStatus sem_stat = osSemaphoreWait(sem_usb_rx, usb_check_timeout);
if (sem_stat == osOK) {
motor_parse_cmd(usb_buf, usb_len, SERIAL_PRINTF_IS_USB);
USBD_CDC_ReceivePacket(&hUsbDeviceFS); // Allow next packet
}
} while (!reset_read_state);
}
// If we get here, then this task is done
vTaskDelete(osThreadGetId());
}
// Called from CDC_Receive_FS callback function, this allows motor_parse_cmd to access the
// incoming USB data
void set_cmd_buffer(uint8_t *buf, uint32_t len) {
usb_buf = buf;
usb_len = len;
}
void usb_update_thread() {
for (;;) {
// Wait for signalling from USB interrupt (OTG_FS_IRQHandler)
osStatus semaphore_status = osSemaphoreWait(sem_usb_irq, osWaitForever);
if (semaphore_status == osOK) {
// We have a new incoming USB transmission: handle it
HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS);
// Let the irq (OTG_FS_IRQHandler) fire again.
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
}
}
vTaskDelete(osThreadGetId());
}
+3
View File
@@ -27,4 +27,7 @@ void init_communication();
void cmd_parse_thread(void const * argument);
void motor_parse_cmd(uint8_t* buffer, int len, SerialPrintf_t response_interface);
void set_cmd_buffer(uint8_t *buf, uint32_t len);
void usb_update_thread();
#endif /* COMMANDS_H */
+20 -2
View File
@@ -88,10 +88,24 @@ void MX_FREERTOS_Init(void) {
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
// Init usb irq binary semaphore, and start with no tolkens by removing the starting one.
// Init usb irq binary semaphore, and start with no tokens by removing the starting one.
osSemaphoreDef(sem_usb_irq);
sem_usb_irq = osSemaphoreCreate(osSemaphore(sem_usb_irq), 1);
osSemaphoreWait(sem_usb_irq, 0);
// Create a semaphore for UART DMA and remove a token
osSemaphoreDef(sem_uart_dma);
sem_uart_dma = osSemaphoreCreate(osSemaphore(sem_uart_dma), 1);
// Create a semaphore for USB RX
osSemaphoreDef(sem_usb_rx);
sem_usb_rx = osSemaphoreCreate(osSemaphore(sem_usb_rx), 1);
osSemaphoreWait(sem_usb_irq, 0); // Remove a token.
// Create a semaphore for USB RX
osSemaphoreDef(sem_usb_tx);
sem_usb_tx = osSemaphoreCreate(osSemaphore(sem_usb_tx), 1);
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
@@ -132,10 +146,14 @@ void StartDefaultTask(void const * argument)
thread_motor_0 = osThreadCreate(osThread(task_motor_0), &motors[0]);
thread_motor_1 = osThreadCreate(osThread(task_motor_1), &motors[1]);
// Start USB command handling thread
// Start command handling thread
osThreadDef(task_cmd_parse, cmd_parse_thread, osPriorityNormal, 0, 512);
thread_cmd_parse = osThreadCreate(osThread(task_cmd_parse), NULL);
// Start USB interrupt handler thread
osThreadDef(task_usb_pump, usb_update_thread, osPriorityNormal, 0, 512);
thread_usb_pump = osThreadCreate(osThread(task_usb_pump), NULL);
//If we get to here, then the default task is done.
vTaskDelete(defaultTaskHandle);
+41 -31
View File
@@ -5,11 +5,12 @@
******************************************************************************
*/
#include <sys/unistd.h>
#include <usbd_cdc_if.h>
#include <usart.h>
#include <cmsis_os.h>
#include <commands.h>
#include <freertos_vars.h>
#include <sys/unistd.h>
#include <usart.h>
#include <usbd_cdc_if.h>
//int _read(int file, char *data, int len) {}
//int _close(int file) {}
@@ -20,34 +21,43 @@
#define UART_TX_BUFFER_SIZE 64
static uint8_t uart_tx_buf[UART_TX_BUFFER_SIZE];
int _write(int file, char *data, int len) {
//number of bytes written
int written = 0;
switch (serial_printf_select) {
int _write(int file, char* data, int len) {
//number of bytes written
int written = 0;
switch (serial_printf_select) {
case SERIAL_PRINTF_IS_USB: {
// Wait on semaphore for the interface to be available
// Note that the USB driver will release the interface again when the TX completes
const uint32_t usb_tx_timeout = 100; // ms
osStatus sem_stat = osSemaphoreWait(sem_usb_tx, usb_tx_timeout);
if (sem_stat == osOK) {
uint8_t status = CDC_Transmit_FS((uint8_t*)data, len); // transmit over CDC
written = (status == USBD_OK) ? len : 0;
} // If the semaphore times out, we simply leave "written" as 0
} break;
case SERIAL_PRINTF_IS_USB: {
// transmit over CDC
uint8_t status = CDC_Transmit_FS((uint8_t*)data, len);
written = (status == USBD_OK) ? len : 0;
} break;
case SERIAL_PRINTF_IS_UART: {
//Check length
if (len > UART_TX_BUFFER_SIZE)
return 0;
// Wait on semaphore for the interface to be available
// Note that HAL_UART_TxCpltCallback will release the interface again when the TX completes
const uint32_t uart_tx_timeout = 100; // ms
osStatus sem_stat = osSemaphoreWait(sem_uart_dma, uart_tx_timeout);
if (sem_stat == osOK) {
memcpy(uart_tx_buf, data, len); // memcpy data into uart_tx_buf
HAL_UART_Transmit_DMA(&huart4, uart_tx_buf, len); // Start DMA background transfer
} // If the semaphore times out, we simply leave "written" as 0
} break;
case SERIAL_PRINTF_IS_UART: {
//Check length
if (len > UART_TX_BUFFER_SIZE)
return 0;
// Check if transfer is already ongoing
if(huart4.gState != HAL_UART_STATE_READY)
return 0;
// memcpy data into uart_tx_buf
memcpy(uart_tx_buf, data, len);
// Start DMA background trasnfer
HAL_UART_Transmit_DMA(&huart4, uart_tx_buf, len);
} break;
default: {
written = 0;
} break;
}
default: {
written = 0;
} break;
}
return written;
return written;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart) {
osSemaphoreRelease(sem_uart_dma);
}
+3 -4
View File
@@ -51,6 +51,7 @@
/* USER CODE BEGIN INCLUDE */
#include "utils.h"
#include "commands.h"
#include <freertos_vars.h>
/* USER CODE END INCLUDE */
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
@@ -272,10 +273,8 @@ static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
int modified_len = MACRO_MIN(*Len+1, APP_RX_DATA_SIZE);
Buf[modified_len-1] = 0;
motor_parse_cmd(Buf, modified_len, SERIAL_PRINTF_IS_USB);
// Allow next packet
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
set_cmd_buffer(Buf, modified_len);
osSemaphoreRelease(sem_usb_rx);
return (USBD_OK);
/* USER CODE END 6 */