第一次发帖请大家见谅,请大家多多吐槽。
在STM8S207C8上跑AtomThreads嵌入式系统,AtomThreads官网有移植到STM8S207C8的工程可以下载。
Atomthreads is a free, lightweight, portable, real-time scheduler for embedded systems.
跨平台的内核代码在kernel文件夹中。移植到特定单片机的代码在port文件夹中。
支持编译器Cosmic,Raisonance,IAR。
开发环境:STVD + Cosmic ,MCU:STM8S207C8(6K RAM)。
默认内存模式使用
modsl0:将数据全部放到page0(0x0~0xFF)之外。
(mods0:将数据放到page0,使用@near放到page0之外)
创建工程:
需要注意的地方:
C Compiler Memory Model:"+modsl0"
Linker Input : Zero Page from 0x2 ~0xFF(空出前面2个bytes)
Linker Input : Ram from 0x100~0x17BF。
0x100~0x17BF:应用使用
0x17C0~0x17FF:启动堆栈
内存主要消耗为线程(任务)堆栈。每个线程堆栈保存自己调度时的寄存器,没有单独的中断堆栈(线程堆栈需要足够堆栈处理中断)。
128bytes足够线程调度使用,需要根据线程使用情况增大。我在使用过程中出现了3个任务的溢出,所有把所有任务的堆栈全部设成了256。
中断使用被其中断的任务的堆栈。中断中需要调用内核引发任务切换需要调用:atomIntEnter() atomIntExit()。如果中断中需要调用内核,需要给中断处理函数添加@svlreg修饰符(保存虚拟寄存器c_lreg)。
Atom任务切换利用当调用一个C函数时编译器自动入栈全部CPU和虚拟寄存器。
自己将自己调度出去(cooperative context switches):调用函数时,所有的需要保存的寄存器编译器自动入栈。任务切换时没有寄存器需要被保存。
中断调度非中断任务(preemptive switches):中断处理函数自动保存所有寄存器。Cosmic中断处理函数调用C函数时保存CPU寄存器和c_x,c_y。对于AtomThreads强制中断处理函数保存c_lreg。保证中断处理函数的c_lreg(被编译器用于处理longs、floats)在任务调度时被保存,longs可以在调用内核代码时使用。
任务切换汇编实现在atomport_asm_cosmic.s(备注写的非常清晰~)
_archContextSwitch:
将当前任务的堆栈地址保存到TCB中,将堆栈地址设置为需要调入的任务的TCB中保存的堆栈地址。
_archFirstThreadRestore:
作用:atomOSStart() 时启动第一个任务
对于一个新的任务没有必要初始化其A、X、Y、CC,然后就剩下SP和PC了。调度任务必须恢复SP,没有必要恢复PC,任务的入口已经在堆栈中了(创建任务时,将thread_shell入栈了,因为当RET返回时PC自动改为任务的入口)。
当一个任务启动时必须开中断,所以有很多地方可以开中断。对于所有的新任务都要这样做,而不是只有第一个任务,采用另外一种模式:使用一个thread shell routine(所有的任务第一次都从这里启动,并且开启中断)。参见atomport.c 中 static NO_REG_SAVE void thread_shell (void);
atomport.c
//每个任务的入口,启动中断。在archThreadContextInit()中调用,将函数地址入栈。
static NO_REG_SAVE void thread_shell(void);
//任务上下文初始化 设置栈顶,入栈thread_shell地址,保存当前堆栈地址到TCB
void archThreadContextInit (ATOM_TCB*tcb_ptr, void *stack_top, void (*entry_point)(uint32_t), uint32_tentry_param);
//系统嘀嗒,所有的定时和延时都基于此,使用随便的一个MCU的定时器,我使用了TIM3 定时1ms(1.024ms)。
void archInitSystemTickTimer ( void );
//时钟的中断处理函数
INTERRUPT_ATOM void TIM3_SystemTickISR(void);
system_ticks++;调用定时器回调atomTimerCallbacks();
atomTimerCallbacks();循环遍历timer_queue,并且调用tmr到期的回调。(这个地方处理在中断里,所以tmr回调不能处理太长。ucOSIII有一个任务专门处理这个)这个地方可以改进下~。
atom.h
//任务控制部件
typedef struct atom_tcb
{
/* Thread's current stack pointer. When a thread is scheduled
* out the architecture port can save*/
POINTER sp_save_ptr;
/* Thread priority (0-255) */
uint8_t priority;
/* Thread entry point and parameter */
void (*entry_point)(uint32_t);
uint32_t entry_param;
/* Queue pointers */
struct atom_tcb *prev_tcb; /*Previous TCB in doubly-linked TCB list */
struct atom_tcb *next_tcb; /*Next TCB in doubly-linked list */
/* Suspension data */
uint8_t suspended; /*TRUE if task is currently suspended */
uint8_t suspend_wake_status; /*Status returned to woken suspend calls */
ATOM_TIMER *suspend_timo_cb; /*Callback registered for suspension timeouts */
/* Details used if thread stack-checking is required */
#ifdef ATOM_STACK_CHECKING
POINTER stack_top; /*Pointer to t

本文介绍了如何在STM8S207C8单片机上运行AtomThreads轻量级实时调度器。讨论了如何配置Cosmic编译器、内存模型和链接器输入,以及中断处理。提到了任务调度、中断调度的实现,包括堆栈管理、中断处理函数的修饰符和系统滴答定时器的设置。同时概述了AtomThreads的TCB结构、任务创建、调度和同步机制,如信号量、互斥锁和队列的使用。

3328

被折叠的 条评论
为什么被折叠?



