# sample_dsp 使用说明

首先申明：该部分是为了更清楚的说明 DSP 的使用，并没有包含针对 DSP 的二次开发功能，所以在 BSP 的 platform_source_code 中是找不到 `adsp` 目录的，涉及到的部分代码和目录也仅仅是为了方便理解做的说明。如果想对 DSP 进行开发，示例满足不了要求；可以联系我们的商务窗口，申请 DSP 的二次开发，申请通过之后才会开放相应的 `adsp` 代码。

## 功能概述

该示例主要说明如何在芯片上简单的使用 DSP 进行任务处理。其中实现的功能是 ARM 侧负责准备数据发起 IPC （进程间通信）调用， DSP 接收到 ARM 侧发来的任务，调用算法处理完成任务计算并将结果发送给 ARM 侧。


### 软件架构说明

sample_dsp 在接收到用户的命令之后，根据具体的输入，由 hb_dsp_start 通过 IPC 和 adsp_firmware 进行通信， adsp_firmware 处理完任务之后，又通过 IPC 返回给 sample_dsp，具体执行结果由 dsp_call 接收。

![software_architecture_diagram.png](_static/_images/sample_dsp/software_architecture_diagram.png)

### 代码位置及目录结构
```
DSP 侧（部分）：即我们提到的 adsp 的目录，未授权则没有开放。

adsp:
├── sample
│   ├── main.c                              # main 函数
│   └── Makefile                            # 编译脚本

......

├── bsp_project/no-archive/algo/            # 算子示例源文件目录
│   ├── hifi5_fft_cplx_32x32
│   │   ├── fft_cplx_32x32.c
│   │   ├── input.c
│   │   ├── readme.txt
│   │   ├── ref_output.c
│   │   └── twiddle32_1024.c
│   └── horizon_sample
│       └── horizon_algo_sample.c

......


ARM 侧： app/samples/platform_samples/sample_dsp/
├── Makefile
├── sample_confg.json                     # IPC 初始化依赖的 json 文件
└── sample_dsp.cpp                        # main 函数， sample 示例

```

### 工具位置及目录结构
`app/samples/platform_samples/sample_dsp/`: 该目录下包含编译后的可执行文件 `sample_dsp`。
```
.
├── Makefile
├── sample_confg.json
├── sample_dsp
├── sample_dsp.cpp
└── sample_dsp.o
```
另一个位置是 `/usr/hobot/lib/firmware/`。
```
.
├── adsp                                # 语音唤醒的固件
├── adsp-sample                         # 复数算法固件
├── bkfir__32x32_taps256_n80.out        # 滤波器相关固件
└── libmm                               # video 相关固件
```
这个位置存放的是 DSP 侧编译出来的固件。

### 背景知识

DSP（数字信号处理器）是一种专门用于数字信号处理的微处理器。它广泛应用于音频处理、语音识别、图像处理等领域。 HiFi5 DSP 子系统是为语音控制、音频处理设计的。

### API 流程说明

![api_process.png](_static/_images/sample_dsp/api_process.png)

API 流程图详细描述了从初始化到数据处理的各个步骤。以下是流程的简要说明：

| **函数名**             | **描述**                                                     |
| --------------------- | ------------------------------------------------------------ |
| hb_dsp_init           | 用于初始化 DSP 环境。                                         |
| hb_dsp_mem_alloc      | 为 DSP 操作分配必要的内存。                                   |
| hb_ipcfhal_getchan_byjson | 用于获取 IPC 通道。                                         |
| hb_ipcfhal_init       | 初始化 IPC 通道。                                            |
| hb_dsp_start          | 启动 DSP 处理。                                              |
| dsp_call              | 是 ARM 侧调用 DSP 算法的接口。                                 |
| hb_ipcfhal_deinit     | 用于释放 IPC 通道。                                          |
| hb_dsp_stop           | 停止 DSP 处理。                                              |
| hb_dsp_mem_free       | 释放之前分配的内存。                                         |
| hb_dsp_deinit         | 进行 DSP 环境的反初始化。                                     |

## 编译部署

### 编译
前提条件：需要注意 `adsp/toolchain/` 目录下要有对应工具链，否则无法正常编译。

编译部分同样分两部分来介绍：
- DSP 侧：
进入 DSP 侧的目录：
首先 source 环境变量，然后参考每一步最后的数字的选择进行选择，最后再进行编译。
```
source env_hf5.sh

please input adsp version: 0: debug or 1: release: 0
adsp target version is debug
Need test cases or not : 0: no or 1: yes: 0
adsp without test cases
Enable stress cases or not : 0: no or 1: yes: 0
Enable algo sample or not : 0: no or 1: yes: 1

make -j4
```

- ARM 侧：
支持整编或者单独编译 app 目录的时候编译到 sample_dsp
```
./bd.sh
./bd.sh app
```

### 工具部署及配置
同样分两部分

- DSP 侧：输出产物在 adsp/output/adsp-sample
没有申请 adsp 的伙伴不用担心，我们释放的镜像包含了固件，以供体验使用流程。

- ARM 侧：输出文件在 out/deploy/app/platform_samples/sample_dsp/
这部分是示例的以及编译产物的位置，编译完成后可参考程序运行方法执行。

## 运行

### 程序运行方法
前提：

检查板端 `/usr/hobot/lib/firmware` 路径下是否存在名为 adsp-sample 固件 (release 版本名称有所不同，比方是 adsp-sample-release)，如果不存在，在对 `/usr/hobot/lib/firmware/` 有写权限的而情况下，将编译出来的 firmware push 到板端 /usr/hobot/lib/firmware/ 路径下。如果没有没办法获得对该路径的写权限，可以重新编译 debug 版本的 ADSP 固件以及相应的 platform 镜像，来运行 sample_dsp。

### 程序参数选项说明
```
Usage: ./sample_dsp
        -p --dsp_path         Specifying firmware paths ( 用于指定 dsp firmware 路径。[ 必选项 ])
        -t --algo_type        Specifying algo type ( 用于指定算法类型。默认 type 是 1)
        -n --dsp_name         Specifying dsp name ( 用于指定加载的 firmware 名称。默认值是 adsp)
        -h --help             print usage ( 用于打印使用帮助 )
```
例如可以这样使用：`./sample_dsp -p /usr/hobot/lib/firmware/ -n adsp-sample`\
（ 如果使用的是 release 版本的镜像 ，-n 的参数需要更新为 adsp-sample-release，比如：`./sample_dsp -p /usr/hobot/lib/firmware/ -n adsp-sample-release` ）

这里详细说明一下

| **参数**       | **描述**                                                     |
| -------------- | ------------------------------------------------------------ |
| -p            | 用于指定 dsp firmware 路径。[ 必选项 ]   |
| -t            | 可选参数是两个， 0 一种算法， 1 代表另一种算法，其定义是编译 ADSP 固件之前就定义好的，如果有授权是可以对其进行更改甚至新增参数的。         |
| -n            | 是 firmware 的名称，当我们的 /usr/hobot/lib/firmware/ 目录下有多个固件，比如 adsp-sample、 adsp 等等的时候，使用 -n 参数来选择。 |
| -h            | 用于打印使用帮助                                |

### 配置文件说明
sample_config.json 是该示例的配置文件，在 sample_dsp.c 的同级目录，它定义了 IPC（进程间通信）的参数和行为。

```
{
        "log_level": 0,
        "config_num": 1,
        "config_num_max":256,
        "config_0": {
                "name": "cpu2dsp_ins2ch0",
                "instance": 2,
                "channel": 0,
                "pkg_size_max": 4096,
                "fifo_size": 64000,
                "fifo_type": 0,
                "ipcf_dev_path":"/dev/ipcdrv",
                "ipcf_dev_name":"ipcdrv"
        }
}

```

以下是配置文件中各个字段的详细说明：


| **字段**       | **子字段** | **值**     | **描述**                                                     |
| -------------- | ---------- | ---------- | ------------------------------------------------------------ |
| log_level      |            | 0          | 定义了日志记录的详细程度。 0 已经代表全部打开了，其他的选项有： 10000 、 15000 、 20000 等等，分别对应 TRACE_LOG 等级、 DEBUG_LOG 等级、 VERBOSE_LOG 等级等等。                    |
| config_num     |            | 1          | 指定配置的通道数量。                                          |
| config_num_max |            | 256        | 配置通道的最大数量，系统最多可以支持 256 个通道配置。          |
| config_0       | name       | cpu2dsp_ins2ch0 | 通道的名称，用于标识 IPC 通道。                                |
|                | instance   | 2          | IPC 通道的实例数量。                                           |
|                | channel    | 0          | 通道的编号，用于区分不同的通道。                              |
|                | pkg_size_max | 4096      | 最大数据包大小，每个数据包最多可以包含 4096 字节的数据。      |
|                | fifo_size  | 64000      | FIFO（先进先出队列）的大小，用于存储数据包。                 |
|                | fifo_type  | 0          | FIFO 的类型，可能表示某种特定的 FIFO 实现或特性。               |
|                | ipcf_dev_path | /dev/ipcdrv | IPC 设备文件的路径， IPC 驱动在系统中的设备文件路径。         |
|                | ipcf_dev_name | ipcdrv    | IPC 设备文件的名称， IPC 驱动的设备名称。                       |


### 运行效果

使用 `/usr/hobot/lib/firmware/adsp-sample` 固件 :

使用串口登录开发板，在 `/app/platform_samples/sample_dsp` 目录执行命令：`./sample_dsp -p /usr/hobot/lib/firmware/ -n adsp-sample`，会出现如下反馈，表明通信成功，并且测试通过。\
(release 版本需要注意 -n 参数是否更换为 adsp-sample-release)
```
root@buildroot:/app/platform_samples/sample_dsp# ./sample_dsp -p /usr/hobot/lib/firmware/ -n adsp-sample
[INFO][hb_ipcf_hal.cpp:272] [channel] cpu2dsp_ins2ch0 [id] 0 init success.
[INFO][hb_ipcf_hal.cpp:325] [channel] cpu2dsp_ins2ch0 [id] 0 config success.
[INFO][hb_ipcf_hal.cpp:272] [channel] cpu2dsp_ins2ch1 [id] 1 init success.
[INFO][hb_ipcf_hal.cpp:325] [channel] cpu2dsp_ins2ch1 [id] 1 config success.
[DSP0-I][]DSP_FREQ = 811000000, xos_get_clock_freq = 811000000, TICK_CYCLES = 811000
[DSP0-I][]--------WELCOME ADSP0 START---------
The example algorithm hifi-fft-cplx takes 19741 cycles
Test Passed.
The example algorithm hifi-fft-cplx takes 7490 cycles
Test Passed.
The example algorithm hifi-fft-cplx takes 8858 cycles
Test Passed.
The example algorithm hifi-fft-cplx takes 9033 cycles
Test Passed.
The example algorithm hifi-fft-cplx takes 8668 cycles
Test Passed.
The example algorithm hifi-fft-cplx takes 8805 cycles
Test Passed.

......

The example algorithm hifi-fft-cplx takes 7789 cycles
Test Passed.
The example algorithm hifi-fft-cplx takes 7670 cycles
Test Passed.
[INFO][hb_ipcf_hal.cpp:500] [channel] cpu2dsp_ins2ch0 [id] 0 deinit success.
The example algorithm hifi-fft-cplx takes 7286 cycles
Test Passed.
[INFO][hb_ipcf_hal.cpp:500] [channel] cpu2dsp_ins2ch1 [id] 1 deinit success.
root@buildroot:/app/platform_samples/sample_dsp#
```
如果使用网络终端登录开发板，`[DSP-I]` 开头的信息不会打印到终端上，需要通过 `dmesg` 打印 Kernel Log 才能查看到。

## 常见问题

- Q: 报错提示 IPC 通信失败，出现如下打印：
```
root@buildroot:/app/platform_samples/sample_dsp# ./sample_dsp -p /usr/hobot/lib/firmware/
[  613.038429] hobot-dsp dsp0: Not attached to any iommu, using physical address!
[INFO][hb_ipcf_hal.cpp:244] [channel] cpu2dsp_ins2ch0 [id] 0 init success.
[INFO][hb_ipcf_hal.cpp:297] [channel] cpu2dsp_ins2ch0 [id] 0 config success.
[DSP0-I][]DSP_FREQ = 811000000, xos_get_clock_freq = 811000000, TICK_CYCLES = 811000
[DSP0-I][]--------WELCOME ADSP0 START---------
[DSP0-I][]platform_init
[DSP0-I][]main
SSF version: V0.1
build: Dec 23 2024 18:24:01
-------- Start SSF Main --------
[  616.094545] remoteproc remoteproc0: wait for boot timeout
[  616.100035] ipc-drv: ipc_shm_acquire_buf() [763]: No free buffer found in channel 0
[  616.107726] ipc-drv: hb_ipc_acquire_buf() [226]: buf acquire failed
[  616.114001] ipc-shm-hal: hal_ipc_shm_write(): [Ins 2 channel 0] sample_dsp(1034) can't obtain buf size 72 from channel cnt 1.
[ERROR][][/Data16T/sw_ae/wangfuhua/sdk-x5-20241227/app/samples/platform_samples/sample_dsp/sample_dsp.cpp:123] ipcfhal send error
[ERROR][][/Data16T/sw_ae/wangfuhua/sdk-x5-20241227/app/samples/platform_samples/sample_dsp/sample_dsp.cpp:212] dsp call fail:-14
root@buildroot:/app/platform_samples/sample_dsp#
```
A: 出现该情况一般检查在运行 sample_dsp 的时候，是否通过 -n 参数指定固件名称，如果未指定，需要通过 -n 参数指定。



- Q: 使用 `./sample_dsp -p /usr/hobot/lib/firmware/ -n adsp-sample` 执行的时候出现如下报错，怎么排查？
```
root@buildroot:/app/platform_samples/sample_dsp# ./sample_dsp -p /usr/hobot/lib/firmware/ -n adsp-sample
[INFO][hb_ipcf_hal.cpp:272] [channel] cpu2dsp_ins2ch0 [id] 0 init success.
[INFO][hb_ipcf_hal.cpp:325] [channel] cpu2dsp_ins2ch[ 4874.846815] remoteproc remoteproc0: hobot_remoteproc_shutdown_hifi5 dsp state is not running
0 [id] 0 config success.
[INFO][hb_ipcf_hal.cpp:272] [channel] [ 4874.848494] hobot-dsp dsp0: dsp_char_ioctl: dsp0 cmd -1071627262 execute error, ret =-22
cpu2dsp_ins2ch1 [id] 1 init success.
[INFO][hb_ipcf_hal.cpp:325] [channel] cpu2dsp_ins2ch1 [id] 1 config success.
[ERROR][][/Data16T/jenkins_slave/workspace/X5_SDK_Publish/platform_source_code/app/samples/platform_samples/sample_dsp/sample_dsp.cpp:290] hb_dsp_start failed, ret -7
[INFO][hb_ipcf_hal.cpp:500] [channel] cpu2dsp_ins2ch0 [id] 0 deinit success.
[INFO][hb_ipcf_hal.cpp:500] [channel] cpu2dsp_ins2ch1 [id] 1 deinit success.
root@buildroot:/app/platform_samples/sample_dsp#
```

A: 检查 /userdata/log/usr/message ， 看报错信息，比如上述问题，可能会看到 ` /usr/hobot/lib/firmware/adsp-sample is not exist ` 这样的 log 提示，到提示位置检查，是否缺少 adsp-sample 文件。
