12
返回列表 发新帖

GD 32 Trochili RTOS 移植

[复制链接]
楼主: chenqiang10
 楼主 | 2018-10-27 12:02 | 显示全部楼层
线程优先级计算函数
函数 uCpuCalcHiPRIO()通过 RBIT和 CLZ指令来加速计算线程队列中的最高线程优先级。
内核与处理器接口函数
函数 uCpuInit()完成处理器初始化,主要是设置主频和系统心跳时钟中断.该函数首先设
置 Systick 参数,使得处理器硬件时钟 Systick 按照指定频率发出中断,目前在 GD32F10x 处
理器上是按照 72M 处理器频率和每 10 毫秒一次定时器中断来设置的。
 楼主 | 2018-10-27 12:04 | 显示全部楼层
内核启动流程
这里我们结合代码和注释来分析内核是如何启动的。内核启动函数在文件 kernel.c 中。
 楼主 | 2018-10-27 12:05 | 显示全部楼层
该函数具体代码如下:
  1. void xKernelStart(TUserEntry pUserEntry,
  2. TCpuSetupEntry pCpuEntry,
  3. TBoardSetupEntry pBoardEntry,
  4. TTraceEntry pTraceEntry)
  5. {
  6. TReg32 imask;
  7. CpuEnterCritical(&imask);
  8. /* 初始化基本内核参数 */
  9. memset(&uKernelVariable, 0, sizeof(uKernelVariable));
  10. uKernelVariable.UserEntry = pUserEntry;
  11. uKernelVariable.CpuSetupEntry = pCpuEntry;
  12. uKernelVariable.BoardSetupEntry = pBoardEntry;
  13. uKernelVariable.TraceEntry = pTraceEntry;
  14. uKernelVariable.Schedulable = eTrue;
  15. /* 初始化所有内核模块 */
  16. uThreadModuleInit(); /* 初始化线程管理模块 */
  17. #if (TCL_TIMER_ENABLE)
  18. uTimerModuleInit(); /* 初始化定时器模块 */
  19. #endif
  20. #if (TCL_IRQ_ENABLE)
  21. uIrqModuleInit(); /* 初始化中断管理模块 */
  22. #endif
  23. /* 初始化内核线程并且激活 */
  24. InitIdleDaemon(); /* 初始化内核 IDLE 线程并且激活
  25. */#if ((TCL_TIMER_ENABLE) && (TCL_TIMER_DAEMON_ENABLE))
  26. uTimerInitDaemon(); /* 初始化内核定时器线程并且激活
  27. */
  28. #endif
  29. #if ((TCL_IRQ_ENABLE) && (TCL_IRQ_DAEMON_ENABLE))
  30. uIrqInitDaemon(); /* 初始化内核 IRQ 线程并且激活
  31. */
  32. #endif
  33. uKernelVariable.CpuSetupEntry(); /* 调用处理器和板级初始化函数
  34. */
  35. uKernelVariable.BoardSetupEntry(); /* 调用处理器和板级初始化函数
  36. */
  37. CpuLoadIdleThread(); /* 启动内核 IDLE 线程
  38. */
  39. CpuLeaveCritical(imask);
  40. while (eTrue)
  41. {
  42. uDebugPanic("", __FILE__, __FUNCTION__, __LINE__);
  43. }
  44. }
复制代码


 楼主 | 2018-10-27 12:05 | 显示全部楼层
在内核启动之前,必须注册用户应用程序入口函数。用户可以在这个函数里初始化应用线程,对 BSP 和设备进行初始化。
 楼主 | 2018-10-27 12:06 | 显示全部楼层
Trochili 多线程编程
下面代码演示了如何注册一个恰当的用户应用函数。
  1. #include "example.h"
  2. #include "trochili.h"
  3. #if (EVB_EXAMPLE == CH13_BOARD_TEST_EXAMPLE)
  4. /* 用户线程参数 */
  5. #define THREAD_LED_STACK_BYTES (512)
  6. #define THREAD_LED_PRIORITY (5)
  7. #define THREAD_LED_SLICE (20)
复制代码




 楼主 | 2018-10-27 12:07 | 显示全部楼层
用户线程定义
  1. /* 用户线程栈定义 */
  2. static TWord ThreadLedStack[THREAD_LED_STACK_BYTES/4];/* 用户线程定义 */
  3. static TThread ThreadLed;
复制代码


 楼主 | 2018-10-27 12:07 | 显示全部楼层
用户定时器结构
  1. /* 用户定时器结构 */
  2. static TTimer LedTimer;
复制代码




 楼主 | 2018-10-27 12:15 | 显示全部楼层
线程做无用操作,起到空转效果

  1. /* 线程做无用操作,起到空转效果 */
  2. static delay(TWord count)
  3. {
  4. while(count --);
  5. }
复制代码


 楼主 | 2018-10-27 12:16 | 显示全部楼层

用户定时器 1 的回调函数  

  1. /* 用户定时器 1 的回调函数,间隔 1 秒,点亮或熄灭 Led1 */
  2. static void Blink(TArgument data)
  3. {
  4. static int index = 0;
  5. if (index % 2)
  6. {
  7. EvbLedControl(LED1, LED_OFF);
  8. EvbLedControl(LED2, LED_OFF);
  9. }
  10. else
  11. {
  12. EvbLedControl(LED1, LED_ON);
  13. EvbLedControl(LED2, LED_ON);
  14. }
  15. index++;
  16. }
复制代码


 楼主 | 2018-10-27 12:17 | 显示全部楼层
按键中断处理函数
  1. /* 评估板按键中断处理函数 */
  2. static TBitMask EvbKeyISR(TArgument data)
  3. {
  4. TState state;
  5. TError error;
  6. static TWord index = 1;
  7. if (EvbKeyScan())
  8. {
  9. if (index % 2)
  10. {
  11. /* 启动用户定时器 */state = TclStartTimer(&LedTimer, 0U, &error);
  12. TCL_ASSERT((state == eSuccess), "");
  13. TCL_ASSERT((error == TCLE_TIMER_NONE), "");
  14. }
  15. else
  16. {
  17. /* 关闭用户定时器 */
  18. state = TclStopTimer(&LedTimer, &error);
  19. TCL_ASSERT((state == eSuccess), "");
  20. TCL_ASSERT((error == TCLE_TIMER_NONE), "");
  21. }
  22. index++;
  23. }
  24. return TCLR_IRQ_DONE;
  25. }
复制代码




 楼主 | 2018-10-27 12:18 | 显示全部楼层
Led 线程的主函数
  1. /* Led 线程的主函数 */
  2. static void ThreadLedEntry(TArgument data)
  3. {
  4. while (eTrue)
  5. {
  6. delay(0x4fffff);
  7. EvbLedControl(LED3, LED_ON);
  8. TclTrace("LED3 ON\r\n");
  9. delay(0x4fffff);
  10. EvbLedControl(LED3, LED_OFF);
  11. TclTrace("LED3 OFF\r\n");
  12. }
  13. }
复制代码




 楼主 | 2018-10-27 12:18 | 显示全部楼层
用户应用程序入口函数
  1. /* 用户应用程序入口函数 */
  2. static void AppSetupEntry(void)
  3. {
  4. TState state;
  5. TError error;
  6. /* 设置和 KEY 相关的外部中断向量 */
  7. state = TclSetIrqVector(KEY_IRQ_ID, &EvbKeyISR, (TArgument)0,
  8. (TThread*)0, &error);
  9. TCL_ASSERT((state == eSuccess), "");
  10. TCL_ASSERT((error == TCLE_IRQ_NONE), "");/* 初始化用户定时器 */
  11. state = TclInitTimer(&LedTimer, TCLP_TIMER_PERIODIC,
  12. TCL_MLS2TICKS(1000), &Blink, (TArgument)0,
  13. &error);
  14. TCL_ASSERT((state == eSuccess), "");
  15. TCL_ASSERT((error == TCLE_TIMER_NONE), "");
  16. /* 初始化 Led 线程 */
  17. state = TclInitThread(&ThreadLed,
  18. &ThreadLedEntry, (TArgument)0,
  19. ThreadLedStack, THREAD_LED_STACK_BYTES,
  20. THREAD_LED_PRIORITY, THREAD_LED_SLICE,
  21. &error);
  22. TCL_ASSERT((state == eSuccess), "");
  23. TCL_ASSERT((error == TCLE_THREAD_NONE), "");
  24. /* 激活 Led 线程 */
  25. state = TclActivateThread(&ThreadLed, &error);
  26. TCL_ASSERT((state == eSuccess), "");
  27. TCL_ASSERT((error == TCLE_THREAD_NONE), "");
  28. }
复制代码




 楼主 | 2018-10-27 12:19 | 显示全部楼层
main 函数
  1. /* 处理器 BOOT 之后会调用 main 函数,必须提供 */
  2. int main(void)
  3. {
  4. /* 注册各个内核函数,启动内核 */
  5. TclStartKernel(&AppSetupEntry,
  6. &CpuSetupEntry,
  7. &EvbSetupEntry,
  8. &EvbTraceEntry);
  9. return 1;
  10. }
复制代码




 楼主 | 2018-10-27 12:19 | 显示全部楼层
函数 AppSetupEntry ()就是所说的用户应用程序入口函数,在该函数里,我们初始化了 LED 和 KEY 设备,通过内核接管了 KEY 的中断处理,然后初始化了一个定
时器,最后将 LED 线程激活
 楼主 | 2018-10-27 12:20 | 显示全部楼层
这个函数注册到内核后,在内核启动过程中被调用,在这之后,内核将通过 IDLE 线程启动多任务。因为 IDLE 线程优先级最低,所以 LED 线程随即抢占 IDLE
线程,用户程序开始执行。
 楼主 | 2018-10-27 12:21 | 显示全部楼层
这次在GD32上移植RTOS 就到这里。
| 2018-10-27 22:28 | 显示全部楼层
rtos的源码呢
| 2018-10-28 14:25 | 显示全部楼层
赞一个
| 2018-10-29 20:58 | 显示全部楼层
感谢分享,这个操作系统还没玩过
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

快速回复 返回顶部 返回列表