Add apu comment, kpu for new nncase, fix spi 32bit mode bug

This commit is contained in:
zhaozhongxiang 2019-03-21 11:09:47 +08:00
parent 2c38d4e0e7
commit c41a0ff39c
5 changed files with 351 additions and 38 deletions

View File

@ -1,3 +1,17 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stddef.h>
#include <stdint.h>
#include <math.h>
@ -18,7 +32,7 @@ the average value of samples from different channels is required, this right shi
is used to perform division.
0x0: no right shift; 0x1: right shift by 1-bit;
. . . . . .
0xF: right shift by 14-bit.
0xF: right shift by 15-bit.
*/
void apu_set_audio_gain(uint16_t gain)
{
@ -40,6 +54,7 @@ void apu_set_smpl_shift(uint8_t smpl_shift)
tmp.smpl_shift_bits = smpl_shift;
apu->bf_dwsz_cfg_reg = tmp;
}
/*get sampling shift*/
uint8_t apu_get_smpl_shift(void)
{
@ -49,13 +64,13 @@ uint8_t apu_get_smpl_shift(void)
}
/*
* BF unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). BF sound channels are related with I2S host RX channels.
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0; BF channel 2/3 correspond
* APU unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). APU sound channels are related with I2S host RX channels.
* APU sound channel 0/1 correspond to the left/right channel of I2S RX0; APU channel 2/3 correspond
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
* channel and hardware automatically clear the bit after the sample buffers used for direction
* searching is filled full.
* 0x1: writing '1' to enable the corresponding BF sound channel.
* 0x1: writing '1' to enable the corresponding APU sound channel.
*/
void apu_set_channel_enabled(uint8_t channel_bit)
{
@ -69,13 +84,13 @@ void apu_set_channel_enabled(uint8_t channel_bit)
}
/*
* BF unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). BF sound channels are related with I2S host RX channels.
* BF sound channel 0/1 correspond to the left/right channel of I2S RX0; BF channel 2/3 correspond
* APU unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). APU sound channels are related with I2S host RX channels.
* APU sound channel 0/1 correspond to the left/right channel of I2S RX0; APU channel 2/3 correspond
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
* channel and hardware automatically clear the bit after the sample buffers used for direction
* searching is filled full.
* 0x1: writing '1' to enable the corresponding BF sound channel.
* 0x1: writing '1' to enable the corresponding APU sound channel.
*/
void apu_channel_enable(uint8_t channel_bit)
{
@ -267,7 +282,6 @@ void apu_voc_set_direction(en_bf_dir_t direction)
apu->bf_ctl_reg = bf_en_tmp;
}
/*
*I2S host beam-forming Filter FIR16 Coefficient Register
*/
@ -283,6 +297,7 @@ void apu_dir_set_prev_fir(uint16_t *fir_coef)
};
}
}
void apu_dir_set_post_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
@ -295,6 +310,7 @@ void apu_dir_set_post_fir(uint16_t *fir_coef)
};
}
}
void apu_voc_set_prev_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
@ -307,6 +323,7 @@ void apu_voc_set_prev_fir(uint16_t *fir_coef)
};
}
}
void apu_voc_set_post_fir(uint16_t *fir_coef)
{
uint8_t i = 0;
@ -367,7 +384,6 @@ void apu_voc_set_interrupt_mask(uint8_t voc_int_mask)
apu->bf_int_mask_reg = tmp;
}
void apu_set_down_size(uint8_t dir_dwn_size, uint8_t voc_dwn_size)
{
apu_dwsz_cfg_t tmp = apu->bf_dwsz_cfg_reg;

View File

@ -1,3 +1,17 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _apu_H_
#define _apu_H_
@ -160,7 +174,7 @@ typedef struct _apu_fir_coef
typedef struct _apu_dwsz_cfg
{
/**
* TThe down-sizing ratio used for direction searching.
* The down-sizing ratio used for direction searching.
* 0x0: no down-sizing;
* 0x1: 1/2 down sizing;
* 0x2: 1/3 down sizing;
@ -283,38 +297,237 @@ typedef struct _apu_reg
extern volatile apu_reg_t *const apu;
/**
* @brief Voice strength average value right shift factor. When performing sound direction detect,
* the average value of samples from different channels is required, this right shift factor
* is used to perform division.
*
* @param[in] gain value of audio gain.
* 0x0: no right shift;
* 0x1: right shift by 1-bit;
* . . . . . .
* 0xF: right shift by 15-bit.
*
*/
void apu_set_audio_gain(uint16_t gain);
/**
* @brief Set sampling shift.
*
* @param[in] smpl_shift vlaue of sampling shift
*
*/
void apu_set_smpl_shift(uint8_t smpl_shift);
/**
* @brief Get sampling shift
*
* @return vlaue of sampling shift
*/
uint8_t apu_get_smpl_shift(void);
/**
* @brief APU unit sound channel enable control bits. Bit 'x' corresponds to enable bit for sound
* channel 'x' (x = 0, 1, 2, . . ., 7). APU sound channels are related with I2S host RX channels.
* APU sound channel 0/1 correspond to the left/right channel of I2S RX0; APU channel 2/3 correspond
* to left/right channels of I2S RX1; and things like that. Software write '1' to enable a sound
* channel and hardware automatically clear the bit after the sample buffers used for direction
* searching is filled full.
*
*
* @param[in] channel_bit APU sound channel.0x1: writing
* '1' to enable the corresponding APU sound channel.
*
*/
void apu_set_channel_enabled(uint8_t channel_bit);
/**
* @brief I2S host beam-forming direction sample ibuffer read index configure register
*
* @param[in] dir_num the direction of index
* @param[in] dir_bidx
*
*/
void apu_set_direction_delay(uint8_t dir_num, uint8_t *dir_bidx);
/**
* @brief I2S host beam-forming direction sample ibuffer read index configure register
*
* @param[in] radius radius
* @param[in] mic_num_a_circle the num of mic per circle
* @param[in] center 0: no center mic, 1:have center mic
*
*/
void apu_set_delay(float radius, uint8_t mic_num_a_circle, uint8_t center);
/**
* @brief Set ffp shift factor
*
* @param[in] enable_flag enable fft
* @param[in] shift_factor shift factor
*
*/
void apu_set_fft_shift_factor(uint8_t enable_flag, uint16_t shift_factor);
void apu_set_down_size(uint8_t dir_dwn_siz, uint8_t voc_dwn_siz); /*split to 2 functions*/
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask); /*split to 2 functions*/
/**
* @brief Set down-sizing ratio used for voice direction searching and voice stream generation.
*
* @param[in] dir_dwn_siz down-sizing ratio used for voice direction searching
* 0x0: no down-sizing
* 0x1: 1/2 down sizing
* 0x2: 1/3 down sizing
* . . . . . .
* 0xF: 1/16 down sizing
* @param[in] voc_dwn_siz down-sizing ratio used for voice stream generation
* 0x0: no down-sizing
* 0x1: 1/2 down sizing
* 0x2: 1/3 down sizing
* . . . . . .
* 0xF: 1/16 down sizing
*/
void apu_set_down_size(uint8_t dir_dwn_siz, uint8_t voc_dwn_siz);
/**
* @brief Set direction and voice interrupt mask
*
* @param[in] dir_int_mask direction interrupt mask
* @param[in] voc_int_mask voice interrupt mask
*
*/
void apu_set_interrupt_mask(uint8_t dir_int_mask, uint8_t voc_int_mask);
/**
* @brief Enable direction searching.
*
*/
void apu_dir_enable(void);
/**
* @brief Reset direction searching.
*
*/
void apu_dir_reset(void);
void apu_dir_set_prev_fir(uint16_t *fir_coef);
void apu_dir_set_post_fir(uint16_t *fir_coef);
/**
* @brief Set down-sizing ratio used for voice direction searching
*
* @param[in] dir_dwn_siz down-sizing ratio used for voice direction searching
* 0x0: no down-sizing
* 0x1: 1/2 down sizing
* 0x2: 1/3 down sizing
* . . . . . .
* 0xF: 1/16 down sizing
*/
void apu_dir_set_down_size(uint8_t dir_dwn_size);
/**
* @brief Set direction searching interrupt mask
*
* @param[in] dir_int_mask direction interrupt mask
*
*/
void apu_dir_set_interrupt_mask(uint8_t dir_int_mask);
/**
* @brief Clear direction interrupt
*
*/
void apu_dir_clear_int_state(void);
/**
* @brief Valid voice sample stream generation enable bit. After sound direction searching is done, software can
* configure this bit to generate a stream of voice samples for voice recognition.
*
* @param[in] enable_flag 0x1: enable output of voice sample stream. 0x0: stop the voice samlpe stream output.
*
*/
void apu_voc_enable(uint8_t enable_flag);
/**
* @brief Reset voice sample
*
*/
void apu_voc_reset(void);
/**
* @brief Target direction select for valid voice output. When the source voice direaction searching
* is done, software can use this field to select one from 16 sound directions for the following
* voice recognition
*
* @param[in] direction 0x0: select sound direction 0;
* 0x1: select sound direction 1;
* . . . . . .
* 0xF: select sound direction 15.
*/
void apu_voc_set_direction(en_bf_dir_t direction);
void apu_voc_set_prev_fir(uint16_t *fir_coef);
void apu_voc_set_post_fir(uint16_t *fir_coef);
/**
* @brief Set down-sizing ratio used for voice stream generation.
*
* @param[in] voc_dwn_siz down-sizing ratio used for voice stream generation
* 0x0: no down-sizing
* 0x1: 1/2 down sizing
* 0x2: 1/3 down sizing
* . . . . . .
* 0xF: 1/16 down sizing
*/
void apu_voc_set_down_size(uint8_t voc_dwn_size);
/**
* @brief Set voice stream generation interrupt mask
*
* @param[in] voc_int_mask voice interrupt mask
*
*/
void apu_voc_set_interrupt_mask(uint8_t voc_int_mask);
/**
* @brief Clear voice interrupt
*
*/
void apu_voc_clear_int_state(void);
/**
* @brief Reset saturation_counter
*
*/
void apu_voc_reset_saturation_counter(void);
/**
* @brief Get saturation counter
*
* @return vlaue of saturation counter.heigh 16 bit is counter, low 16 bit is total
*/
uint32_t apu_voc_get_saturation_counter(void);
/**
* @brief set saturation limit
*
* @param[in] upper heigh 16 bit is counter
* @param[in] bottom low 16 bit is total
*
*/
void apu_voc_set_saturation_limit(uint16_t upper, uint16_t bottom);
/**
* @brief Get saturation limit
*
* @return vlaue of saturation limit.heigh 16 bit is counter, low 16 bit is total
*/
uint32_t apu_voc_get_saturation_limit(void);
/**
* @brief Print apu setting for debug
*
*/
void apu_print_setting(void);
#if defined(__cplusplus)

View File

@ -425,11 +425,11 @@ int i2c_recv_data(i2c_device_number_t i2c_num, const uint8_t *send_buf, size_t s
*
* @param[in] dma_send_channel_num send dma channel
* @param[in] dma_receive_channel_num receive dma channel
* @param[in] i2c_num i2c number
* @param[in] send_buf send data address
* @param[in] send_buf_len length of send buf
* @param[in] receive_buf receive buf address
* @param[in] receive_buf_len length of receive buf
* @param[in] i2c_num i2c number
* @param[in] send_buf send data address
* @param[in] send_buf_len length of send buf
* @param[in] receive_buf receive buf address
* @param[in] receive_buf_len length of receive buf
*
* @return result
* - 0 Success

View File

@ -1,3 +1,17 @@
/* Copyright 2018 Canaan Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _KPU_H
#define _KPU_H
@ -840,9 +854,53 @@ void kpu_matmul_end(const uint8_t *src, int channels, float *dest, const quantiz
*/
void kpu_dequantize(const uint8_t *src, const quantize_param_t *src_param, size_t count, float *dest);
/**
* @brief Kpu load kmodel
*
* @param[in] ctx Kmodel object
* @param[in] buffer Kmodel buffer
*
* @return result
* - 0 Success
* - Other Fail.
*/
int kpu_load_kmodel(kpu_model_context_t *ctx, const uint8_t *buffer);
/**
* @brief Kpu free kmodel buffer
*
* @param[in] ctx kmodel object
*
*/
void kpu_model_free(kpu_model_context_t *ctx);
/**
* @brief Kpu load kmodel
*
* @param[in] ctx Kmodel object
* @param[in] index Output index
* @param[in] data Output data
* @param[in] size Output data size
*
* @return result
* - 0 Success
* - Other Fail.
*/
int kpu_get_output(kpu_model_context_t *ctx, uint32_t index, uint8_t **data, size_t *size);
/**
* @brief Kpu run kmodel
*
* @param[in] ctx Kmodel object
* @param[in] src Source data
* @param[in] dma_ch Dma channel
* @param[in] done_callback Kpu complete callback
* @param[in] userdata Data of callback
*
* @return result
* - 0 Success
* - Other Fail.
*/
int kpu_run_kmodel(kpu_model_context_t *ctx, const uint8_t *src, dmac_channel_number_t dma_ch, kpu_done_callback_t done_callback, void *userdata);
#endif

View File

@ -20,6 +20,7 @@
#include "sysctl.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
volatile spi_t *const spi[4] =
{
@ -222,6 +223,11 @@ void spi_send_data_normal(spi_device_num_t spi_num, spi_chip_select_t chip_selec
uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F;
spi_transfer_width_t frame_width = spi_get_frame_size(data_bit_length);
uint8_t v_misalign_flag = 0;
uint32_t v_send_data;
if((uintptr_t)tx_buff % frame_width)
v_misalign_flag = 1;
spi_handle->ssienr = 0x01;
spi_handle->ser = 1U << chip_select;
uint32_t i = 0;
@ -233,13 +239,37 @@ void spi_send_data_normal(spi_device_num_t spi_num, spi_chip_select_t chip_selec
{
case SPI_TRANS_INT:
fifo_len = fifo_len / 4 * 4;
for (index = 0; index < fifo_len / 4; index++)
spi_handle->dr[0] = ((uint32_t *)tx_buff)[i++];
if(v_misalign_flag)
{
for(index = 0; index < fifo_len; index +=4)
{
i += 4;
memcpy(&v_send_data, tx_buff + i , 4);
spi_handle->dr[0] = v_send_data;
}
}
else
{
for (index = 0; index < fifo_len / 4; index++)
spi_handle->dr[0] = ((uint32_t *)tx_buff)[i++];
}
break;
case SPI_TRANS_SHORT:
fifo_len = fifo_len / 2 * 2;
for (index = 0; index < fifo_len / 2; index++)
spi_handle->dr[0] = ((uint16_t *)tx_buff)[i++];
if(v_misalign_flag)
{
for(index = 0; index < fifo_len; index +=2)
{
i += 4;
memcpy(&v_send_data, tx_buff + (i++), 2);
spi_handle->dr[0] = v_send_data;
}
}
else
{
for (index = 0; index < fifo_len / 2; index++)
spi_handle->dr[0] = ((uint16_t *)tx_buff)[i++];
}
break;
default:
for (index = 0; index < fifo_len; index++)
@ -770,7 +800,6 @@ void spi_receive_data_multiple(spi_device_num_t spi_num, spi_chip_select_t chip_
case SPI_TRANS_SHORT:
for (index = 0; index < fifo_len; index++)
((uint16_t *)rx_buff)[i++] = (uint16_t)spi_handle->dr[0];
break;
default:
for (index = 0; index < fifo_len; index++)
@ -821,10 +850,6 @@ void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num,
switch(frame_width)
{
case SPI_TRANS_INT:
write_cmd = malloc(cmd_len + rx_len);
for(i = 0; i < cmd_len; i++)
write_cmd[i] = cmd_buff[i];
read_buf = &write_cmd[i];
v_recv_len = rx_len / 4;
break;
case SPI_TRANS_SHORT:
@ -842,14 +867,14 @@ void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num,
v_recv_len = rx_len;
break;
}
spi_receive_data_normal_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, write_cmd, cmd_len, read_buf, v_recv_len);
if(frame_width == SPI_TRANS_INT)
spi_receive_data_normal_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, cmd_buff, cmd_len, rx_buff, v_recv_len);
else
spi_receive_data_normal_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, write_cmd, cmd_len, read_buf, v_recv_len);
switch(frame_width)
{
case SPI_TRANS_INT:
for(i = 0; i < v_recv_len; i++)
((uint32_t *)rx_buff)[i] = read_buf[i];
break;
case SPI_TRANS_SHORT:
for(i = 0; i < v_recv_len; i++)
@ -861,7 +886,8 @@ void spi_receive_data_multiple_dma(dmac_channel_number_t dma_send_channel_num,
break;
}
free(write_cmd);
if(frame_width != SPI_TRANS_INT)
free(write_cmd);
}
@ -1002,7 +1028,7 @@ static void spi_slave_command_mode(void)
{
volatile spi_t *spi_handle = spi[2];
uint8_t cmd_data[8], sum = 0;
spi_transfer_width_t frame_width = spi_get_frame_size(g_instance.data_bit_length - 1);
uint32_t data_width = g_instance.data_bit_length / 8;
spi_device_num_t spi_num = SPI_DEVICE_2;
@ -1114,11 +1140,11 @@ static void spi_slave_command_mode(void)
}
break;
}
}
}
else if (g_instance.command.cmd == WRITE_DATA_BLOCK)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x1 << g_instance.slv_oe) | ((32 - 1) << g_instance.dfs);
spi_handle->dmacr = 0x01;
spi_handle->imr = 0x00;
spi_handle->ssienr = 0x01;
@ -1128,7 +1154,7 @@ static void spi_slave_command_mode(void)
dmac_set_single_mode(g_instance.dmac_channel, (void *)(&spi_handle->dr[0]), (void *)((uintptr_t)g_instance.command.addr & 0xFFFFFFF0), DMAC_ADDR_NOCHANGE, DMAC_ADDR_INCREMENT,
DMAC_MSIZE_4, DMAC_TRANS_WIDTH_32, g_instance.command.len * 4);
}
else if (g_instance.command.cmd == READ_DATA_BLOCK)
else if (g_instance.command.cmd == READ_DATA_BLOCK)
{
spi_handle->ctrlr0 = (0x0 << g_instance.work_mode) | (0x0 << g_instance.slv_oe) | ((32 - 1) << g_instance.dfs);
spi_set_tmod(2, SPI_TMOD_TRANS);
@ -1290,7 +1316,7 @@ void spi_slave_config(uint8_t int_pin, uint8_t ready_pin, dmac_channel_number_t
gpiohs_set_drive_mode(g_instance.int_pin, GPIO_DM_INPUT_PULL_UP);
gpiohs_set_pin_edge(g_instance.int_pin, GPIO_PE_RISING);
gpiohs_set_irq(g_instance.int_pin, 3, spi_slave_cs_irq);
plic_set_priority(IRQN_SPI_SLAVE_INTERRUPT, 4);
plic_irq_enable(IRQN_SPI_SLAVE_INTERRUPT);
plic_irq_register(IRQN_SPI_SLAVE_INTERRUPT, spi_slave_irq, NULL);