Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
SMP
全志
全志_T113
T113-S3 SMP适配笔记
10.00
发布于 2022-04-10 13:17:08 浏览:3911
订阅该版
[tocm] # T113-S3 SMP适配笔记 ## 目标 给T113-S3适配RT-Thread,并支持SMP。 ### 资料 没有太详细的资料和示例,只有一些零星的信息。 - F133封装基本兼容 - Cortex-A7双核 一些参考资料 - https://whycan.com/t_7808.html - https://bbs.aw-ol.com/topic/1247/ ## 计划 - 最好能直接使用xfel在SRAM,或是DDR中运行,避免从SD卡启动还需要SPL。 - 先用xfel payload跑通, 最好能有串口打印。 - 再尝试直接load到ddr运行。 - 尝试在DDR中运行rt-thread - 尝试响应中断 - 尝试支持SPL ## 过程 ### 环境准备 - 开发板 芒果派 - 下载工具 xfel 先连接好开发板,默认没卡也没有FLASH,会自动进入USB FEL。 通过xfel可以探测并读取芯片信息。 ``` $ xfel version AWUSBFEX ID=0x00185900(R528/T113) dflag=0x44 dlength=0x08 scratchpad=0x00045000 $ xfel sid d3402000ec1408140140082114cb5bcb $ xfel ddr t113-s3 Initial ddr controller succeeded ``` ### xfel payload 磨刀不误砍柴工,调芯片最好有JTAG,没有的情况下,串口打印是必须的。 xfel工程里面有默认有t113-s3的ddr和spi的payload工程了。 我们先从里面剥离出最简单的串口操作代码,让其至少有输出功能,方便后面打印日志。 使用新编译出的payload,重新编译生成xfel,再随便执行下spi flash命令,串口有打印就行了。 留着这代码备用。 ### ddr中运行代码 继续基于上面的代码,把具体的功能可以先屏蔽。然后把修改链接地址为ddr。 然后使用xfel把这代码加载到DDR中,运行下看没有输出。 ``` xfel ddr t113-s3 xfel write 0x40000000 spi.bin xfel exec 0x40000000 ``` 果然看到了打印,说明可以使用xfel直接加载程序到DDR中运行,这样为后面的开发带来了极大的便利。 ### DDR中运行rt-thread 有了基本开发条件后,就可以开始移植软件部分了。 因为是cortex-a的内核,这块都比较通用,我打算基于`bsp/qemu-vexpress-a9`来修改。 先是使用menuconfig重新配置一下,把所有用不到的组件全关了,只留最基本的kernal和串口驱动部分。 再把链接脚本中的地址修改为目标芯片的地址 0x40000000。 然后把board.c中的中断和时钟心跳这些与硬件有关的代码先屏蔽。 #### 串口驱动 因为没有JTAG,那么串口驱动是必须的了, 把之前从xfel payload中提取出来的串口驱动复制过来。 替换到原来的串口驱动的初始化部分,并把原来的所有硬件相关的代码暂时屏蔽。 只保留putc功能。 编译通过后,使用xfel加载到ddr中运行。观察串口。 果然没有任何打印 !!!! #### 汇编中的debug 遇事不要慌,问题肯定不大。没有任何打印说明程序没能正常运行,或是打印本身有问题。 首先没被运行的可能性可以排除,因为之前加载payload改的小代码可以运行的。 然后就是有可能程序还没运行到程序中串口初始化的地方,此时最好能有JTAG单步,或是能知道启动代码中的汇编程序都运行到哪了。 如果是C,每行加个打印就好了。嗯,汇编也能加。 因为驱动中的接口都是一堆参数,带句柄,还是static的,显然不方便汇编里面调用。 于是我们单独改造下,让串口初始化不需要参数,输出函数只要一个输出数据参数即可。 ```c void sys_uart_init(void) { virtual_addr_t addr; uint32_t val; /* Config GPIOE2 and GPIOE3 to txd0 and rxd0 */ addr = 0x020000c0 + 0x0; val = readl(addr); val &= ~(0xf << ((2 & 0x7) << 2)); val |= ((0x6 & 0xf) << ((2 & 0x7) << 2)); write32(addr, val); ............ } void sys_uart_putc(char c) { virtual_addr_t addr = 0x02500000; while((readl(addr + 0x7c) & (0x1 << 1)) == 0); write32(addr + 0x00, c); } ``` 这样汇编中就可以比较方便调用了,先放在启动入口看看有没打印。 ``` .globl _reset _reset: ldr r1, [r1] bl sys_uart_init mov r0, ='R' bl sys_uart_putc mov r0, ='T' bl sys_uart_putc mov r0, ='T' bl sys_uart_putc ``` 新程序加载到DDR中,果然看到了我们想要的RTT这3个字的打印。说明程序运行到了这里。 通过这种办法,继续在汇编中不同位置添加不同的字符,最后定位到是进MMU初始化就再没打印了。 哦!!! 想起来还没更新MMU配置呢。 MMU配置可以先简单些,32位的全4G空间全部当成外设,把DDR区域设置为常规(带cache,可运行) 修改board.c中的platform_mem_desc表就好了 ```c struct mem_desc platform_mem_desc[] = { {0x00000000, 0xFFFFFFFF, 0x00000000, DEVICE_MEM}, {0x40000000, 0x47FFFFFF, 0x40000000, NORMAL_MEM}, }; ``` 更新mmu配置后,果然看到了 RT-Thread 启动LOGO,还打印了`msh>`。 当然,此时命令行不能输入。因为我们串口驱动的输入还没写。 因为全志的串口驱动基本兼容的,知道串口外设的基地址,直接抄原来其它芯片的代码,直接读寄存器,把getc实现就好了。 但还是不能输入,应该是要支持中断才行。 ### 中断 cortex-A芯片一般都使用GIC,但有好几个版本,通过有限的资料查到,T113-S3是使用GICv2。 这块代码都是通用的,关键是要知道其在芯片中的地址,这个PDF中也有查到GIC地址是在`0x03020000`。 RT-Thread中,GICv2的基本适配已做好,新芯片适配需要知道2个地址,但PDF中没写。 这块根据全志同类型芯片的偏移来看,猜测是一样的 ```c /* the basic constants and interfaces needed by gic */ rt_inline rt_uint32_t platform_get_gic_dist_base(void) { return 0x03021000; } rt_inline rt_uint32_t platform_get_gic_cpu_base(void) { return 0x03022000; } ``` 再通过PDF上面查到的UART0中断号是34,改好后,加载运行,果然收到中断了。 ### SMP 接下来就是适配SMP了,因为只是2核,所以也不用管分簇这些了。 最主要是要知道第2个核是怎么启动,启动后会运行哪个地址的程序。 其它这里还有个**坑点**要注意,就是有些芯片多核是自动启动的,但此时一般软件环境还没准备好,可能会乱飞,需要把非0核先暂停下来。 如果是这类芯片,就需要把`RT_SMP_AUTO_BOOT`打开,这样非0核会自动挂起,直到被0核唤醒,再去指定地址运行。 因为我们之前都能正常运行了,所以肯定不是这种类型的。 通过 https://whycan.com/t_7808.html 这个贴子里面 shaoxi2010 大佬的说明,知道了第2个核的启动方法。 此时更新menuconfig把SMP打开,然后更新下SMP需要的几个接口 ```c /* The Soft Entry Address Register of CPU0 is 0x070005C4. The Soft Entry Address Register of CPU1 is 0x070005C8. */ void rt_hw_secondary_cpu_up(void) { uint32_t cpuboot_membase = 0x070005c4; uint32_t cpuxcfg_membase = 0x09010000; uint32_t cpu, reg; cpu = 1; /* Set CPU boot address */ writel((uint32_t)(secondary_cpu_start), cpuboot_membase + 4 * cpu); /* Deassert the CPU core in reset */ reg = readl(cpuxcfg_membase); writel(reg | (1 << cpu), cpuxcfg_membase); __asm__ volatile ("isb":::"memory"); } ``` 一些和芯片外设相关的先禁用掉,不要心跳也是能运行的。 ```c void secondary_cpu_c_start(void) { // int timer_irq_number; // timer_irq_number = aw_get_irq_num("TIMER1"); rt_hw_vector_init(); rt_hw_spin_lock(&_cpus_lock); arm_gic_cpu_init(0, platform_get_gic_cpu_base()); // arm_gic_set_cpu(0, timer_irq_number, 0x2); //timer1 // timer1_init(); // rt_hw_interrupt_install(timer_irq_number, rt_hw_timer1_isr, RT_NULL, "tick1"); // rt_hw_interrupt_umask(timer_irq_number); rt_system_scheduler_start(); } ``` 编译通过后,使用xfel加载到ddr中运行。SMP果然愉快地运行起来了。 ``` \ | / - RT - Thread Operating System / | \ 4.1.0 build Apr 9 2022 21:17:55 2006 - 2022 Copyright by RT-Thread team [I/sal.skt] Socket Abstraction Layer initialize success. cpuxcfg_membase = 0x13FF0101 // 启动之前的值 cpuxcfg_membase = 0x13FF0103 // 启动之后的值 Hello T113 RT-Thread SMP! msh />ps thread cpu bind pri status sp stack size max used left tick error -------- --- ---- --- ------- ---------- ---------- ------ ---------- --- tshell 0 2 20 running 0x00000140 0x00001000 15% 0x0000000a 000 aio N/A 2 16 suspend 0x00000080 0x00000800 07% 0x0000000a 000 sys work N/A 2 23 suspend 0x00000084 0x00000800 06% 0x0000000a 000 tsystem N/A 2 30 suspend 0x00000098 0x00000400 22% 0x00000020 000 tidle1 1 1 31 running 0x0000005c 0x00000400 19% 0x00000020 000 tidle0 N/A 0 31 ready 0x0000005c 0x00000400 19% 0x00000020 000 timer N/A 2 4 suspend 0x0000007c 0x00000400 12% 0x0000000a 000 ``` ## 后续计划 暂无新计划,欢迎加入一起更新。 ## 代码分享 - https://gitee.com/aozima/rt-thread/tree/allwinner_t113/ - https://gitee.com/aozima/rt-thread/tree/allwinner_t113/bsp/allwinner_t113
8
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
aozima
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
文章
28
回答
4479
被采纳
379
关注TA
发私信
相关文章
1
aarch64有计划支持SMP吗
2
SMP重新定义中断处理函数的问题
3
rt_tick_increase()在SMP时只增加当前核的TICK?
4
RISCV smp系统调度异常问题请教
5
qemu-vexpress-a9 在SMP情况下GDB无法调试
6
为什么在k210上使用多核smp总是会卡死
7
RT-Thread SMP核弹碰撞树莓派
8
请教多核SMP功能验证
9
明年开始玩SMP多核处理器
10
建议RT-Thread支持SMP
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
5
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部