From f87de543ebd3366e898f2a76b919faf8f8e3819a Mon Sep 17 00:00:00 2001 From: Rahix <rahix@rahix.de> Date: Wed, 3 Jul 2019 20:28:44 +0200 Subject: [PATCH] feat(epicardium): Port to FreeRTOS Signed-off-by: Rahix <rahix@rahix.de> --- epicardium/FreeRTOSConfig.h | 45 +++++++++++++++++++ epicardium/cdcacm.c | 3 ++ epicardium/main.c | 90 ++++++++++++++++++++++++++++++------- epicardium/meson.build | 20 ++++++++- epicardium/serial.c | 68 ++++++++++++++++++++++++++++ epicardium/serial.h | 8 ++++ 6 files changed, 216 insertions(+), 18 deletions(-) create mode 100644 epicardium/FreeRTOSConfig.h create mode 100644 epicardium/serial.c create mode 100644 epicardium/serial.h diff --git a/epicardium/FreeRTOSConfig.h b/epicardium/FreeRTOSConfig.h new file mode 100644 index 000000000..26e51bc4c --- /dev/null +++ b/epicardium/FreeRTOSConfig.h @@ -0,0 +1,45 @@ +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "max32665.h" + +/* CMSIS keeps a global updated with current system clock in Hz */ +#define configCPU_CLOCK_HZ ((unsigned long)120000000) + +/* TODO: Adjust this for tickless idle */ +#define configTICK_RATE_HZ ((portTickType)1000) + +/* Memory */ +#define configTOTAL_HEAP_SIZE ((size_t)(26 * 1024)) +#define configMINIMAL_STACK_SIZE ((unsigned short)128) + +#define configMAX_PRIORITIES 5 +/* # of priority bits (configured in hardware) is provided by CMSIS */ +#define configPRIO_BITS __NVIC_PRIO_BITS +/* Priority 7, or 255 as only the top three bits are implemented. This is the lowest priority. */ +#define configKERNEL_INTERRUPT_PRIORITY ( ( unsigned char ) 7 << ( 8 - configPRIO_BITS) ) +/* Priority 5, or 160 as only the top three bits are implemented. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( ( unsigned char ) 5 << ( 8 - configPRIO_BITS) ) + +/* We want to use preemption to easier integrate components */ +#define configUSE_PREEMPTION 1 + +/* TODO: Adjust */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_CO_ROUTINES 0 +#define configUSE_16_BIT_TICKS 0 +#define configUSE_MUTEXES 1 + +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelay 1 + +/* Allow static allocation of data structures */ +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* Alias the default handler names to match CMSIS weak symbols */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/epicardium/cdcacm.c b/epicardium/cdcacm.c index a11d38e05..5bc8f706d 100644 --- a/epicardium/cdcacm.c +++ b/epicardium/cdcacm.c @@ -344,7 +344,10 @@ void USB_IRQHandler(void) } /******************************************************************************/ +/* TODO: We probably need to fix something related to this */ +#if 0 void SysTick_Handler(void) { mxc_delay_handler(); } +#endif /* 0 */ diff --git a/epicardium/main.c b/epicardium/main.c index 40ef9e9ac..3490b026d 100644 --- a/epicardium/main.c +++ b/epicardium/main.c @@ -1,35 +1,59 @@ #include <stdio.h> -#include "card10.h" +#include <stdlib.h> + #include "uart.h" #include "cdcacm.h" + +#include "card10.h" #include "leds.h" #include "api/dispatcher.h" +#include "serial.h" -extern mxc_uart_regs_t * ConsoleUart; +#include "FreeRTOS.h" +#include "task.h" -void epic_uart_write_str(char*str, intptr_t length) +void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b) { - UART_Write(ConsoleUart, (uint8_t*)str, length); - cdcacm_write((uint8_t*)str, length); + leds_set(led, r, g, b); + leds_update(); } -char epic_uart_read_chr(void) +void vApiDispatcher(void*pvParameters) { - while(1) { - if(UART_NumReadAvail(ConsoleUart) > 0) { - return UART_ReadByte(ConsoleUart); - } - - if(cdcacm_num_read_avail() > 0) { - return cdcacm_read(); - } + while (1) { + api_dispatcher_poll(); + vTaskDelay(portTICK_PERIOD_MS * 10); } } -void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b) +void vApplicationGetIdleTaskMemory( + StaticTask_t**ppxIdleTaskTCBBuffer, + StackType_t**ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize) { - leds_set(led, r, g, b); - leds_update(); + /* + * If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. + */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* + * Pass out a pointer to the StaticTask_t structure in which the Idle task's + * ktate will be stored. + */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* + * Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + * Note that, as the array is necessarily of type StackType_t, + * configMINIMAL_STACK_SIZE is specified in words, not bytes. + */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } int main(void) @@ -39,14 +63,46 @@ int main(void) cdcacm_init(); + printf("Initializing tasks ...\n"); + + /* Serial */ + if (xTaskCreate( + vSerialTask, + (const char*)"Serial", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 1, + NULL + ) != pdPASS) { + printf("Failed to create serial-comms task!\n"); + abort(); + } + + if (xTaskCreate( + vApiDispatcher, + (const char*)"API Dispatcher", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 2, + NULL + ) != pdPASS) { + printf("Failed to create api dispatcher task!\n"); + abort(); + } + printf("Initializing dispatcher ...\n"); api_dispatcher_init(); printf("Staring core1 payload ...\n"); core1_start(); + vTaskStartScheduler(); + printf("ERROR: FreeRTOS did not start due to above error!\n"); + +#if 0 while(1) { __WFE(); api_dispatcher_poll(); } +#endif } diff --git a/epicardium/meson.build b/epicardium/meson.build index f84abbe79..7aa214405 100644 --- a/epicardium/meson.build +++ b/epicardium/meson.build @@ -39,6 +39,22 @@ api_dispatcher_lib = static_library( dependencies: periphdriver, ) +########################################################################## +# +# FreeRTOS +# +########################################################################## + +freertos = static_library( + 'freertos', + freertos_sources, + dependencies: periphdriver, + include_directories: [ + freertos_includes, + include_directories('./'), + ], +) + ########################################################################## # # Epicardium executable @@ -49,9 +65,11 @@ elf = executable( name + '.elf', 'main.c', 'cdcacm.c', + 'serial.c', dependencies: [libcard10, max32665_startup_core0, maxusb], - link_with: api_dispatcher_lib, + link_with: [api_dispatcher_lib, freertos], link_whole: [max32665_startup_core0_lib, board_card10_lib], + include_directories: [freertos_includes], link_args: [ '-Wl,-Map=' + meson.current_build_dir() + '/' + name + '.map', ], diff --git a/epicardium/serial.c b/epicardium/serial.c new file mode 100644 index 000000000..0a062c23d --- /dev/null +++ b/epicardium/serial.c @@ -0,0 +1,68 @@ +#include <stdint.h> +#include <stdio.h> + +#include "serial.h" + +#include "cdcacm.h" +#include "uart.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +extern mxc_uart_regs_t * ConsoleUart; + +static QueueHandle_t read_queue; + +void epic_uart_write_str(char*str, intptr_t length) +{ + UART_Write(ConsoleUart, (uint8_t*)str, length); + cdcacm_write((uint8_t*)str, length); +} + +char epic_uart_read_chr(void) +{ + char chr; + xQueueReceive(read_queue, &chr, portMAX_DELAY); + return chr; +} + +void vSerialTask(void*pvParameters) +{ + static uint8_t buffer[sizeof(char) * SERIAL_READ_BUFFER_SIZE]; + static StaticQueue_t read_queue_data; + + /* Setup read queue */ + read_queue = xQueueCreateStatic( + SERIAL_READ_BUFFER_SIZE, + sizeof(char), + buffer, + &read_queue_data + ); + + /* Setup UART interrupt */ + NVIC_ClearPendingIRQ(UART0_IRQn); + NVIC_DisableIRQ(UART0_IRQn); + NVIC_SetPriority(UART0_IRQn, 1); + NVIC_EnableIRQ(UART0_IRQn); + + while (1) { + char chr; + + /* TODO: Wait for interrupt on either device */ + vTaskDelay(portTICK_PERIOD_MS * 10); + + if(UART_NumReadAvail(ConsoleUart) > 0) { + chr = UART_ReadByte(ConsoleUart); + } else if(cdcacm_num_read_avail() > 0) { + chr = cdcacm_read(); + } else { + continue; + } + + if (xQueueSend(read_queue, &chr, 100) == errQUEUE_FULL) { + /* Queue overran, wait a bit */ + vTaskDelay(portTICK_PERIOD_MS * 50); + } + } +} diff --git a/epicardium/serial.h b/epicardium/serial.h new file mode 100644 index 000000000..5e2e17795 --- /dev/null +++ b/epicardium/serial.h @@ -0,0 +1,8 @@ +#ifndef EPIC_SERIAL_H +#define EPIC_SERIAL_H + +#define SERIAL_READ_BUFFER_SIZE 128 + +void vSerialTask(void*pvParameters); + +#endif /* EPIC_SERIAL_H */ -- GitLab