RTOS源码
下载FreeRTOS 202210-LTS,portable
文件夹保留/MemMang
和/GCC/RISC-V
+---freertos
| | FreeRTOSConfig.h //RTOS 配置文件
| \---kernel //RTOS源文件
| | croutine.c
| | event_groups.c
| | list.c
| | manifest.yml
| | queue.c
| | Quick_Start_Guide.url
| | stream_buffer.c
| | tasks.c
| | timers.c
| +---include //所有 header 文件
| \---portable //移植接口文件
| | riscv_application_isr.c //创建文件实现中断接口
| +---MemMang
| \---RISC-V
\---src
| linker.ld
| main.c
\---bsp
\---driver
+---gpio
+---riscv_mc
+---smbus_mailbox
\---uart
关键配置
时基
内置模块类型
#define portasmHAS_SIFIVE_CLINT 0
#define portasmHAS_MTIME 1
#define portasmADDITIONAL_CONTEXT_SIZE 0
Machine Timer地址
#define configMTIME_BASE_ADDRESS ( RISCV_UCPU_INST_BASE_ADDR + 0x400 )
#define configMTIMECMP_BASE_ADDRESS ( RISCV_UCPU_INST_BASE_ADDR + 0x410 )
时钟配置
#define configCPU_CLOCK_HZ ( ( unsigned long ) 90000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
中断
设置中断入口
la t0, freertos_risc_v_trap_handler
csrw mtvec, t0
重定义中断和异常接口函数,参数为mcause
寄存器的值
void freertos_risc_v_application_interrupt_handler( uint32_t ulMcause )
{
/* Not implemented yet! */
printf( "interrupt: 0x%04x\r\n", ulMcause );
}
/*-----------------------------------------------------------*/
void freertos_risc_v_application_exception_handler( uint32_t ulMcause )
{
/* Not implemented yet! */
printf( "exception: 0x%04x\r\n", ulMcause );
}
中断和异常解析
.section .text.freertos_risc_v_trap_handler
.align 8
freertos_risc_v_trap_handler:
portcontextSAVE_CONTEXT_INTERNAL
csrr a0, mcause
csrr a1, mepc
bge a0, x0, synchronous_exception
asynchronous_interrupt:
store_x a1, 0( sp ) /* Save unmodified exception return address. */
load_x sp, xISRStackTop /* Switch to ISR stack. */
j handle_interrupt
synchronous_exception:
addi a1, a1, 4 /* Update exception return address to the instruction after the instruction that generated the exeption. */
store_x a1, 0( sp ) /* Save updated exception return address. */
load_x sp, xISRStackTop /* Switch to ISR stack. */
j handle_exception
handle_interrupt:
#if( portasmHAS_MTIME != 0 )
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
addi t0, x0, 1
slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */
addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */
bne a0, t1, application_interrupt_handler /* mtimer更新定时器,其余中断进入重定义的中断接口 */
portUPDATE_MTIMER_COMPARE_REGISTER
call xTaskIncrementTick
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
call vTaskSwitchContext
j processed_source
#endif /* portasmHAS_MTIME */
application_interrupt_handler:
call freertos_risc_v_application_interrupt_handler
j processed_source
handle_exception:
/* a0 contains mcause. */
li t0, 11 /* 11 == environment call. */
bne a0, t0, application_exception_handler /* ecall执行切换,其余异常进入重定义的异常接口 */
call vTaskSwitchContext
j processed_source
application_exception_handler:
call freertos_risc_v_application_exception_handler
j processed_source /* No other exceptions handled yet. */
processed_source:
portcontextRESTORE_CONTEXT
- 中断状态下
mepc
保持不变,异常状态下mepc
指向下一条指令mepc+4
- MTimer提供OS时基,产生的中断更新定时器;其余中断由用户自定义管理
#define portYIELD() __asm volatile( "ecall" );
,ecall
指令通知上下文切换;其余异常由用户自定义管理