64位 RT-Thread 移植到 Cortex-A53 系统 bug 修复笔记

9 篇文章 3 订阅
1 篇文章 0 订阅

RT-Thread 版本:4.1.0 master 版本。
完整工程代码如下:可运行在 Cortex-A53 架构上的 RTT

1. Idle 默认栈大小为 256 字节,导致任务切换触发异常

Arch64 状态下,RT-thead 的任务切换触发未知错误。

经过测试,是因为 idle 初始化时,栈溢出,修改了就绪列表的值,导致任务切换失败.

#ifndef IDLE_THREAD_STACK_SIZE
#if defined (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP)
#define IDLE_THREAD_STACK_SIZE  256
#else
#define IDLE_THREAD_STACK_SIZE  128
#endif /* (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) */
#endif /* IDLE_THREAD_STACK_SIZE */

可以手动设置 IDLE_THREAD_STACK_SIZE 大小更改 IDLE 任务栈大小。问题解决。

2. 栈初始化时,未对栈指针进行对齐操作,导致任务切换时触发 sp 指针对齐失败异常

串口报错如下:
[0]switch to priority#255 thread:tidle0(sp:0x41019024), from thread:tshell(sp: 0x42058f20)
[SYNC Error]: in EL1
ELR_EL1 =0x000000004100045c
ESR_EL1 =0x000000009a000000
current Exception Level exception, SPsel = 0
x0 =0x0000000000000000  x1 =0x0000000000000001
x2 =0x0000000000000000  x3 =0x0000000000000000
x29 =0x000000000000001d x30 =0x0000000041003134
[INFO]: CPU Reboot now!!!

查看手册得知,ELR_EL1 =0x000000004100045c,该异常由 sp 指针对齐失败导致的。

解决:由于当前 sp 指针为 4 字节对齐的,所以失败,在 rt_hw_stack_init() 中 将 sp 指针进行 16 字节对齐,问题解决。

    /*
     * TODO sp 指针4字节对齐不行,64位任务环境下的任务切换会失败,更改为 16 字节对齐
     */
    stack_addr = RT_ALIGN_DOWN((rt_ubase_t)stack_addr, sizeof(rt_ubase_t) * 2);

注意:栈指针16字节对齐,是编程向导手册中要求的(8.2.1章节)!!!经过测试,8字节对齐确实不行

在这里插入图片描述

3.每一次通过 shell 命令读取系统 tick 计数都是 0

测试发现,shell 输入回车以及任一shell命令导致系统 tick 计数清零。

经过调试分析,在rt_sem_take(&shell->rx_sem, RT_WAITING_FOREVER) 代码前后将 rt_tick 清零。

继续测试,是rt_sem_release() 中的rt_schedule()rt_tick清零。

继续测试,问题出现在rt_schedule()中的 rt_hw_context_switch_interrupt()的汇编实现中。

原因:汇编代码中变量访问越界造成该问题。

rt_hw_context_switch_interrupt()的汇编实现中,会用到三个外部定义的变量:

.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread

这三个外部变量定义在 libcpu 文件夹下对应架构的 interrupt.c 文件中。

volatile rt_ubase_t rt_interrupt_from_thread = 0;
volatile rt_ubase_t rt_interrupt_to_thread = 0;
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;

其中,变量 rt_thread_switch_interrupt_flag 定义为无符号的32位整型,而在rt_hw_context_switch_interrupt()的汇编实现中,我们使用 Xn 寄存器来访问这个变量,而 Xn 寄存器是64位的,导致访问越界,而刚好, rt_thread_switch_interrupt_flag 变量地址为 0x41019144, 变量rt_tick 地址为 0x41019148, 所以当我们以 64 位宽度对 rt_thread_switch_interrupt_flag 置1或清0时,我们都会将 rt_tick 清0。

解决:

变量 rt_thread_switch_interrupt_flag 的初始类型为:

volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;

现在更改为:

volatile rt_ubase_t rt_thread_switch_interrupt_flag = 0;

问题解决。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RT-Thread 是一个开源的实时操作系统,它具有轻量级、可裁剪、可移植等特点。而 hc32f460 是汇顶科技推出的一款高性能的32位ARM Cortex-M4F内核的微控制器。 要将 RT-Thread 移植到 hc32f460 上,我们需要进行以下几个步骤: 1. 确认硬件支持:首先需要确保 hc32f460 上的硬件资源能够满足 RT-Thread 的要求,比如存储器空间、CPU性能等。 2. 创建移植目录:在 RT-Thread 的源代码目录中,我们可以通过复制一个与 hc32f460 对应的目录来进行移植。例如,将 `port` 目录下的 `hc32` 目录复制,并重命名为 `hc32f460`。 3. 配置:打开 `rtconfig.h` 文件,根据 hc32f460 的硬件特点和资源情况,对 RT-Thread 进行相应的配置。这包括设置堆栈大小、线程数量、中断优先级、时钟相关配置等。 4. 驱动移植:检查 hc32f460 上的外设驱动是否与 RT-Thread 的驱动兼容。如果不兼容,需要进行一些适配工作,确保驱动能够正确地与 RT-Thread 进行交互。 5. 编译:使用 hc32f460 相应的编译工具链,编译 RT-Thread 移植代码。 6. 烧录和运行:将编译生成的可执行文件烧录到 hc32f460 的存储器中,并启动芯片,即可运行 RT-Thread。 总之,将 RT-Thread 移植到 hc32f460 上主要涉及硬件支持、目录创建、配置、驱动移植以及编译和烧录等步骤。只要按照这些步骤进行操作,我们就可以成功将 RT-Thread 移植到 hc32f460 上,并利用 RT-Thread 强大的功能和优势来开发我们的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值