pinebuds/platform/hal/best2300p/hal_sensor_eng_best2300p.c

346 lines
11 KiB
C

#include "plat_addr_map.h"
#include "cmsis_nvic.h"
#include "hal_dma.h"
#include "hal_sensor_eng.h"
#include "hal_timer.h"
#include "hal_trace.h"
#include CHIP_SPECIFIC_HDR(reg_sensor_eng)
#include "reg_timer.h"
#include "string.h"
#ifdef RTOS
#include "cmsis_os.h"
#endif
#define MAX_RX_FRAME_NUM (5)
static struct SENSOR_ENG_T * const sensor_eng[] = {
(struct SENSOR_ENG_T *)SENSOR_ENG_BASE,
};
static struct DUAL_TIMER_T * const sensor_eng_timer = (struct DUAL_TIMER_T *)MCU_TIMER2_BASE;
static struct HAL_DMA_DESC_T tx_dma_desc[1];
static struct HAL_DMA_DESC_T rx_dma_desc[MAX_RX_FRAME_NUM];
static HAL_SENSOR_ENG_HANDLER_T sensor_eng_handler;
static uint8_t dma_rx_chan;
static uint8_t *dma_rx_buf;
static uint32_t dma_rx_len;
static uint32_t prev_rx_pos;
void hal_sensor_process_rx_buffer(void)
{
if (dma_rx_len == 0) {
return;
}
uint8_t *dma_buf_active = (uint8_t *)hal_dma_get_cur_dst_addr(dma_rx_chan);
uint32_t result_len = 0;
uint8_t *curr_pos;
curr_pos = dma_rx_buf + prev_rx_pos;
//TRACE(2,"dma_buf_active:%08x curr_pos:%08x", dma_buf_active, curr_pos);
if (dma_buf_active < curr_pos) {
result_len = dma_rx_buf + dma_rx_len - curr_pos;
//TRACE(2,"1:result_len:%08x, curr_pos:%08x", result_len, curr_pos);
//DUMP8("%02x ", curr_pos, result_len);
if (sensor_eng_handler){
sensor_eng_handler(HAL_SENSOR_ENGINE_ID_0, HAL_SENSOR_ENGINE_DEVICE_I2C0, curr_pos, result_len);
}
curr_pos = dma_rx_buf;
}
if (curr_pos < dma_buf_active) {
result_len = dma_buf_active - curr_pos;
//TRACE(2,"2:result_len:%08x, curr_pos:%08x", result_len, curr_pos);
//DUMP8("%02x ", curr_pos, result_len);
if (sensor_eng_handler){
sensor_eng_handler(HAL_SENSOR_ENGINE_ID_0, HAL_SENSOR_ENGINE_DEVICE_I2C0, curr_pos, result_len);
}
curr_pos = dma_buf_active;
}
prev_rx_pos = curr_pos - dma_rx_buf;
}
static void hal_sensor_eng_irq_handler(void)
{
//TRACE(2,"%s: irq=0x%08x", __func__, sensor_eng[0]->SENSOR_INTR_STS);
sensor_eng[0]->SENSOR_INTR_CLR = SENSOR_INTR_CLEAR;
hal_sensor_process_rx_buffer();
}
static void hal_sensor_eng_irq_enable(void)
{
NVIC_SetVector(SENSOR_WKUP_IRQn, (uint32_t)hal_sensor_eng_irq_handler);
NVIC_SetPriority(SENSOR_WKUP_IRQn, IRQ_PRIORITY_HIGH);
NVIC_ClearPendingIRQ(SENSOR_WKUP_IRQn);
NVIC_EnableIRQ(SENSOR_WKUP_IRQn);
}
static void hal_sensor_eng_irq_disable(void)
{
NVIC_DisableIRQ(SENSOR_WKUP_IRQn);
}
static void hal_sensor_eng_timer_stop(void)
{
sensor_eng_timer->timer[0].Control = 0;
sensor_eng_timer->timer[0].IntClr = 1;
}
static void hal_sensor_eng_timer_open(uint32_t ticks)
{
if (ticks > 1) {
ticks -= 1;
} else {
ticks = 1;
}
sensor_eng_timer->timer[0].Load = ticks;
sensor_eng_timer->timer[0].Control = TIMER_CTRL_MODE_PERIODIC | TIMER_CTRL_INTEN | TIMER_CTRL_PRESCALE_DIV_1 | TIMER_CTRL_SIZE_32_BIT;
}
static void hal_sensor_eng_timer_start(void)
{
sensor_eng_timer->timer[0].Control |= TIMER_CTRL_EN;
}
int hal_sensor_engine_open(const struct HAL_SENSOR_ENGINE_CFG_T *cfg)
{
struct HAL_DMA_CH_CFG_T rx_dma_cfg;
enum HAL_DMA_RET_T dret;
uint32_t i;
uint32_t sx_sel;
ASSERT(cfg->id == HAL_SENSOR_ENGINE_ID_0, "Bad sensor engine id: %d", cfg->id);
ASSERT(cfg->device == HAL_SENSOR_ENGINE_DEVICE_I2C0, "Bad sensor engine device: %d", cfg->device);
ASSERT(cfg->rx_burst_cnt <= MAX_RX_FRAME_NUM, "Bad rx_burst_cnt: %d", cfg->rx_burst_cnt);
ASSERT(cfg->tx_dma_cfg, "Bad tx_dma_cfg");
sensor_eng_handler = cfg->handler;
dma_rx_chan = cfg->rx_dma_cfg->ch;
dma_rx_buf = (uint8_t *)cfg->rx_dma_cfg->dst;
dma_rx_len = cfg->rx_burst_len * cfg->rx_burst_cnt;
prev_rx_pos = 0;
dret = hal_dma_init_desc(&tx_dma_desc[0], cfg->tx_dma_cfg, &tx_dma_desc[0], 0);
ASSERT(dret == HAL_DMA_OK, "SensorEng: Failed to init tx desc 0");
dret = hal_gpdma_sg_start(&tx_dma_desc[0], cfg->tx_dma_cfg);
ASSERT(dret == HAL_DMA_OK, "SensorEng: Failed to start tx dma");
if (dma_rx_len) {
ASSERT(cfg->rx_dma_cfg, "Bad rx_dma_cfg");
rx_dma_cfg = *cfg->rx_dma_cfg;
for (i = 0; i < cfg->rx_burst_cnt; i++) {
rx_dma_cfg.dst = (uint32_t)(dma_rx_buf + cfg->rx_burst_len * i);
if (i + 1 == cfg->rx_burst_cnt) {
dret = hal_dma_init_desc(&rx_dma_desc[i], &rx_dma_cfg, &rx_dma_desc[0], 0);
} else {
dret = hal_dma_init_desc(&rx_dma_desc[i], &rx_dma_cfg, &rx_dma_desc[i + 1], 0);
}
ASSERT(dret == HAL_DMA_OK, "SensorEng: Failed to init rx desc %d", i);
}
hal_gpdma_sg_start(&rx_dma_desc[0], cfg->rx_dma_cfg);
ASSERT(dret == HAL_DMA_OK, "SensorEng: Failed to start rx dma");
}
hal_cmu_clock_enable(HAL_CMU_MOD_H_SENSOR_ENG);
hal_cmu_reset_clear(HAL_CMU_MOD_H_SENSOR_ENG);
hal_cmu_clock_enable(HAL_CMU_MOD_O_TIMER2);
hal_cmu_clock_enable(HAL_CMU_MOD_P_TIMER2);
hal_cmu_reset_clear(HAL_CMU_MOD_O_TIMER2);
hal_cmu_reset_clear(HAL_CMU_MOD_P_TIMER2);
sensor_eng[0]->SLV0_CONFIG_REG = SLV_I2C_SPI_SEL(cfg->device) | SLV_SLV_DEV_ID(cfg->device_address) | SLV_ENABLE;
if (dma_rx_len) {
//RX LLI = 1
sensor_eng[0]->GLOBAL_CFG1_REG = SET_BITFIELD(sensor_eng[0]->GLOBAL_CFG1_REG, NUM_OF_RX_LLI0, 1);
}
//TX LLI = 1
sensor_eng[0]->GLOBAL_CFG3_REG = SET_BITFIELD(sensor_eng[0]->GLOBAL_CFG3_REG, NUM_OF_TX_LLI0, 1);
if (cfg->trigger_type == HAL_SENSOR_ENGINE_TRIGGER_GPIO) {
sensor_eng[0]->SLV0_INTR_MASK = ~(1 << cfg->trigger_gpio);
}
if (cfg->data_to_vad) {
sx_sel = cfg->id;
} else {
sx_sel = GET_BITFIELD(sensor_eng[0]->GLOBAL_CFG0_REG, GBL_CODEC_SX_SEL);
}
sensor_eng[0]->GLOBAL_CFG0_REG = GBL_CODEC_SX_SEL(sx_sel) | GBL_SENSORHUB_EN |
(cfg->trigger_type == HAL_SENSOR_ENGINE_TRIGGER_GPIO ? GBL_TRIGGER_TYPE : 0);
if (cfg->trigger_type == HAL_SENSOR_ENGINE_TRIGGER_TIMER) {
hal_sensor_eng_timer_open(US_TO_TICKS(cfg->period_us));
hal_sensor_eng_timer_start();
}
hal_sensor_eng_irq_enable();
return 0;
}
int hal_sensor_engine_close(enum HAL_SENSOR_ENGINE_ID_T id)
{
uint32_t cnt;
hal_sensor_eng_irq_disable();
hal_sensor_eng_timer_stop();
sensor_eng[0]->GLOBAL_CFG0_REG &= ~GBL_SENSORHUB_EN;
// Wait until sensor engine becomes idle
cnt = 0;
while ((sensor_eng[0]->SENSOR_STATUS & SENSOR_ENG_FSM_MASK) && cnt < 10) {
osDelay(1);
cnt++;
}
if (sensor_eng[0]->SENSOR_STATUS & SENSOR_ENG_FSM_MASK) {
ASSERT(false, "%s: Sensor engine cannot become idle: 0x%08X", __func__, sensor_eng[0]->SENSOR_STATUS);
}
sensor_eng[0]->SLV0_INTR_MASK = ~0UL;
dma_rx_len = 0;
hal_cmu_reset_set(HAL_CMU_MOD_P_TIMER2);
hal_cmu_reset_set(HAL_CMU_MOD_O_TIMER2);
hal_cmu_clock_disable(HAL_CMU_MOD_P_TIMER2);
hal_cmu_clock_disable(HAL_CMU_MOD_O_TIMER2);
hal_cmu_reset_set(HAL_CMU_MOD_H_SENSOR_ENG);
hal_cmu_clock_disable(HAL_CMU_MOD_H_SENSOR_ENG);
return 0;
}
#if 0
#include "hal_i2c.h"
#define READ_BUF_BURST_CNT 5
#define TRIGGER_TIMER_US 500000
#define LOCK_INTR_CNT 3
#define TRIGGER_GPIO_PIN HAL_GPIO_PIN_P0_0
static void hal_sensor_eng_external_input_pin_irqhandler(enum HAL_GPIO_PIN_T pin)
{
bool gpio_lvl = 0;
gpio_lvl = hal_gpio_pin_get_val(pin);
TRACE(2,"hal_sensor_eng_external_irqhandler io=%d val=%d", pin, gpio_lvl);
}
static void sensor_timer_test_handler(enum HAL_I2C_ID_T id, const uint8_t *buf, uint32_t len)
{
TRACE(7,"%s: id=%d len=%u %02X-%02X-%02X-%02x", __FUNCTION__, id, len, buf[0], buf[1], buf[2], buf[3]);
}
static void sensor_gpio_test_handler(enum HAL_I2C_ID_T id, const uint8_t *buf, uint32_t len)
{
TRACE(7,"%s: id=%d len=%u %02X-%02X-%02X-%02x", __FUNCTION__, id, len, buf[0], buf[1], buf[2], buf[3]);
}
static int sensor_eng_test(enum HAL_SENSOR_ENGINE_TRIGGER_T trigger_type)
{
static uint8_t write_buf[3];
static uint8_t read_buf[READ_BUF_BURST_CNT][sizeof(write_buf) * 2];
int ret;
struct HAL_I2C_CONFIG_T cfg;
struct HAL_I2C_SENSOR_ENGINE_CONFIG_T se_cfg;
enum HAL_I2C_ID_T id;
uint32_t i;
id = HAL_I2C_ID_0;
for (i = 0; i < sizeof(write_buf); i++) {
write_buf[i] = i;
}
memset(&cfg, 0, sizeof(cfg));
cfg.mode = HAL_I2C_API_MODE_SENSOR_ENGINE;
cfg.as_master = 1;
cfg.use_dma = 1;
cfg.use_sync = 1;
cfg.speed = 100000;
ret = hal_i2c_open(id, &cfg);
if (ret) {
TRACE(2,"%s: i2c open failed %d", __func__, ret);
return ret;
}
memset(&se_cfg, 0, sizeof(se_cfg));
se_cfg.id = HAL_SENSOR_ENGINE_ID_0;
se_cfg.trigger_type = trigger_type;
if (trigger_type == HAL_SENSOR_ENGINE_TRIGGER_TIMER) {
se_cfg.period_us = TRIGGER_TIMER_US;
se_cfg.handler = sensor_timer_test_handler;
} else {
se_cfg.trigger_gpio = TRIGGER_GPIO_PIN;
se_cfg.handler = sensor_gpio_test_handler;
}
se_cfg.target_addr = 0x17;
se_cfg.write_buf = &write_buf[0];
se_cfg.write_txn_len = 1;
se_cfg.read_buf = &read_buf[0][0];
se_cfg.read_txn_len = 2;
se_cfg.txn_cnt = sizeof(write_buf);
se_cfg.read_burst_cnt = READ_BUF_BURST_CNT;
hal_i2c_sensor_engine_start(id, &se_cfg);
uint32_t lock = int_lock();
while (1) {
hal_sys_timer_delay(US_TO_TICKS(TRIGGER_TIMER_US) * LOCK_INTR_CNT);
TRACE_IMM(2,"%s: delay %u ms", __func__, (TRIGGER_TIMER_US / 1000 * LOCK_INTR_CNT));
hal_sensor_process_rx_buffer();
}
int_unlock(lock);
return 0;
}
int hal_sensor_eng_periodic_timer_test(void)
{
sensor_eng_test(HAL_SENSOR_ENGINE_TRIGGER_TIMER);
return 0;
}
int hal_sensor_eng_external_input_test(void)
{
static const struct HAL_IOMUX_PIN_FUNCTION_MAP ext_pin[] = {
{TRIGGER_GPIO_PIN, HAL_IOMUX_FUNC_GPIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENABLE},
};
struct HAL_GPIO_IRQ_CFG_T gpiocfg;
sensor_eng_test(HAL_SENSOR_ENGINE_TRIGGER_GPIO);
hal_iomux_init((struct HAL_IOMUX_PIN_FUNCTION_MAP *)ext_pin, sizeof(ext_pin)/sizeof(struct HAL_IOMUX_PIN_FUNCTION_MAP));
hal_gpio_pin_set_dir(TRIGGER_GPIO_PIN, HAL_GPIO_DIR_IN, 1);
gpiocfg.irq_enable = true;
gpiocfg.irq_debounce = false;
gpiocfg.irq_polarity = HAL_GPIO_IRQ_POLARITY_HIGH_RISING;
gpiocfg.irq_handler = hal_sensor_eng_external_input_pin_irqhandler;
gpiocfg.irq_type = HAL_GPIO_IRQ_TYPE_EDGE_SENSITIVE;
hal_gpio_setup_irq(TRIGGER_GPIO_PIN, &gpiocfg);
TRACE(5,"SLV0:%08x CFG1:0x%08x CFG3:0x%08x CFG0:0x%08x INTR_MASK:0x%08x",
sensor_eng[0]->SLV0_CONFIG_REG,
sensor_eng[0]->GLOBAL_CFG1_REG,
sensor_eng[0]->GLOBAL_CFG3_REG,
sensor_eng[0]->GLOBAL_CFG0_REG,
sensor_eng[0]->SLV0_INTR_MASK);
return 0;
}
#endif