Driver: ACC¶
1 功能概述¶
外设模块ACC模块主要用于计算两个32位无符号数相乘,并将其值累加存储起来,用于加速向量点积操作,同时也可当作硬件除法器。该sample演示了外设模块ACC的点乘运算和除法运算。
2 环境要求¶
PAN1080 EVB一块
Micro USB线一条(用于供电和查看串口打印Log)
硬件接线:
使用USB线,将PC USB与EVB MicroUSB(USB->UART)相连
使用杜邦线将EVB上的:
UART1 TX与P06相连
UART1 RX与P07相连
PC软件: 串口调试助手(UartAssist)或终端工具(SecureCRT),波特率921600
3 编译和烧录¶
项目位置:zephyr\samples_panchip\drivers\acc
目前可使用ZAL工具或quick build脚本进行编译和下载。
脚本位置:quick_build_samples\drivers\acc.bat
打开脚本后默认会编译项目,编译完成时,可输入字符进行后续下载等操作:
Input the keyword to continue:
'b' build 编译项目
'r' make clean and rebuild 重新编译项目
'f' flash download 下载
'e' erase chip 擦除芯片
'o' open project by VS Code 打开 `VS Code`,可查看源码,执行编译下载等
others exit 退出
wait input:
4 演示说明¶
4.1点乘运算¶
设置了两个包含8个固定元素的向量。
static uint32_t mult_left[MULT_BUFFER_SIZE] = { /*向量1元素*/ 0x1122, 0x2233, 0x3344, 0x3, 0x4, 0x5, 0x6, 0x1234 }; static uint32_t mult_right[MULT_BUFFER_SIZE] = { /*向量2元素*/ 0, 1, 2, 3, 4, 5, 6, 7 };
启动ACC乘法运算,并获取结果。
ret = acc_start_multiplier(acc_dev, &acc_mult_cfg); /*启动acc模块点乘运算*/ if (ret != 0) { LOG_INF("acc start multiplier failed with code %d", ret); } ret = acc_get_value(acc_dev, &acc_mult_cfg); /*获取运算结果*/ if (ret != 0) { LOG_INF("acc get value failed with code %d", ret); } for (uint8_t i = 0; i < RESULT_BUFFER_SIZE; i++) { /*缓存运算结果*/ result_buffer[i] = acc_mult_cfg.buffer[i]; }
对比ACC模块计算值与事先已验证过的正确值,判断ACC模块点乘运算功能是否正常,数值一致打印success,否则打印 “[数值_sw] should equal to [数值_hw] ”。
4.2 除法运算¶
从向量中选取一组数值作为除数与被除数,启动ACC除法运算,并获取结果。
ret = acc_start_divider(acc_dev, &acc_div_cfg); /*启动acc模块除法运算*/ if (ret != 0) { LOG_INF("acc start divider failed with code %d", ret); } result = acc_div_cfg.buffer[0]; /*获取运算结果*/
使用除法器中运算使用的除数与被除数通过软件计算方式计算结果,对比软件结果与除法器结果,数值一致打印divider success,否则打印“[数值_sw] != [数值_hw]”。
result_sw = acc_div_cfg.divisor / acc_div_cfg.dividend; /*软件除法运算*/ if (result != result_sw) { /*对比结果*/ LOG_INF("[%08x] != [%08x]", result, result_sw); }
5 开发说明¶
5.2 初始化ACC¶
int ret;
const struct device *acc_dev;
acc_dev = device_get_binding(DT_LABEL(DT_INST(0, panchip_pan_acc))); /*获取acc设备*/
if (!acc_dev) {
LOG_INF("Cannot get ACC device\n");
}
ret = acc_set_up(acc_dev, acc_cfg); /*初始化acc模块*/
if (ret != 0) {
LOG_INF("Setting up acc config failed with code %d", ret);
}
其中acc_cfg数据结构及参数含义如下
/** @brief Structure with generic accumulator features.
*
* @param operate_mode operate mode select(multiplier or divider)
* @param first_multiplier first multiplier data
* @param sec_multiplier second multiplier data
* @param divisor divisor value
* @param dividend dividend value
* @param number_words The multiplier calculates the number of polls
* @param cycle: The multiplier reserves the computation period
* @param buffer: result buffer
*/
struct acc_config_info {
uint8_t operate_mode;
uint32_t *first_multiplier;
uint32_t *sec_multiplier;
uint32_t divisor;
uint32_t dividend;
uint8_t number_words;
uint8_t calc_cycle;
uint32_t buffer[16];
};
5.3 ACC API接口¶
接口总览
__subsystem struct acc_driver_api {
acc_api_set_up set_up;
acc_api_set_int enable_int;
acc_api_start_multiplier start_multiplier;
acc_api_get_multiplier_value get_value;
acc_api_start_divider start_divider;
};
acc初始化模块配置
/**
* @brief This function is used to setup acc device
* @param dev Pointer to the device structure for the driver instance.
* @param acc_cfg Pointer to acc configuration.
* @retval 0 On success.
* @retval -EINVAL If a parameter with an invalid value has been provided.
*/
__syscall int acc_set_up(const struct device *dev,
const struct acc_config_info *acc_cfg);
acc中断初始化
/**
* @brief This function is used to enable acc interrupt
* @param dev Pointer to the device structure for the driver instance.
* @param enable_state interrupt enable or not.
* @retval 0 On success.
* @retval -EINVAL If a parameter with an invalid value has been provided.
*/
__syscall void acc_enable_int(const struct device *dev, bool enable_state);
acc启动乘法运算
/**
* @brief This function is used to start multiplier
* @param dev Pointer to the device structure for the driver instance.
* @param acc_cfg Pointer to acc configuration.
* @retval 0 On success.
* @retval -EINVAL If a parameter with an invalid value has been provided.
*/
__syscall int acc_start_multiplier(const struct device *dev,
const struct acc_config_info *acc_cfg);
acc获取运算结果
/**
* @brief This function is used to get multiplier result
* @param dev Pointer to the device structure for the driver instance.
* @param acc_cfg Pointer to acc configuration.
* @retval 0 On success.
* @retval -EINVAL If a parameter with an invalid value has been provided.
*/
__syscall int acc_get_value(const struct device *dev,
const struct acc_config_info *acc_cfg);
acc启动除法运算
/**
* @brief This function is used to start divider
* @param dev Pointer to the device structure for the driver instance.
* @param acc_cfg Pointer to acc configuration.
* @retval 0 On success.
* @retval -EINVAL If a parameter with an invalid value has been provided.
*/
__syscall int acc_start_divider(const struct device *dev,
const struct acc_config_info *acc_cfg);