Add full automotive RTOS project
Add kernel (Cortex-M0/M3/M4, Tricore, S32K, RISC-V ports), drivers, middleware (CAN stack, diagnostics, safety), applications, board support, build/test tooling, and documentation.
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* @file port.c
|
||||
* @brief RISC-V RV32 architecture specific port
|
||||
* @note RISC-V is emerging in automotive applications
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
#include "task.h"
|
||||
#include "scheduler.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
/* Context storage */
|
||||
uint32_t* current_task_sp = NULL;
|
||||
uint32_t* next_task_sp = NULL;
|
||||
|
||||
/* Machine Timer registers */
|
||||
#define MTIME_ADDR 0x0200BFF8
|
||||
#define MTIMECMP_ADDR 0x02004000
|
||||
|
||||
/* Initialize Architecture Port */
|
||||
void port_init(void) {
|
||||
/* Configure machine timer for 1ms interrupts */
|
||||
volatile uint32_t* mtime = (uint32_t*)MTIME_ADDR;
|
||||
volatile uint32_t* mtimecmp = (uint32_t*)MTIMECMP_ADDR;
|
||||
|
||||
uint32_t current_time = *mtime;
|
||||
*mtimecmp = current_time + (SystemCoreClock / 1000);
|
||||
|
||||
/* Enable machine timer interrupt */
|
||||
__asm volatile (
|
||||
"li t0, 0x80\n" /* Machine Timer Interrupt Enable */
|
||||
"csrs mie, t0\n"
|
||||
);
|
||||
|
||||
/* Enable global interrupts */
|
||||
__asm volatile (
|
||||
"csrsi mstatus, 0x8\n" /* Machine Interrupt Enable */
|
||||
);
|
||||
}
|
||||
|
||||
/* Start First Task */
|
||||
void port_start_first_task(void) {
|
||||
TaskHandle_t first_task = scheduler_get_current_task();
|
||||
|
||||
if (first_task == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Load task stack pointer */
|
||||
__asm volatile (
|
||||
"mv sp, %0\n"
|
||||
"ret\n"
|
||||
:
|
||||
: "r" (first_task->stack_pointer)
|
||||
);
|
||||
}
|
||||
|
||||
/* Context Switch */
|
||||
void port_context_switch(uint32_t* current_context, uint32_t* next_context) {
|
||||
current_task_sp = current_context;
|
||||
next_task_sp = next_context;
|
||||
|
||||
/* Trigger software interrupt */
|
||||
__asm volatile (
|
||||
"li t0, 0x8\n" /* Machine Software Interrupt */
|
||||
"csrs mip, t0\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* Initialize Task Stack */
|
||||
uint32_t* port_initialize_task_stack(TaskFunction_t task_function,
|
||||
void* parameters,
|
||||
uint32_t* stack_top) {
|
||||
uint32_t* stack_ptr = stack_top;
|
||||
|
||||
/* Align to 16 bytes */
|
||||
stack_ptr = (uint32_t*)((uint32_t)stack_ptr & ~0xF);
|
||||
|
||||
/* Initial stack frame */
|
||||
*(--stack_ptr) = (uint32_t)parameters; /* a0 */
|
||||
*(--stack_ptr) = 0; /* a1 */
|
||||
*(--stack_ptr) = 0; /* a2 */
|
||||
*(--stack_ptr) = 0; /* a3 */
|
||||
*(--stack_ptr) = 0; /* a4 */
|
||||
*(--stack_ptr) = 0; /* a5 */
|
||||
*(--stack_ptr) = 0; /* a6 */
|
||||
*(--stack_ptr) = 0; /* a7 */
|
||||
|
||||
*(--stack_ptr) = (uint32_t)task_function; /* ra */
|
||||
*(--stack_ptr) = 0; /* t0 */
|
||||
*(--stack_ptr) = 0; /* t1 */
|
||||
*(--stack_ptr) = 0; /* t2 */
|
||||
*(--stack_ptr) = 0; /* t3 */
|
||||
*(--stack_ptr) = 0; /* t4 */
|
||||
*(--stack_ptr) = 0; /* t5 */
|
||||
*(--stack_ptr) = 0; /* t6 */
|
||||
|
||||
*(--stack_ptr) = 0; /* s0 */
|
||||
*(--stack_ptr) = 0; /* s1 */
|
||||
*(--stack_ptr) = 0; /* s2 */
|
||||
*(--stack_ptr) = 0; /* s3 */
|
||||
*(--stack_ptr) = 0; /* s4 */
|
||||
*(--stack_ptr) = 0; /* s5 */
|
||||
*(--stack_ptr) = 0; /* s6 */
|
||||
*(--stack_ptr) = 0; /* s7 */
|
||||
*(--stack_ptr) = 0; /* s8 */
|
||||
*(--stack_ptr) = 0; /* s9 */
|
||||
*(--stack_ptr) = 0; /* s10 */
|
||||
*(--stack_ptr) = 0; /* s11 */
|
||||
|
||||
*(--stack_ptr) = 0; /* gp */
|
||||
*(--stack_ptr) = 0; /* tp */
|
||||
|
||||
/* mstatus */
|
||||
*(--stack_ptr) = 0x00001880; /* MPP = Machine mode */
|
||||
|
||||
return stack_ptr;
|
||||
}
|
||||
|
||||
/* Machine Timer Interrupt Handler */
|
||||
void machine_timer_interrupt_handler(void) {
|
||||
/* Clear interrupt */
|
||||
volatile uint32_t* mtimecmp = (uint32_t*)MTIMECMP_ADDR;
|
||||
volatile uint32_t* mtime = (uint32_t*)MTIME_ADDR;
|
||||
*mtimecmp = *mtime + (SystemCoreClock / 1000);
|
||||
|
||||
/* Call kernel tick handler */
|
||||
extern void kernel_tick_handler(void);
|
||||
kernel_tick_handler();
|
||||
}
|
||||
|
||||
/* Machine Software Interrupt Handler */
|
||||
void machine_software_interrupt_handler(void) {
|
||||
/* Clear interrupt */
|
||||
__asm volatile (
|
||||
"li t0, 0x8\n"
|
||||
"csrc mip, t0\n"
|
||||
);
|
||||
|
||||
/* Perform context switch */
|
||||
__asm volatile (
|
||||
/* Save current context */
|
||||
"addi sp, sp, -128\n"
|
||||
"sw ra, 0(sp)\n"
|
||||
"sw t0, 4(sp)\n"
|
||||
"sw t1, 8(sp)\n"
|
||||
"sw t2, 12(sp)\n"
|
||||
"sw s0, 16(sp)\n"
|
||||
"sw s1, 20(sp)\n"
|
||||
"sw a0, 24(sp)\n"
|
||||
"sw a1, 28(sp)\n"
|
||||
"sw a2, 32(sp)\n"
|
||||
"sw a3, 36(sp)\n"
|
||||
"sw a4, 40(sp)\n"
|
||||
"sw a5, 44(sp)\n"
|
||||
"sw a6, 48(sp)\n"
|
||||
"sw a7, 52(sp)\n"
|
||||
"sw s2, 56(sp)\n"
|
||||
"sw s3, 60(sp)\n"
|
||||
"sw s4, 64(sp)\n"
|
||||
"sw s5, 68(sp)\n"
|
||||
"sw s6, 72(sp)\n"
|
||||
"sw s7, 76(sp)\n"
|
||||
"sw s8, 80(sp)\n"
|
||||
"sw s9, 84(sp)\n"
|
||||
"sw s10, 88(sp)\n"
|
||||
"sw s11, 92(sp)\n"
|
||||
"sw t3, 96(sp)\n"
|
||||
"sw t4, 100(sp)\n"
|
||||
"sw t5, 104(sp)\n"
|
||||
"sw t6, 108(sp)\n"
|
||||
"csrr t0, mstatus\n"
|
||||
"sw t0, 112(sp)\n"
|
||||
"csrr t0, mepc\n"
|
||||
"sw t0, 116(sp)\n"
|
||||
|
||||
/* Save current stack pointer */
|
||||
"la t0, current_task_sp\n"
|
||||
"sw sp, 0(t0)\n"
|
||||
|
||||
/* Load next stack pointer */
|
||||
"la t0, next_task_sp\n"
|
||||
"lw sp, 0(t0)\n"
|
||||
|
||||
/* Restore next context */
|
||||
"lw ra, 0(sp)\n"
|
||||
"lw t0, 4(sp)\n"
|
||||
"lw t1, 8(sp)\n"
|
||||
"lw t2, 12(sp)\n"
|
||||
"lw s0, 16(sp)\n"
|
||||
"lw s1, 20(sp)\n"
|
||||
"lw a0, 24(sp)\n"
|
||||
"lw a1, 28(sp)\n"
|
||||
"lw a2, 32(sp)\n"
|
||||
"lw a3, 36(sp)\n"
|
||||
"lw a4, 40(sp)\n"
|
||||
"lw a5, 44(sp)\n"
|
||||
"lw a6, 48(sp)\n"
|
||||
"lw a7, 52(sp)\n"
|
||||
"lw s2, 56(sp)\n"
|
||||
"lw s3, 60(sp)\n"
|
||||
"lw s4, 64(sp)\n"
|
||||
"lw s5, 68(sp)\n"
|
||||
"lw s6, 72(sp)\n"
|
||||
"lw s7, 76(sp)\n"
|
||||
"lw s8, 80(sp)\n"
|
||||
"lw s9, 84(sp)\n"
|
||||
"lw s10, 88(sp)\n"
|
||||
"lw s11, 92(sp)\n"
|
||||
"lw t3, 96(sp)\n"
|
||||
"lw t4, 100(sp)\n"
|
||||
"lw t5, 104(sp)\n"
|
||||
"lw t6, 108(sp)\n"
|
||||
"lw t0, 112(sp)\n"
|
||||
"csrw mstatus, t0\n"
|
||||
"lw t0, 116(sp)\n"
|
||||
"csrw mepc, t0\n"
|
||||
"addi sp, sp, 128\n"
|
||||
|
||||
/* Return from interrupt */
|
||||
"mret\n"
|
||||
);
|
||||
}
|
||||
|
||||
/* Enter Critical Section */
|
||||
void port_disable_interrupts(void) {
|
||||
__asm volatile (
|
||||
"csrci mstatus, 0x8\n" /* Clear Machine Interrupt Enable */
|
||||
);
|
||||
}
|
||||
|
||||
/* Exit Critical Section */
|
||||
void port_enable_interrupts(void) {
|
||||
__asm volatile (
|
||||
"csrsi mstatus, 0x8\n" /* Set Machine Interrupt Enable */
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file portmacro.h
|
||||
* @brief RISC-V RV32 specific macros
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Data Types */
|
||||
typedef uint32_t port_stack_type_t;
|
||||
typedef uint32_t port_base_type_t;
|
||||
|
||||
/* Architecture Constants */
|
||||
#define PORT_STACK_GROWTH_DIRECTION (-1)
|
||||
#define PORT_BYTE_ALIGNMENT 16
|
||||
|
||||
/* Critical Section Macros */
|
||||
#define portENTER_CRITICAL() __asm volatile("csrci mstatus, 0x8")
|
||||
#define portEXIT_CRITICAL() __asm volatile("csrsi mstatus, 0x8")
|
||||
|
||||
/* Interrupt Control */
|
||||
#define portENABLE_INTERRUPTS() __asm volatile("csrsi mstatus, 0x8")
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile("csrci mstatus, 0x8")
|
||||
|
||||
/* Context Switch */
|
||||
#define portYIELD() __asm volatile("li t0, 0x8\ncsrs mip, t0")
|
||||
#define portYIELD_FROM_ISR() __asm volatile("li t0, 0x8\ncsrs mip, t0")
|
||||
|
||||
/* Memory Barriers */
|
||||
#define portMEMORY_BARRIER() __asm volatile("fence")
|
||||
#define portSYNC_BARRIER() __asm volatile("fence")
|
||||
#define portINSTRUCTION_BARRIER() __asm volatile("fence.i")
|
||||
|
||||
/* NOP */
|
||||
#define portNOP() __asm volatile("nop")
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
Reference in New Issue
Block a user