Atomthreads&STM8S207C8

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

第一次发帖请大家见谅,请大家多多吐槽。


在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

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值