重要事项
DSP 官方文档列表
这些文档包括:HiFi5 DSP 配置信息、用户手册、编译器连接器使用手册、仿真调试手册等等。 在安装完工具链后,文档就在工具链的安装路径下:
DSP 使用说明: C:\usr\xtensa\XtDevTools\downloads\RI-2021.8\docs
DSP 架构文档 (Call0 ABI): C:\usr\xtensa\XtDevTools\install\builds\RI-2021.8-win32\HIFI5_PROD_1123_asic_UPG\index.html
DSP 架构文档 (Window ABI): C:\usr\xtensa\XtDevTools\install\builds\RI-2021.8-win32\HIFI5_PROD_1123_asic_wUPG\index.html
DSP 使用说明: /opt/xtensa/XtDevTools/downloads/RI-2021.8/docs
DSP 架构文档 (Call0 ABI): /opt/xtensa/XtDevTools/install/builds/RI-2021.8-linux/HIFI5_PROD_1123_asic_UPG/index.html
DSP 架构文档 (Window ABI): /opt/xtensa/XtDevTools/install/builds/RI-2021.8-linux/HIFI5_PROD_1123_asic_wUPG/index.html
Printf
标准的 printf 输出函数在退出时会打开中断,因此 不能在中断 handler 和临界区(critical section)内使用 ,可使用 DiagPrintf 替代。DiagPrintf 不会打开中断,但 不支持浮点数打印 。
DTCM 地址限制
DTCM 是一块延迟极低的本地内存,可实现单周期数据读取(不能将代码放入 DTCM)。 虽然 DTCM(DRAM)空间为连续的 256KB,但其实物理上有两个独立的 DRAM 区(各 128K)。因此 iDMA 和单个 CPU 的向量指令都不能跨 DRAM 边界(0x1FFE0000),否则报错。
iDMA
iDMA 可将数据从 PSRAM 或 SRAM 搬运到 DTCM。在 psram 内存带宽受限时,可以用 iDMA 将大块数据搬到 DTCM,进行 ping-pong 运算提升数据处理速度。但使用 iDMA 有下列注意事项:
DTCM 地址限制
iDMA 只支持在 system memory(SRAM/PSRAM)与本地 memory(DRAM 0/1)之间或者本地内存之间搬运数据,不允许仅在 system memory(即 SRAM 与 PSRAM 间)作搬运。
iDMA 单次不能跨 DRAM 边界(0x1FFE0000)搬运。
中断注册和使能
如需用到 iDMA 中断,不仅要注册与使能中断,还需在发起搬运任务时添加控制描述符 DESC_NOTIFY_W_INT,否则不会进入 ISR handler。
idma_register_interrupts(0, (os_handler)done_handler, (os_handler)error_handler);
idma_copy_desc(dst_data, src_data, DATA_SIZE, DESC_NOTIFY_W_INT);
iDMA 的实用方法可参考 SDK 示例及 Xtensa 文档 sys_sw_rm.pdf
相关内容。
FreeRTOS SyStick
SyStick
在中断 handler 中用 xTaskGetTickCountFromISR 获取的 SyStick Tick 值可能不准确。 该 API 只能读到系统进入 WATI 前的 SyStick,真正的 SyStick 要等中断退出后才会更新。因此不建议直接依赖 Tick 值作精确计时。 在需要准确时间的场景,应该实用硬件定时器。比如上电默认运行的 DBG Timer。
Stack overflow 检测
DSP 没有硬件的栈溢出检测寄存器。发生栈溢出时软件可能无法在第一时间发现,导致系统直接 hang 住没有 crash log。 可以考虑静态创建任务,并将任务栈放在内存块的边缘,然后使用下面的 MPU 来检测栈溢出。
Cache
dsp_wrapper.h
对常用 D-Cache 操作接口做了封装:
DCache_Clean
DCache_Invalidate
DCache_CleanInvalidate
DMA 使用时一定要注意 cache 的影响:
DCache_Invalidate 操作时,如长度不是 cacheline(128 字节)的整数倍,则 整条 cacheline 会被无条件失效 ,导致同行里的其它数据丢失。
DCache_Clean 操作时,如果 DMA 已把新数据写到内存,再执行 DCache_Clean,会将旧数据从 cache 回刷到内存,覆盖掉 DMA 结果,造成数据错乱。
MPU Entry
如需设置更细致的内存保护,可以在默认 MPU 表基础上新增 MPU 区间。最多可用 16 项(Entry),SDK 默认用掉了 7 项。
注意:mpu_table.c
文件在 RTK_LSP 路径与项目的 project_dsp 路径要同步修改。
例如,禁止 DSP 访问 PSRAM 特定区间 (0x60700000 - 0x60800000):

DSP 若访问受保护地址,会打印出如下 crash log:

Crash Dump 分析
若崩溃前栈状态没有被完全破坏,DSP 会打印出 Crash Dump 日志。崩溃时,系统处于异常状态。因此日志信息不一定完全准确。 例如:
======== xt_unhandled_exception ========
exit:0x00000015 (exit point for dispatch)
pc:0x6034fd88 (PC cause exception)
ps:0x00000030 (return PS)
a0:0x6034fc4d (PC after the exception point)
a1:0x1fffe540 (stack pointer before interrupt)
a2:0x606630fc
a3:0x60670a90
a4:0x60670a94
a5:0x60670a90
a6:0x60670830
a7:0x60670ad0
a8:0000000000
a9:0x00000021
a10:0x6066e4d8
a11:0x00000008
a12:0x001e9f60
a13:0x0000007c
a14:0xf2e5d8eb
a15:0xf3f8f8f8
sar:0x0000001e
exccause:13 (exception cause. Please refer to "isa_rm.pdf": Table 4-94. Exception Causes)
excvaddr:0000000000
lbeg:0x6034fd88 (loop begin PC)
lend:0x6034fd93 (loop end PC)
lcount:1614085193 (loop counter)
=============== backtrace ==============
Call0 ABI
1. pc cause exception: 0x6034fd88
2. function return pc: 0x6034fc4d
3. function return pc: 0x60335f10
4. function return pc: 0x6034b5e0
Except for the first pc value, the other backtrace values are the next pc immediately after the call instruction.
Refer to the application note for the method of generating disassembly.
Crash Dump 日志由两部分组成:
1. Stack Dump
寄存器值:PC 和其他内核寄存器值。可以根据 反汇编和 map 文件 查看崩溃地址原因。lbeg、lend 则是崩溃前一次的循环代码的开始和结束位置,也可以参考。
异常代码:exccause 的代码含义可以参考
isa_rm.pdf
(文档位置说明)的 220 页:Table 94: Exception Causes
。
2. Backtrace
backtrace 结果是一系列连续调用的 PC 值。 上面示例日志里的函数调用关系是:0x6034b5e0 -> 0x60335f10 -> 0x6034fc4d -> 0x6034fd88。