木子剑
生命不熄,学习不止!

话不多说,直接看我的测试源码:

//
//-- main.c
//

#include <stdio.h>
#include <stdlib.h>
#include "stm32f10x.h"
#include "tn.h"

//-- 空闲任务栈的大小,以字为单位 17+32个字,即49个字
#define IDLE_TASK_STACK_SIZE          (TN_MIN_STACK_SIZE + 32)

//-- 中断堆栈大小,以字为单位
#define INTERRUPT_STACK_SIZE          (TN_MIN_STACK_SIZE + 32)

//-- 用户任务的堆栈大小
#define TASK_A_STK_SIZE               (TN_MIN_STACK_SIZE + 32)
#define TASK_B_STK_SIZE               (TN_MIN_STACK_SIZE + 32)
#define TASK_C_STK_SIZE               (TN_MIN_STACK_SIZE + 32)

//-- 用户任务优先级,0最高
#define TASK_A_PRIORITY    2
#define TASK_B_PRIORITY    3
#define TASK_C_PRIORITY    4

/*******************************************************************************
 *    DATA
 ******************************************************************************/

//-- Allocate arrays for stacks: stack for idle task
//   and for interrupts are the requirement of the kernel;
//   others are application-dependent.
//   We use convenience macro TN_STACK_ARR_DEF() for that.
TN_STACK_ARR_DEF(idle_task_stack, IDLE_TASK_STACK_SIZE);
TN_STACK_ARR_DEF(interrupt_stack, INTERRUPT_STACK_SIZE);

TN_STACK_ARR_DEF(task_a_stack, TASK_A_STK_SIZE);
TN_STACK_ARR_DEF(task_b_stack, TASK_B_STK_SIZE);
TN_STACK_ARR_DEF(task_c_stack, TASK_C_STK_SIZE);

//-- 任务结构, 当成C++公有的类,task_a b c 是类实列化的对像
struct TN_Task task_a;
struct TN_Task task_b;
struct TN_Task task_c;

/*******************************************************************************
 *    FUNCTIONS
 ******************************************************************************/

//-- to printf
int fputc(int c, FILE *stream)
{
   return ITM_SendChar(c);
}

//-- init system timer
void hw_init(void)
{
   SysTick_Config(SYS_FREQ / SYS_TMR_FREQ); // 配置SysTick
}

//-- system timer 中断
void SysTick_Handler(void)
{
   tn_tick_int_processing();  // 周期性执行
}

//-- 测试IO口
void gpio_test(void)
{
  /* GPIOD Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

  /* Configure PC6 in output pushpull mode */
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}

//-- a task
void task_a_body(void *par)
{
   printf("New task a is OK!\n");

   for(;;)
   {
      printf("task a runing...\n");
      tn_task_sleep(400);

   }
}

//-- b task
void task_b_body(void *par)
{
   printf("New task b is OK!\n");
   for(;;)
   {
      printf("task b runing...\n");
      tn_task_sleep(400);
   }
}

//-- c task
void task_c_body(void *par)
{
   static char x=0;
   printf("New task c is OK!\n");
   tn_task_activate(&task_b); // 在C任务中激活B任务
   for(;;)
   {
      printf("task c runing...\n");
      GPIO_WriteBit(GPIOC, GPIO_Pin_6, x^=1); // 反转一个IO口
      tn_task_sleep(400);
   }
}

//-- 空闲回调,从空闲任务中定期调用
void idle_task_callback (void)
{
  ;
}

//-- 创建应用任务, 
void init_task_create(void)
{
   //-- 初始化各种板载外围设备,如闪存、显示器,等等。
   //-- 初始化各种程序模块,----- 免去再建一个APP_init()函数,没必要
   gpio_test();  //-- 测试IO口初始化


   //-- 以下是任务建立,推介只激活一个任务,然后在该任务依次激活所有任务.
   tn_task_create(
         &task_a,                   //-- task structure  任务a对像的地址
         task_a_body,               //-- task body function  任务A的回调函数
         TASK_A_PRIORITY,           //-- task priority  任务A的优先级
         task_a_stack,              //-- task stack   任务A的堆栈地址,类似数组
         TASK_A_STK_SIZE,           //-- task stack size (in words) 任务A的堆栈长度 
         NULL,                      //-- task function parameter  函数参数
         TN_TASK_CREATE_OPT_START   //-- creation option  任务创建后是否应立即激活
         );

   tn_task_create(
         &task_b,
         task_b_body,
         TASK_B_PRIORITY,
         task_b_stack,
         TASK_B_STK_SIZE,
         NULL,
         0//TN_TASK_CREATE_OPT_START  不激活,在C中进行激活
         );

   tn_task_create(
         &task_c,
         task_c_body,
         TASK_C_PRIORITY,
         task_c_stack,
         TASK_C_STK_SIZE,
         NULL,
         TN_TASK_CREATE_OPT_START // 激活
         );
}


/*******************************************************************************
 *    主程序入口
 ******************************************************************************/
int main(void)
{
   //-- 无条件关中断,初始化OS心跳
   tn_arch_int_dis(); 
   hw_init();

   //-- 对tn_sys_start()的调用从不返回
   tn_sys_start(
         idle_task_stack,       // 空闲堆栈地址   
         IDLE_TASK_STACK_SIZE,  // 空闲堆栈大小
         interrupt_stack,       // 中断栈
         INTERRUPT_STACK_SIZE,  // 中断栈大小
         init_task_create,      // 用户任务回调
         idle_task_callback     // 空闲任务回调
         );

   //-- unreachable  无法到达
   return 1;

}

 

接上STM32F10X开发板, SEGGER Embedded Studio在线仿真效果如下:

 因为 GPIO_WriteBit(GPIOC, GPIO_Pin_6, x^=1)存在; 所以会看到PC6引脚上的LED在闪烁!!

 

空间使用多不多,下面可以参考一下,必竟抢占式使用了堆栈

 

 

清一色的堆栈改成“ +16 ”后,RAM又小一点。来说说为什么还是去裸蹦代码???

 

 

当OS系统只有空闲任务时,这就是OS占用芯片的资源了:

 

 TASK结束了,真是无聊透顶了,尽干这些没用的东东!!

 

posted on 2022-03-10 20:59  木子剑  阅读(153)  评论(0编辑  收藏  举报