diff --git a/software/CMakeLists.txt b/software/CMakeLists.txt index 8198da2..7f7bac3 100644 --- a/software/CMakeLists.txt +++ b/software/CMakeLists.txt @@ -42,12 +42,14 @@ set(OST_SRCS system/ff/ff.c system/ff/ffsystem.c system/ff/ff_stubs.c + chip32/chip32_vm.c ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/library ${CMAKE_CURRENT_SOURCE_DIR}/system ${CMAKE_CURRENT_SOURCE_DIR}/system/ff + ${CMAKE_CURRENT_SOURCE_DIR}/chip32 ) # ================================================================================================== diff --git a/software/platform/raspberry-pico-w/pico_hal_wrapper.c b/software/platform/raspberry-pico-w/pico_hal_wrapper.c index 398ffa8..3ec7524 100644 --- a/software/platform/raspberry-pico-w/pico_hal_wrapper.c +++ b/software/platform/raspberry-pico-w/pico_hal_wrapper.c @@ -30,8 +30,8 @@ // =========================================================================================================== // CONSTANTS / DEFINES // =========================================================================================================== - -const uint8_t LED_PIN = 14; // GP 14 +const uint8_t DEBUG_PIN = 1; +const uint8_t LED_PIN = 14; const uint8_t LCD_DC = 8; const uint8_t LCD_CS = 9; @@ -99,6 +99,10 @@ void ost_system_initialize() gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); + //------------------- Init DEBUG PIN + gpio_init(DEBUG_PIN); + gpio_set_dir(DEBUG_PIN, GPIO_OUT); + //------------------- Init UART // Set up our UART with the required speed. @@ -180,6 +184,25 @@ void system_putc(char ch) uart_putc_raw(UART_ID, ch); } +#include +clock_t clock() +{ + return (clock_t)time_us_64() / 1000; +} +static uint64_t stopwatch_start_time; +static uint64_t stopwatch_end_time; + +void ost_system_stopwatch_start() +{ + stopwatch_start_time = clock(); +} + +uint32_t ost_system_stopwatch_stop() +{ + stopwatch_end_time = clock(); + return (stopwatch_end_time - stopwatch_start_time); +} + int ost_hal_gpio_get(ost_hal_gpio_t gpio) { int value = 0; @@ -205,6 +228,9 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value) case OST_GPIO_DEBUG_LED: gpio_put(LED_PIN, value); break; + case OST_GPIO_DEBUG_PIN: + gpio_put(DEBUG_PIN, value); + break; // Nothing to do for these inputes case OST_GPIO_ROTARY_A: diff --git a/software/system/main.c b/software/system/main.c index 260affd..8275cb9 100644 --- a/software/system/main.c +++ b/software/system/main.c @@ -6,47 +6,6 @@ #include "qor.h" #include "rotary-button.h" -#define RUN_TESTS 1 - -#ifndef RUN_TESTS -int main(void) -{ - // Low level initialization, mainly platform stuff - // After this call, debug_printf *MUST* be available - ost_system_initialize(); - debug_printf("\r\n [OST] Starting OpenStoryTeller tests: V%d.%d\r\n", 1, 0); - - // File system access - filesystem_mount(); - - // Display - ost_display_initialize(); - decompress(); - - // Audio - - // Tasker - ost_tasker_init(); - - for (;;) - { - } - - return 0; -} -#else - -// Raspberry Pico SDK -#include "pico/stdlib.h" -#include "hardware/uart.h" -#include "hardware/spi.h" -#include "hardware/dma.h" -#include "hardware/irq.h" -#include "hardware/pio.h" -#include "hardware/clocks.h" -#include "pico.h" -#include "pico/stdlib.h" - #include "sdcard.h" #include @@ -54,13 +13,76 @@ int main(void) #include #include "audio_player.h" +#include "chip32_vm.h" void ost_hal_panic() { } // =========================================================================================================== -// SD CARD TASK +// VIRTUAL MACHINE TASK +// =========================================================================================================== +static qor_tcb_t VmTcb; +static uint32_t VmStack[4096]; + +static qor_mbox_t VmMailBox; + +typedef struct +{ + uint8_t ev; +} ost_vm_event_t; +ost_vm_event_t VmQueue[10]; + +static ost_vm_event_t VmEvent; + +static uint8_t m_rom_data[16 * 1024]; +static uint8_t m_ram_data[16 * 1024]; +static chip32_ctx_t m_chip32_ctx; + +uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t signum) +{ +} + +void VmTask(void *args) +{ + + // VM Initialize + m_chip32_ctx.stack_size = 512; + + m_chip32_ctx.rom.mem = m_rom_data; + m_chip32_ctx.rom.addr = 0; + m_chip32_ctx.rom.size = sizeof(m_rom_data); + + m_chip32_ctx.ram.mem = m_ram_data; + m_chip32_ctx.ram.addr = sizeof(m_rom_data); + m_chip32_ctx.ram.size = sizeof(m_ram_data); + + m_chip32_ctx.syscall = vm_syscall; + + chip32_initialize(&m_chip32_ctx); + + chip32_result_t run_result; + ost_vm_event_t *e = NULL; + + while (1) + { + uint32_t res = qor_mbox_wait(&VmMailBox, (void **)&e, 300); // On devrait recevoir un message toutes les 3ms (durée d'envoi d'un buffer I2S) + + if (res == QOR_MBOX_OK) + { + if (VmEvent.ev == 1) + { + do + { + run_result = chip32_step(&m_chip32_ctx); + } while (run_result != VM_OK); + } + } + } +} + +// =========================================================================================================== +// FILE SYSTEM TASK // =========================================================================================================== static qor_tcb_t AudioTcb; static uint32_t AudioStack[4096]; @@ -82,14 +104,8 @@ static int dbg_state = 0; static void audio_callback(void) { dbg_state = 1 - dbg_state; - gpio_put(1, dbg_state); qor_mbox_notify(&AudioMailBox, (void **)&wake_up, QOR_MBOX_OPTION_SEND_BACK); } -#include -clock_t clock() -{ - return (clock_t)time_us_64() / 1000; -} void show_duration(uint32_t millisecondes) { @@ -116,16 +132,12 @@ void AudioTask(void *args) ost_audio_register_callback(audio_callback); - gpio_init(1); - gpio_set_dir(1, GPIO_OUT); - static bool onetime = true; - gpio_put(1, 0); while (1) { debug_printf("\r\n-------------------------------------------------------\r\nPlaying: out2.wav\r\n"); - clock_t startTime = clock(); + ost_system_stopwatch_start(); ost_audio_play("out2.wav"); ost_audio_event_t *e = NULL; @@ -145,9 +157,8 @@ void AudioTask(void *args) } while (isPlaying); + uint32_t executionTime = ost_system_stopwatch_stop(); ost_audio_stop(); - clock_t endTime = clock(); - uint32_t executionTime = endTime - startTime; debug_printf("\r\nPackets: %d\r\n", count); show_duration(executionTime); @@ -190,14 +201,15 @@ int main() // 3. Filesystem / SDCard initialization filesystem_mount(); - // 4. Initialize OS and threads + // 4. Initialize OS before all other OS calls qor_init(125000000UL); - // qor_create_thread(&tcb1, UserTask_1, 2, "UserTask_1"); - // qor_create_thread(&tcb2, UserTask_2, 1, "UserTask_2"); + // 5. Initialize the tasks + qor_create_thread(&VmTcb, VmTask, VmStack, sizeof(VmStack) / sizeof(VmStack[0]), 2, "VmTask"); qor_create_thread(&AudioTcb, AudioTask, AudioStack, sizeof(AudioStack) / sizeof(AudioStack[0]), 3, "AudioTask"); ///< High priority for audio + + // 6. Start the operating system! qor_start(&IdleTcb, IdleTask, IdleStack, 1024); return 0; } -#endif diff --git a/software/system/ost_hal.h b/software/system/ost_hal.h index 8b90ab4..7ee46fa 100644 --- a/software/system/ost_hal.h +++ b/software/system/ost_hal.h @@ -38,6 +38,7 @@ extern "C" OST_GPIO_ROTARY_A, OST_GPIO_ROTARY_B, OST_GPIO_DEBUG_LED, + OST_GPIO_DEBUG_PIN, } ost_hal_gpio_t; // ---------------------------------------------------------------------------- @@ -47,6 +48,9 @@ extern "C" void system_putc(char ch); void ost_system_delay_ms(uint32_t delay); + void ost_system_stopwatch_start(); + uint32_t ost_system_stopwatch_stop(); + void ost_audio_play(const char *filename); void ost_audio_stop(); int ost_audio_process(); diff --git a/software/system/qor.h b/software/system/qor.h index 5196371..ca5b2f1 100644 --- a/software/system/qor.h +++ b/software/system/qor.h @@ -1,6 +1,8 @@ #ifndef QOR_H #define QOR_H +#define QOR_VERSION "0.1" + #include #include @@ -23,24 +25,24 @@ typedef void (*thread_func_t)(void *args); */ typedef enum { - qor_tcb_state_active, - qor_tcb_state_sleep + qor_tcb_state_active, //!< Thread is active (and can be scheduled or is currently running) + qor_tcb_state_sleep //!< Thread is wating for mailbox or sleep } qor_tcb_state_t; +typedef struct qor_mbox_t qor_mbox_t; //!< Foreward declaration + /** * @brief Thread Control Block * * IMPORTANT! keep the stack pointer on top, it is required by the task switch assembly * */ - -typedef struct qor_mbox_t qor_mbox_t; typedef struct TCB { - uint32_t *sp; //!< Stack pointer, valid for threads not running + uint32_t *sp; //!< Stack pointer, valid for threads not running, keep it on top struct TCB *next; //!< Pointer to circular-linked-list of TCBs struct TCB *wait_next; //!< Next TCB in waiting list - uint32_t stack_size; + uint32_t stack_size; //!< Stack size, in number of uint32_t qor_tcb_state_t state; //!< TCB active or free uint32_t wait_time; //!< Timeout for mbox maiting or sleep qor_mbox_t *mbox; //!< Pointer to mailbox on which the thread is blocked, NULL if not blocked @@ -51,21 +53,55 @@ typedef struct TCB // Debug/traces uint32_t stack_usage; uint32_t *stack_bottom; - bool so; // stack overflow detected + bool so; //!< stack overflow detected } qor_tcb_t; +/** + * @brief QoRTOS initialization, call it before anything else + * + * @param scheduler_frequency_hz: CPU frequency in Hz + */ void qor_init(uint32_t scheduler_frequency_hz); +/** + * @brief + * + * @param tcb + * @param task + * @param stack + * @param stack_size + * @param priority + * @param name + */ void qor_create_thread(qor_tcb_t *tcb, thread_func_t task, uint32_t *stack, uint32_t stack_size, uint8_t priority, const char *name); +/** + * @brief + * + * @param idle_tcb + * @param idle_task + * @param idle_stack + * @param idle_stack_size + * @return true + * @return false + */ bool qor_start(qor_tcb_t *idle_tcb, thread_func_t idle_task, uint32_t *idle_stack, uint32_t idle_stack_size); +/** + * @brief + * + * @param sleep_duration_ms + */ void qor_sleep(uint32_t sleep_duration_ms); // =========================================================================================================== // MAILBOX API // =========================================================================================================== +/** + * @brief + * + */ struct qor_mbox_t { qor_tcb_t *head; @@ -76,6 +112,10 @@ struct qor_mbox_t void **msgBuffer; }; +/** + * @brief + * + */ typedef struct { uint32_t count; @@ -88,12 +128,36 @@ typedef struct #define QOR_MBOX_ERROR 3 #define QOR_MBOX_FULL 4 +/** + * @brief + * + * @param mbox + * @param msgBuffer + * @param maxCount + */ void qor_mbox_init(qor_mbox_t *mbox, void **msgBuffer, uint32_t maxCount); + +/** + * @brief + * + * @param mbox + * @param msg + * @param wait_ms + * @return uint32_t + */ uint32_t qor_mbox_wait(qor_mbox_t *mbox, void **msg, uint32_t wait_ms); #define QOR_MBOX_OPTION_SEND_FRONT 1 #define QOR_MBOX_OPTION_SEND_BACK 2 +/** + * @brief + * + * @param mbox + * @param msg + * @param notifyOption + * @return uint32_t + */ uint32_t qor_mbox_notify(qor_mbox_t *mbox, void *msg, uint32_t notifyOption); #endif // QOR_H