STM32F103C8T6 Port
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(RTOS_STM32F103C8T6 C ASM)
|
||||
|
||||
file(GLOB SOURCES ${CMAKE_CURRENT_LIST_DIR}/*.c)
|
||||
if (CMAKE_C_COMPILER_ID MATCHES GNU)
|
||||
file(GLOB ARM_SOURCES ${CMAKE_CURRENT_LIST_DIR}/*_gnu.S)
|
||||
endif ()
|
||||
if (CMAKE_C_COMPILER_ID MATCHES ARMCC)
|
||||
file(GLOB ARM_SOURCES ${CMAKE_CURRENT_LIST_DIR}/*_armcc.S)
|
||||
endif ()
|
||||
|
||||
set(RTOS_PORT_SOURCES ${SOURCES} ${ARM_SOURCES} PARENT_SCOPE)
|
||||
set(RTOS_PORT_INCLUDE_PATH ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE)
|
||||
@@ -0,0 +1,172 @@
|
||||
#ifndef INCLUDED_CPU_H
|
||||
#define INCLUDED_CPU_H
|
||||
|
||||
#ifndef INCLUDED_STM32F1XX_H
|
||||
#define INCLUDED_STM32F1XX_H
|
||||
#include <stm32f1xx.h>
|
||||
#endif /*INCLUDED_STM32F1XX_H*/
|
||||
|
||||
#ifndef INCLUDED_OS_TYPES_H
|
||||
#include <os_types.h>
|
||||
#endif /*INCLUDED_OS_TYPES_H*/
|
||||
|
||||
#ifndef INCLUDED_OS_COMPILER_H
|
||||
#include <os_compiler.h>
|
||||
#endif /*INCLUDED_OS_COMPILER_H*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
|
||||
#define os_port_disable_irq CMSIS_disable_irq
|
||||
#define os_port_enable_irq CMSIS_enable_irq
|
||||
#define os_port_save_disable_irq cpu_save_disable_irq
|
||||
#define os_port_restore_irq cpu_restore_irq
|
||||
#define os_port_save_disable_irq_in_isr cpu_save_disable_irq_in_isr
|
||||
#define os_port_restore_irq_in_isr cpu_restore_irq_in_isr
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
#define CPU_SYSCALL_ID 0x00
|
||||
#define CPU_SYSCALL_OP_SAVE_DISABLE_IRQ 0x00
|
||||
#define CPU_SYSCALL_OP_RESTORE_IRQ 0x01
|
||||
#define CPU_SYSCALL_OP_SCHED 0x02
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
|
||||
#if defined(__CC_ARM) /* armcc (AC5) */
|
||||
|
||||
#define SVC_CALL_ARGS0(num, type, name) \
|
||||
__svc(num) type name(void)
|
||||
|
||||
#define SVC_CALL_ARGS1(num, type, name, a0) \
|
||||
__svc(num) type name(os_uintptr_t a0)
|
||||
|
||||
#define SVC_CALL_ARGS2(num, type, name, a0, a1) \
|
||||
__svc(num) type name(os_uintptr_t a0, os_uintptr_t a1)
|
||||
|
||||
#define SVC_CALL_ARGS3(num, type, name, a0, a1, a2) \
|
||||
__svc(num) type name(os_uintptr_t a0, os_uintptr_t a1, os_uintptr_t a2)
|
||||
|
||||
#define SVC_CALL_ARGS4(num, type, name, a0, a1, a2, a3) \
|
||||
__svc(num) type name(os_uintptr_t a0, os_uintptr_t a1, os_uintptr_t a2, os_uintptr_t a3)
|
||||
|
||||
|
||||
#elif defined(__GNUC__) /* gcc */
|
||||
|
||||
#define SVC_CALL_ARGS0(num, type, name) \
|
||||
OS_STATIC_FORCE_INLINE type name(void) { \
|
||||
register os_uintptr_t r0 __asm__("r0")=0; \
|
||||
__asm__ volatile ("svc " #num : : : "memory"); \
|
||||
return (type)r0; \
|
||||
}
|
||||
|
||||
#define SVC_CALL_ARGS1(num, type, name, a1) \
|
||||
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1) { \
|
||||
register os_uintptr_t r0 __asm__("r0") = a1; \
|
||||
__asm__ volatile ("svc " #num :"=r"(r0):"r"(r0) : "memory"); \
|
||||
return (type)r0; \
|
||||
}
|
||||
|
||||
#define SVC_CALL_ARGS2(num, type, name, a1, a2) \
|
||||
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1, os_uintptr_t a2) { \
|
||||
register os_uintptr_t r0 __asm__("r0") = a1;\
|
||||
register os_uintptr_t r1 __asm__("r1") = a2;\
|
||||
__asm__ volatile ("svc " #num :"=r"(r0) :"r"(r0), "r"(r1) : "memory"); \
|
||||
return (type)r0; \
|
||||
}
|
||||
|
||||
#define SVC_CALL_ARGS3(num, type, name, a1, a2, a3) \
|
||||
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1, os_uintptr_t a2, os_uintptr_t a3) { \
|
||||
register os_uintptr_t r0 __asm__("r0") = a1; \
|
||||
register os_uintptr_t r1 __asm__("r1") = a2; \
|
||||
register os_uintptr_t r2 __asm__("r2") = a3; \
|
||||
__asm__ volatile ("svc " #num :"=r"(r0) :"r"(r0), "r"(r1), "r"(r2) : "memory"); \
|
||||
return (type)r0; \
|
||||
}
|
||||
|
||||
#define SVC_CALL_ARGS4(num, type, name, a1, a2, a3, a4) \
|
||||
OS_STATIC_FORCE_INLINE type name(os_uintptr_t a1, os_uintptr_t a2, os_uintptr_t a3, os_uintptr_t a4) { \
|
||||
register os_uintptr_t r0 __asm__("r0") = a1; \
|
||||
register os_uintptr_t r1 __asm__("r1") = a2; \
|
||||
register os_uintptr_t r2 __asm__("r2") = a3; \
|
||||
register os_uintptr_t r3 __asm__("r3") = a4; \
|
||||
__asm__ volatile ("svc " #num :"=r"(r0) :"r"(r0), "r"(r1), "r"(r2), "r"(r3) : "memory"); \
|
||||
return (type)r0; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
SVC_CALL_ARGS1(0, os_uint_t, cpu_svc0_args1, a1);
|
||||
SVC_CALL_ARGS2(0, void, cpu_svc0_args2, a1, a2);
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
os_uint_t cpu_save_disable_irq_in_svc(void){
|
||||
return cpu_svc0_args1(CPU_SYSCALL_OP_SAVE_DISABLE_IRQ);
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void cpu_restore_irq_in_svc(os_uint_t level){
|
||||
cpu_svc0_args2(CPU_SYSCALL_OP_RESTORE_IRQ, level);
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void cpu_sched_in_svc(void){
|
||||
cpu_svc0_args1(CPU_SYSCALL_OP_SCHED);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
int is_cpu_in_privilege(void){
|
||||
// 1. 检查是否在中断/异常中 (IPSR != 0 表示 Handler 模式)
|
||||
if ( __get_IPSR() != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 2. 如果在 Thread 模式,检查 CONTROL 寄存器
|
||||
return ((__get_CONTROL() & 0x01) == 0)?1:0;
|
||||
}
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
os_uint_t cpu_save_disable_irq_in_isr(void){
|
||||
os_uint_t level = __get_BASEPRI();
|
||||
__set_BASEPRI((OS_CFG_SYSCALL_PRIORITY+1) << 4);
|
||||
return level;
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void cpu_restore_irq_in_isr(os_uint_t value){
|
||||
__set_BASEPRI(value);
|
||||
}
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
os_uint_t cpu_save_disable_irq(void){
|
||||
if(is_cpu_in_privilege()){
|
||||
return cpu_save_disable_irq_in_isr();
|
||||
}else{
|
||||
return cpu_save_disable_irq_in_svc();
|
||||
}
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void cpu_restore_irq(os_uint_t value){
|
||||
if(is_cpu_in_privilege()){
|
||||
cpu_restore_irq_in_isr(value);
|
||||
}else{
|
||||
cpu_restore_irq_in_svc(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /*INCLUDED_CPU_H*/
|
||||
@@ -0,0 +1,147 @@
|
||||
#include "os_port.h"
|
||||
#include "os_stack.h"
|
||||
#include "os_macros.h"
|
||||
#include "os_align.h"
|
||||
#include "os_compiler.h"
|
||||
#include "os_systick.h"
|
||||
#include "os_sched.h"
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
volatile os_uint_t svc_exc_return;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
typedef struct {
|
||||
#if(OS_CFG_CPU_FPU_PRESENT)
|
||||
os_uintptr_t s16;
|
||||
os_uintptr_t s17;
|
||||
os_uintptr_t s18;
|
||||
os_uintptr_t s19;
|
||||
os_uintptr_t s20;
|
||||
os_uintptr_t s21;
|
||||
os_uintptr_t s22;
|
||||
os_uintptr_t s23;
|
||||
os_uintptr_t s24;
|
||||
os_uintptr_t s25;
|
||||
os_uintptr_t s26;
|
||||
os_uintptr_t s27;
|
||||
os_uintptr_t s28;
|
||||
os_uintptr_t s29;
|
||||
os_uintptr_t s30;
|
||||
os_uintptr_t s31;
|
||||
#endif
|
||||
/* ==== 以下为手动压栈部分 ==== */
|
||||
os_uintptr_t exc_return; /* r2 - LR */ /* 这是地址最小的位置 */
|
||||
os_uintptr_t control; /* r3 */
|
||||
os_uintptr_t r4;
|
||||
os_uintptr_t r5;
|
||||
os_uintptr_t r6;
|
||||
os_uintptr_t r7;
|
||||
os_uintptr_t r8;
|
||||
os_uintptr_t r9;
|
||||
os_uintptr_t r10;
|
||||
os_uintptr_t r11;
|
||||
/* ==== 以下为自动压栈部分 ==== */
|
||||
os_uintptr_t r0;
|
||||
os_uintptr_t r1;
|
||||
os_uintptr_t r2;
|
||||
os_uintptr_t r3;
|
||||
os_uintptr_t r12;
|
||||
os_uintptr_t lr;
|
||||
os_uintptr_t pc;
|
||||
os_uintptr_t xPSR;
|
||||
}os_stack_frame_t;
|
||||
|
||||
#define STACK_FRAME_SIZE sizeof(os_stack_frame_t)
|
||||
|
||||
os_stack_t os_port_cpu_stack_init(os_task_entry_t entry, void* param
|
||||
, void* stack_base, os_size_t stack_size, void(*exit_entry)(void)){
|
||||
os_uintptr_t stack_max = (os_uintptr_t)((uint8_t *) stack_base + stack_size);
|
||||
os_uintptr_t real_max = OS_ALIGN_DOWN(stack_max, OS_ALIGN_SIZE); /* 实际栈顶的位置,对齐后的位置 */
|
||||
stack_size -= (stack_max - real_max); /* 实际栈大小 */
|
||||
|
||||
uint8_t flag = 0x01;
|
||||
os_stack_frame_t* p_frame = (os_stack_frame_t*)(real_max - STACK_FRAME_SIZE);
|
||||
for(os_size_t i=0; i<STACK_FRAME_SIZE/sizeof(os_uintptr_t); i++){
|
||||
((os_uintptr_t*)(p_frame))[i] = ((os_uintptr_t)flag<<24)|((os_uintptr_t)flag<<16)|((os_uintptr_t)flag<<8)|flag;
|
||||
flag++;
|
||||
}
|
||||
|
||||
p_frame->r0 = (os_uintptr_t)param; /* 任务参数 */
|
||||
p_frame->pc = (os_uintptr_t)entry; /* 任务入口 */
|
||||
p_frame->lr = (os_uintptr_t)exit_entry; /* 退出地址 */
|
||||
|
||||
p_frame->xPSR = (1u << 24); /* THUMB */
|
||||
p_frame->control = 0x03; /* 任务使用用户权限,栈使用 PSP */
|
||||
p_frame->exc_return = 0xFFFFFFFDul; /* 任务在中断中切换,这里是退出中断的设置 */
|
||||
|
||||
os_stack_t stack;
|
||||
stack.min = (os_uintptr_t)stack_base;
|
||||
stack.max = (os_uintptr_t)real_max;
|
||||
stack.type = kOsStackType_MaxToMin;
|
||||
stack.sp = p_frame;
|
||||
return stack;
|
||||
}
|
||||
|
||||
void os_port_init(void){
|
||||
|
||||
}
|
||||
|
||||
void os_port_startup(void){
|
||||
NVIC_SetPriority(PendSV_IRQn, 0xff);
|
||||
NVIC_SetPriority(SVCall_IRQn, OS_CFG_SYSCALL_PRIORITY);
|
||||
SysTick_Config(SystemCoreClock/OS_CFG_TICKS_PER_SECOND);
|
||||
}
|
||||
|
||||
void os_port_send_context_switch_request(void){
|
||||
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
|
||||
void os_port_clear_context_switch_request(void){
|
||||
SCB->ICSR &= ~SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
|
||||
void os_sched(void){
|
||||
if(is_cpu_in_privilege()){
|
||||
os_sched_in_isr();
|
||||
}else{
|
||||
cpu_sched_in_svc();
|
||||
}
|
||||
}
|
||||
|
||||
void SysTick_Handler(void){
|
||||
os_systick_tick();
|
||||
}
|
||||
|
||||
void SVC_Handler_C(os_uintptr_t* svc_args){
|
||||
// 读取系统调用号:它存储在原本的 PC 指令前两个字节
|
||||
uint8_t svc_number = ((uint8_t *)svc_args[6])[-2];
|
||||
switch (svc_number) {
|
||||
case CPU_SYSCALL_ID:{
|
||||
os_uint_t op = svc_args[0];
|
||||
switch (op) {
|
||||
case CPU_SYSCALL_OP_SAVE_DISABLE_IRQ:{
|
||||
svc_args[0] = os_port_save_disable_irq_in_isr();
|
||||
break;
|
||||
}
|
||||
case CPU_SYSCALL_OP_RESTORE_IRQ:{
|
||||
os_port_restore_irq_in_isr(svc_args[1]);
|
||||
break;
|
||||
}
|
||||
case CPU_SYSCALL_OP_SCHED:{
|
||||
os_sched_in_isr();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
cpu_clz PROC
|
||||
EXPORT cpu_clz
|
||||
CLZ R0, R0
|
||||
BX LR
|
||||
ENDP
|
||||
|
||||
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler
|
||||
IMPORT svc_exc_return
|
||||
IMPORT SVC_Handler_C
|
||||
tst lr, #4 // 检查 EXC_RETURN (LR) 的位 2
|
||||
ite eq
|
||||
mrseq r0, msp // 如果位 2 是 0,栈帧在 MSP
|
||||
mrsne r0, psp // 如果位 2 是 1,栈帧在 PSP
|
||||
ldr r1, =svc_exc_return
|
||||
str lr, [r1]
|
||||
bl SVC_Handler_C // 跳转到 C 实现,r0 作为第一个参数传入
|
||||
ldr r1, =svc_exc_return
|
||||
ldr lr, [r1]
|
||||
bx lr
|
||||
ENDP
|
||||
|
||||
PendSV_Handler PROC
|
||||
EXPORT PendSV_Handler
|
||||
IMPORT g_os_port_switch_from_sp
|
||||
IMPORT g_os_port_switch_to_sp
|
||||
IMPORT os_port_on_switch_success
|
||||
mrs r1, primask // 获取值
|
||||
cpsid i // 关闭中断
|
||||
PUSH {R1}
|
||||
|
||||
LDR R1, =g_os_port_switch_from_sp // 加载当前任务指针地址
|
||||
LDR R1, [R1] // 加载 g_os_port_switch_from_sp 的值
|
||||
CBZ R1, __PendSV_SwitchTo
|
||||
|
||||
/* ---- 压栈 ---- */
|
||||
MRS R0, PSP
|
||||
MOV R2, LR
|
||||
MRS R3, CONTROL
|
||||
STMDB R0!, {R2-R11}
|
||||
|
||||
/* ---- sp值保存到变量中 ---- */
|
||||
STR R0, [R1] // 将 sp 的值加载到 R0
|
||||
|
||||
__PendSV_SwitchTo
|
||||
BL os_port_on_switch_success // 执行切换完成后的设置
|
||||
|
||||
/* ---- 加载目标栈 ---- */
|
||||
LDR R2, =g_os_port_switch_to_sp // 获取目标任务指针变量地址
|
||||
LDR R2, [R2] // 获取切换目标任务的指针
|
||||
LDR R0, [R2] // 获取目标任务的 sp 指针
|
||||
LDMIA R0!, {R2-R11} // 恢复 R2-R11 寄存器的值
|
||||
MOV LR, R2 // 恢复 LR 寄存器值
|
||||
MSR CONTROL, R3 // 恢复 CONTROL 寄存器值, 这里是在 ISR 中,设置暂时不生效,直到退出 ISR 才生效,所以没有问题
|
||||
ISB // 设置 CONTROL 后确保生效
|
||||
|
||||
MSR PSP, R0 // 更新 PSP 指向下一个任务的栈
|
||||
POP {R1}
|
||||
MSR PRIMASK, R1 // 开中断
|
||||
BX LR
|
||||
|
||||
ENDP
|
||||
|
||||
END
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "os_config.h"
|
||||
|
||||
.syntax unified
|
||||
.thumb
|
||||
|
||||
.section .text.PendSV_Handler,"ax",%progbits
|
||||
.global g_os_port_switch_from_sp
|
||||
.global g_os_port_switch_to_sp
|
||||
.global PendSV_Handler
|
||||
.thumb_func
|
||||
PendSV_Handler:
|
||||
mrs r1, primask // 获取值
|
||||
cpsid i // 关闭中断
|
||||
PUSH {R1}
|
||||
|
||||
LDR R1, =g_os_port_switch_from_sp // 加载当前任务指针地址
|
||||
LDR R1, [R1] // 加载 g_os_port_switch_from_sp 的值
|
||||
CBZ R1, __PendSV_SwitchTo
|
||||
|
||||
/* ---- 压栈 ---- */
|
||||
MRS R0, PSP
|
||||
#if(OS_CFG_CPU_FPU_PRESENT)
|
||||
TST LR, #0x10 // 测试第4位如果为0压栈浮点寄存器
|
||||
VSTMDBEQ R0!, {S16-S31}
|
||||
#endif
|
||||
MOV R2, LR
|
||||
MRS R3, CONTROL
|
||||
STMDB R0!, {R2-R11}
|
||||
|
||||
/* ---- sp值保存到变量中 ---- */
|
||||
STR R0, [R1] // 将 sp 的值加载到 R0
|
||||
|
||||
__PendSV_SwitchTo:
|
||||
BL os_port_on_switch_success // 执行切换完成后的设置
|
||||
|
||||
/* ---- 加载目标栈 ---- */
|
||||
LDR R2, =g_os_port_switch_to_sp // 获取目标任务指针变量地址
|
||||
LDR R2, [R2] // 获取切换目标任务的指针
|
||||
LDR R0, [R2] // 获取目标任务的 sp 指针
|
||||
LDMIA R0!, {R2-R11} // 恢复 R2-R11 寄存器的值
|
||||
MOV LR, R2 // 恢复 LR 寄存器值
|
||||
MSR CONTROL, R3 // 恢复 CONTROL 寄存器值, 这里是在 ISR 中,设置暂时不生效,直到退出 ISR 才生效,所以没有问题
|
||||
ISB // 设置 CONTROL 后确保生效
|
||||
#if(OS_CFG_CPU_FPU_PRESENT)
|
||||
TST LR, #0x10
|
||||
IT EQ
|
||||
VLDMIAEQ R0!, {S16-S31}
|
||||
#endif
|
||||
MSR PSP, R0 // 更新 PSP 指向下一个任务的栈
|
||||
POP {R1}
|
||||
MSR PRIMASK, R1 // 开中断
|
||||
BX LR
|
||||
|
||||
|
||||
.section .text.SVC_Handler,"ax",%progbits
|
||||
.global SVC_Handler
|
||||
.global svc_exc_return
|
||||
.global SVC_Handler_C
|
||||
.type SVC_Handler, %function
|
||||
SVC_Handler:
|
||||
tst lr, #4 // 检查 EXC_RETURN (LR) 的位 2
|
||||
ite eq
|
||||
mrseq r0, msp // 如果位 2 是 0,栈帧在 MSP
|
||||
mrsne r0, psp // 如果位 2 是 1,栈帧在 PSP
|
||||
ldr r1, =svc_exc_return
|
||||
str lr, [r1]
|
||||
bl SVC_Handler_C // 跳转到 C 实现,r0 作为第一个参数传入
|
||||
ldr r1, =svc_exc_return
|
||||
ldr lr, [r1]
|
||||
bx lr
|
||||
|
||||
.section .text.cpu_clz,"ax",%progbits
|
||||
.global cpu_clz
|
||||
.thumb_func
|
||||
cpu_clz:
|
||||
CLZ R0, R0
|
||||
BX LR
|
||||
|
||||
.align 4
|
||||
.end
|
||||
Reference in New Issue
Block a user