Add VM task and source files to build system, wip: qor API

This commit is contained in:
Anthony Rabine 2023-07-26 21:41:56 +02:00
parent 802f818735
commit 5104f9a6c0
5 changed files with 176 additions and 68 deletions

View file

@ -42,12 +42,14 @@ set(OST_SRCS
system/ff/ff.c system/ff/ff.c
system/ff/ffsystem.c system/ff/ffsystem.c
system/ff/ff_stubs.c system/ff/ff_stubs.c
chip32/chip32_vm.c
) )
include_directories( include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/library ${CMAKE_CURRENT_SOURCE_DIR}/library
${CMAKE_CURRENT_SOURCE_DIR}/system ${CMAKE_CURRENT_SOURCE_DIR}/system
${CMAKE_CURRENT_SOURCE_DIR}/system/ff ${CMAKE_CURRENT_SOURCE_DIR}/system/ff
${CMAKE_CURRENT_SOURCE_DIR}/chip32
) )
# ================================================================================================== # ==================================================================================================

View file

@ -30,8 +30,8 @@
// =========================================================================================================== // ===========================================================================================================
// CONSTANTS / DEFINES // CONSTANTS / DEFINES
// =========================================================================================================== // ===========================================================================================================
const uint8_t DEBUG_PIN = 1;
const uint8_t LED_PIN = 14; // GP 14 const uint8_t LED_PIN = 14;
const uint8_t LCD_DC = 8; const uint8_t LCD_DC = 8;
const uint8_t LCD_CS = 9; const uint8_t LCD_CS = 9;
@ -99,6 +99,10 @@ void ost_system_initialize()
gpio_init(LED_PIN); gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT); gpio_set_dir(LED_PIN, GPIO_OUT);
//------------------- Init DEBUG PIN
gpio_init(DEBUG_PIN);
gpio_set_dir(DEBUG_PIN, GPIO_OUT);
//------------------- Init UART //------------------- Init UART
// Set up our UART with the required speed. // Set up our UART with the required speed.
@ -180,6 +184,25 @@ void system_putc(char ch)
uart_putc_raw(UART_ID, ch); uart_putc_raw(UART_ID, ch);
} }
#include <time.h>
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 ost_hal_gpio_get(ost_hal_gpio_t gpio)
{ {
int value = 0; int value = 0;
@ -205,6 +228,9 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value)
case OST_GPIO_DEBUG_LED: case OST_GPIO_DEBUG_LED:
gpio_put(LED_PIN, value); gpio_put(LED_PIN, value);
break; break;
case OST_GPIO_DEBUG_PIN:
gpio_put(DEBUG_PIN, value);
break;
// Nothing to do for these inputes // Nothing to do for these inputes
case OST_GPIO_ROTARY_A: case OST_GPIO_ROTARY_A:

View file

@ -6,47 +6,6 @@
#include "qor.h" #include "qor.h"
#include "rotary-button.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 "sdcard.h"
#include <stdint.h> #include <stdint.h>
@ -54,13 +13,76 @@ int main(void)
#include <stdlib.h> #include <stdlib.h>
#include "audio_player.h" #include "audio_player.h"
#include "chip32_vm.h"
void ost_hal_panic() 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 qor_tcb_t AudioTcb;
static uint32_t AudioStack[4096]; static uint32_t AudioStack[4096];
@ -82,14 +104,8 @@ static int dbg_state = 0;
static void audio_callback(void) static void audio_callback(void)
{ {
dbg_state = 1 - dbg_state; dbg_state = 1 - dbg_state;
gpio_put(1, dbg_state);
qor_mbox_notify(&AudioMailBox, (void **)&wake_up, QOR_MBOX_OPTION_SEND_BACK); qor_mbox_notify(&AudioMailBox, (void **)&wake_up, QOR_MBOX_OPTION_SEND_BACK);
} }
#include <time.h>
clock_t clock()
{
return (clock_t)time_us_64() / 1000;
}
void show_duration(uint32_t millisecondes) void show_duration(uint32_t millisecondes)
{ {
@ -116,16 +132,12 @@ void AudioTask(void *args)
ost_audio_register_callback(audio_callback); ost_audio_register_callback(audio_callback);
gpio_init(1);
gpio_set_dir(1, GPIO_OUT);
static bool onetime = true; static bool onetime = true;
gpio_put(1, 0);
while (1) while (1)
{ {
debug_printf("\r\n-------------------------------------------------------\r\nPlaying: out2.wav\r\n"); 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_play("out2.wav");
ost_audio_event_t *e = NULL; ost_audio_event_t *e = NULL;
@ -145,9 +157,8 @@ void AudioTask(void *args)
} while (isPlaying); } while (isPlaying);
uint32_t executionTime = ost_system_stopwatch_stop();
ost_audio_stop(); ost_audio_stop();
clock_t endTime = clock();
uint32_t executionTime = endTime - startTime;
debug_printf("\r\nPackets: %d\r\n", count); debug_printf("\r\nPackets: %d\r\n", count);
show_duration(executionTime); show_duration(executionTime);
@ -190,14 +201,15 @@ int main()
// 3. Filesystem / SDCard initialization // 3. Filesystem / SDCard initialization
filesystem_mount(); filesystem_mount();
// 4. Initialize OS and threads // 4. Initialize OS before all other OS calls
qor_init(125000000UL); qor_init(125000000UL);
// qor_create_thread(&tcb1, UserTask_1, 2, "UserTask_1"); // 5. Initialize the tasks
// qor_create_thread(&tcb2, UserTask_2, 1, "UserTask_2"); 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 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); qor_start(&IdleTcb, IdleTask, IdleStack, 1024);
return 0; return 0;
} }
#endif

View file

@ -38,6 +38,7 @@ extern "C"
OST_GPIO_ROTARY_A, OST_GPIO_ROTARY_A,
OST_GPIO_ROTARY_B, OST_GPIO_ROTARY_B,
OST_GPIO_DEBUG_LED, OST_GPIO_DEBUG_LED,
OST_GPIO_DEBUG_PIN,
} ost_hal_gpio_t; } ost_hal_gpio_t;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -47,6 +48,9 @@ extern "C"
void system_putc(char ch); void system_putc(char ch);
void ost_system_delay_ms(uint32_t delay); 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_play(const char *filename);
void ost_audio_stop(); void ost_audio_stop();
int ost_audio_process(); int ost_audio_process();

View file

@ -1,6 +1,8 @@
#ifndef QOR_H #ifndef QOR_H
#define QOR_H #define QOR_H
#define QOR_VERSION "0.1"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -23,24 +25,24 @@ typedef void (*thread_func_t)(void *args);
*/ */
typedef enum typedef enum
{ {
qor_tcb_state_active, qor_tcb_state_active, //!< Thread is active (and can be scheduled or is currently running)
qor_tcb_state_sleep qor_tcb_state_sleep //!< Thread is wating for mailbox or sleep
} qor_tcb_state_t; } qor_tcb_state_t;
typedef struct qor_mbox_t qor_mbox_t; //!< Foreward declaration
/** /**
* @brief Thread Control Block * @brief Thread Control Block
* *
* IMPORTANT! keep the stack pointer on top, it is required by the task switch assembly * 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 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 *next; //!< Pointer to circular-linked-list of TCBs
struct TCB *wait_next; //!< Next TCB in waiting list 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 qor_tcb_state_t state; //!< TCB active or free
uint32_t wait_time; //!< Timeout for mbox maiting or sleep 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 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 // Debug/traces
uint32_t stack_usage; uint32_t stack_usage;
uint32_t *stack_bottom; uint32_t *stack_bottom;
bool so; // stack overflow detected bool so; //!< stack overflow detected
} qor_tcb_t; } 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); 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); 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); 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); void qor_sleep(uint32_t sleep_duration_ms);
// =========================================================================================================== // ===========================================================================================================
// MAILBOX API // MAILBOX API
// =========================================================================================================== // ===========================================================================================================
/**
* @brief
*
*/
struct qor_mbox_t struct qor_mbox_t
{ {
qor_tcb_t *head; qor_tcb_t *head;
@ -76,6 +112,10 @@ struct qor_mbox_t
void **msgBuffer; void **msgBuffer;
}; };
/**
* @brief
*
*/
typedef struct typedef struct
{ {
uint32_t count; uint32_t count;
@ -88,12 +128,36 @@ typedef struct
#define QOR_MBOX_ERROR 3 #define QOR_MBOX_ERROR 3
#define QOR_MBOX_FULL 4 #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); 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); 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_FRONT 1
#define QOR_MBOX_OPTION_SEND_BACK 2 #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); uint32_t qor_mbox_notify(qor_mbox_t *mbox, void *msg, uint32_t notifyOption);
#endif // QOR_H #endif // QOR_H