当前文档版本为 v1.2.0,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

Driver: ACC

1 功能概述

外设模块ACC模块主要用于计算两个32位无符号数相乘,并将其值累加存储起来,用于加速向量点积操作,同时也可当作硬件除法器。该sample演示了外设模块ACC的点乘运算和除法运算。

2 环境要求

  • PAN1080 EVB 一块

  • USB-TypeC 线一条(用于供电和查看串口打印 Log)

  • 硬件接线:

    • 使用 USB 线,将 PC USB 与 EVB USB-TypeC(USB->UART)相连

    • 根据 EVB 核心板芯片的封装不同,使用杜邦线将 EVB 底板上的:

      • TX0 与 P00 相连, RX0 与 P01 相连(若 EVB 板芯片为 QFN32 或 LQFP64 封装)

      • TX0 与 P30 相连, RX0 与 P31 相连(若 EVB 板芯片为 QFN48 封装)

  • PC 软件: 串口调试助手(UartAssist)或终端工具(SecureCRT),波特率921600

3 编译和烧录

例程位置:zephyr\samples_panchip\drivers\acc

使用 ZAL 工具可以对其进行编译、烧录、打开 VS Code 调试等操作。关于 ZAL 工具的详细介绍请参考:Zephyr APP Launcher 工具介绍

4 演示说明

4.1点乘运算

  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
    };
    
  2. 启动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];
    }
    
  3. 对比ACC模块计算值与事先已验证过的正确值,判断ACC模块点乘运算功能是否正常,数值一致打印success,否则打印 “[数值_sw] should equal to [数值_hw] ”。

4.2 除法运算

  1. 从向量中选取一组数值作为除数与被除数,启动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];	/*获取运算结果*/
    
  2. 使用除法器中运算使用的除数与被除数通过软件计算方式计算结果,对比软件结果与除法器结果,数值一致打印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.1 启用ACC模块

在prj.conf文件中添加“CONFIG_ACC=y”启用ACC模块。
CONFIG_ACC=y

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);

6 RAM/Flash资源使用情况

Memory region         Used Size  Region Size  %age Used
FLASH:       23388 B       384 KB      5.95%
SRAM:        7552 B        64 KB     11.52%