初版
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
#include "includes.h"
|
||||
#include "bsp.h"
|
||||
#include "iic_api.h"
|
||||
|
||||
void bsp_init()
|
||||
{
|
||||
#if P11_HW_IIC_EN
|
||||
hw_iic_master_module_init();
|
||||
#endif//P11_HW_IIC_EN
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "includes.h"
|
||||
#include "timer.h"
|
||||
|
||||
void clock_early_init()
|
||||
{
|
||||
if (M2P_LRC24M_MODE) {
|
||||
//P11_SYS_CLK_SEL(P11_SYS_CLK_BTOSC_24M);
|
||||
//P11_SYS_CLK_SEL(P11_SYS_CLK_LRC24M);
|
||||
P11_SYS_CLK_SEL(P11_SYS_CLK_RC16M);
|
||||
|
||||
#if 0
|
||||
//PB0 OUT
|
||||
P11_PORT->PB_DIR &= ~BIT(0);
|
||||
P11_PORT->PB_SEL |= BIT(0);
|
||||
//och0 sysclk
|
||||
SFR(P11_PORT->OCH_CON0, 0, 4, 7);
|
||||
//crossbar och0
|
||||
P11_OMAP->P11_PB0_OUT = P11_FO_GP_OCH0;
|
||||
|
||||
while (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
//std12M 输出
|
||||
SFR(P11_CLOCK->CLK_CON1, 15, 2, 1); //MSYS_BT24M --> P11_BT24M
|
||||
SFR(P11_CLOCK->CLK_CON1, 17, 3, 1); //STD12M sel P11_BT24M input
|
||||
SFR(P11_CLOCK->CLK_CON1, 20, 2, 0); // div0
|
||||
SFR(P11_CLOCK->CLK_CON1, 22, 2, 1); // div1
|
||||
}
|
||||
|
||||
static void clock_switch_lrc24m()
|
||||
{
|
||||
printf("fun: %s\n", __FUNCTION__);
|
||||
|
||||
P11_SYS_CLK_SEL(P11_SYS_CLK_LRC24M);
|
||||
|
||||
uart_clk_sel(UART_CLK_SYS_CLK);
|
||||
}
|
||||
|
||||
static void clock_msg_handler(void *priv, u8 *msg, u32 len)
|
||||
{
|
||||
switch (msg[0]) {
|
||||
case MSG_CLOCK_LRC24M_OK:
|
||||
clock_switch_lrc24m();
|
||||
timer_set_clock_source(GPTIMER_CLK_SRC_LRC_24M);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_M2P_MSG_HANDLER(0, MSG_CLOCK, clock_msg_handler);
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "includes.h"
|
||||
|
||||
const int LIB_CONFIG_LPCTMU_ENABLE = CONFIG_LPCTMU_ENABLE;
|
||||
const int LIB_CONFIG_EXCEPTION_RESET_ENABLE = !CONFIG_UART_DEBUG_ENABLE;
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef __LIB_CONFIG_H__
|
||||
#define __LIB_CONFIG_H__
|
||||
|
||||
extern const int LIB_CONFIG_LPCTMU_ENABLE;
|
||||
extern const int LIB_CONFIG_EXCEPTION_RESET_ENABLE;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "sdk_config.h"
|
||||
#include "includes.h"
|
||||
#ifdef CONFIG_UART_DEBUG_ENABLE
|
||||
const char libs_debug AT(.LOG_TAG_CONST) = TRUE; //打印总开关
|
||||
#else
|
||||
const char libs_debug AT(.LOG_TAG_CONST) = FALSE; //打印总开关
|
||||
#endif
|
||||
|
||||
#define CONFIG_DEBUG_LIBS(X) (X & libs_debug)
|
||||
|
||||
const char log_tag_const_i_MAIN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_d_MAIN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_e_MAIN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
|
||||
const char log_tag_const_i_UBOOT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_d_UBOOT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_e_UBOOT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
|
||||
const char log_tag_const_i_UPGRADE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_d_UPGRADE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_e_UPGRADE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
|
||||
const char log_tag_const_i_FLASH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_d_FLASH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_e_FLASH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
|
||||
const char log_tag_const_i_FS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_d_FS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_e_FS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
|
||||
const char log_tag_const_i_SFC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_d_SFC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
const char log_tag_const_e_SFC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(0);
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef __APP_CONFIG_H__
|
||||
#define __APP_CONFIG_H__
|
||||
|
||||
|
||||
|
||||
|
||||
//==========================================================//
|
||||
// 串口打印使能开关 //
|
||||
//==========================================================//
|
||||
#define CONFIG_UART_DEBUG_ENABLE 0
|
||||
#define CONFIG_DEBUG_UART_TX_PIN IO_PORTB_00
|
||||
#define CONFIG_DEBUG_UART_BAUD 115200L
|
||||
|
||||
|
||||
//==========================================================//
|
||||
// 低功耗触摸 //
|
||||
//==========================================================//
|
||||
|
||||
#define CONFIG_LPCTMU_ENABLE 0
|
||||
|
||||
|
||||
//==========================================================//
|
||||
// SENSOR驱动 //
|
||||
//==========================================================//
|
||||
|
||||
#define CONFIG_SENSOR_DRIVER_ENABLE 0
|
||||
#define CONFIG_SENSOR_SLEEP_ENABLE 0 //自动让SENSOR睡眠,需要SENSOR支持唤醒检测并IO中断唤醒MCU
|
||||
|
||||
#define TCFG_SC7A20_ENABLE 0
|
||||
|
||||
#define TCFG_MMC5603_ENABLE 0
|
||||
|
||||
#define TCFG_VCHR11S_ENABLE 0
|
||||
#define TCFG_HRS3602_ENABLE 0
|
||||
#define TCFG_HR_SENSOR_READ_BY_INT 0
|
||||
|
||||
//==========================================================//
|
||||
// soft iic //
|
||||
//==========================================================//
|
||||
#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_02 //spft IIC CLK
|
||||
#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_01 //spft IIC DAT
|
||||
#define TCFG_SW_I2C0_DELAY_CNT 1 //软件IIC延时参数,影响通讯时钟频率
|
||||
|
||||
|
||||
|
||||
//========================================================== //
|
||||
// hw iic //
|
||||
//==========================================================//
|
||||
#define P11_HW_IIC_EN 0
|
||||
#define P11_HW_IIC_SCL IO_PORTB_02
|
||||
#define P11_HW_IIC_SDA IO_PORTB_01
|
||||
#define P11_HW_IIC_FREQ (400*1000)
|
||||
#define P11_HW_IIC_PU_EN 1
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,407 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".iic.bss")
|
||||
#pragma data_seg(".iic.data")
|
||||
#pragma const_seg(".iic.const")
|
||||
#pragma code_seg(".iic.text")
|
||||
#pragma str_literal_override(".iic.text")
|
||||
#endif /* #ifdef SUPPORT_MS_EXTENSIONS */
|
||||
|
||||
#include "includes.h"
|
||||
#include "sdk_config.h"
|
||||
#include "gpio.h"
|
||||
#include "iic_api.h"
|
||||
|
||||
|
||||
/******************************soft iic*****************************/
|
||||
//如果无reg_addr:reg_addr=NULL,reg_len=0
|
||||
//return: <0:error, =read_len:ok
|
||||
int soft_i2c_master_read_nbytes_from_device_reg(soft_iic_dev iic,
|
||||
unsigned char dev_addr, //设备地址
|
||||
unsigned char *reg_addr, unsigned char reg_len,//设备寄存器地址,长度
|
||||
unsigned char *read_buf, int read_len)//缓存buf,读取长度
|
||||
{
|
||||
u8 ack;
|
||||
int ret = 0;
|
||||
if (soft_iic_check_busy(iic) != IIC_OK) { //busy
|
||||
ret = IIC_ERROR_BUSY; //busy
|
||||
goto _read_exit2;
|
||||
}
|
||||
soft_iic_start(iic);
|
||||
|
||||
if ((reg_addr != NULL) && (reg_len != 0)) {
|
||||
ack = soft_iic_tx_byte(iic, dev_addr & 0xfe);
|
||||
if (ack == 0) {
|
||||
printf("<err>:dev_addr no ack!\n");
|
||||
ret = IIC_ERROR_DEV_ADDR_ACK_ERROR; //无应答
|
||||
goto _read_exit1;
|
||||
}
|
||||
|
||||
for (u8 i = 0; i < reg_len; i++) {
|
||||
ack = soft_iic_tx_byte(iic, reg_addr[i]);
|
||||
if (ack == 0) {
|
||||
printf("<err>:reg_addr no ack!\n");
|
||||
ret = IIC_ERROR_REG_ADDR_ACK_ERROR; //无应答
|
||||
goto _read_exit1;
|
||||
}
|
||||
}
|
||||
|
||||
soft_iic_start(iic);
|
||||
}
|
||||
|
||||
ack = soft_iic_tx_byte(iic, dev_addr | BIT(0));
|
||||
if (ack == 0) {
|
||||
printf("<err>:dev_addr no ack!\n");
|
||||
ret = IIC_ERROR_DEV_ADDR_ACK_ERROR; //无应答
|
||||
goto _read_exit1;
|
||||
}
|
||||
|
||||
ret = soft_iic_read_buf(iic, read_buf, read_len);
|
||||
_read_exit1:
|
||||
soft_iic_stop(iic);
|
||||
_read_exit2:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//如果无reg_addr:reg_addr=NULL,reg_len=0
|
||||
//return: =write_len:ok, other:error
|
||||
int soft_i2c_master_write_nbytes_to_device_reg(soft_iic_dev iic,
|
||||
unsigned char dev_addr, //设备地址
|
||||
unsigned char *reg_addr, unsigned char reg_len,//设备寄存器地址,长度
|
||||
unsigned char *write_buf, int write_len)//数据buf, 写入长度
|
||||
{
|
||||
int res;
|
||||
u8 ack;
|
||||
if (soft_iic_check_busy(iic) != IIC_OK) { //busy
|
||||
res = IIC_ERROR_BUSY; //busy
|
||||
goto _write_exit2;
|
||||
}
|
||||
|
||||
soft_iic_start(iic);
|
||||
ack = soft_iic_tx_byte(iic, dev_addr);
|
||||
if (ack == 0) {
|
||||
printf("<err>:dev_addr no ack!\n");
|
||||
res = IIC_ERROR_DEV_ADDR_ACK_ERROR; //无应答
|
||||
goto _write_exit1;
|
||||
}
|
||||
|
||||
if ((reg_addr != NULL) && (reg_len != 0)) {
|
||||
for (u8 i = 0; i < reg_len; i++) {
|
||||
ack = soft_iic_tx_byte(iic, reg_addr[i]);
|
||||
if (ack == 0) {
|
||||
printf("<err>:reg_addr no ack!\n");
|
||||
res = IIC_ERROR_REG_ADDR_ACK_ERROR; //无应答
|
||||
goto _write_exit1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (res = 0; res < write_len; res++) {
|
||||
if (0 == soft_iic_tx_byte(iic, write_buf[res])) {
|
||||
printf("<err>:write data no ack!\n");
|
||||
goto _write_exit1;
|
||||
}
|
||||
}
|
||||
_write_exit1:
|
||||
soft_iic_stop(iic);
|
||||
_write_exit2:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************hw iic master*****************************/
|
||||
|
||||
#define HW_IIC_MASTER_ISR_MODE_SEL 0 //1:中断模式,0:轮询
|
||||
|
||||
//如果无reg_addr:reg_addr=NULL,reg_len=0
|
||||
//return: other:error, =read_len:ok
|
||||
int hw_i2c_master_read_nbytes_from_device_reg(hw_iic_dev iic,
|
||||
unsigned char dev_addr, //设备地址
|
||||
unsigned char *reg_addr, unsigned char reg_len,//设备寄存器地址,长度
|
||||
unsigned char *read_buf, int read_len)//缓存buf,读取长度
|
||||
{
|
||||
#if HW_IIC_MASTER_ISR_MODE_SEL && HW_IIC_MASTER_ISR_EN
|
||||
#if defined(P11_HW_IIC_NUM)&&P11_HW_IIC_NUM
|
||||
if (iic != HW_P11_IIC_0)
|
||||
#endif
|
||||
{
|
||||
struct hw_iic_master_isr_transmit iic_isr_info = {
|
||||
.dev_addr = dev_addr & 0xfe,
|
||||
.restart_flag = 1,
|
||||
.reg_buf = reg_addr,
|
||||
.reg_len = reg_len,
|
||||
.data_buf = read_buf,
|
||||
.rx_len = read_len,
|
||||
.tx_len = 0,
|
||||
};
|
||||
if ((reg_addr == NULL) || (reg_len == 0)) {
|
||||
iic_isr_info .dev_addr = dev_addr | BIT(0);
|
||||
iic_isr_info .restart_flag = 0;
|
||||
}
|
||||
enum iic_state_enum iic_sta = hw_iic_master_isr_transmit_cfg(iic, &iic_isr_info, 20);//byte间隔超时20:20*30ms
|
||||
if (iic_sta != IIC_OK) {
|
||||
log_error("iic%d isr sta:%d\n", iic, iic_sta);
|
||||
if (iic_sta == IIC_ERROR_MASTER_ERROR) {
|
||||
hw_iic_reset(iic);
|
||||
}
|
||||
return iic_sta;
|
||||
}
|
||||
return iic_isr_info.xfer_postion;
|
||||
}
|
||||
#endif
|
||||
|
||||
u8 ack;
|
||||
int ret = 0;
|
||||
if (hw_iic_check_busy(iic) != IIC_OK) { //busy
|
||||
ret = IIC_ERROR_BUSY; //busy
|
||||
goto _read_exit2;
|
||||
}
|
||||
|
||||
ret = hw_iic_start(iic);
|
||||
if (ret < 0) {
|
||||
printf("<err>:iic lock busy!%d\n", ret);
|
||||
goto _read_exit2;
|
||||
}
|
||||
if ((reg_addr != NULL) && (reg_len != 0)) {
|
||||
ack = hw_iic_tx_byte(iic, dev_addr & 0xfe);
|
||||
if (ack == 0) {
|
||||
printf("<err>:dev_addr no ack!\n");
|
||||
ret = IIC_ERROR_DEV_ADDR_ACK_ERROR; //无应答
|
||||
goto _read_exit1;
|
||||
}
|
||||
|
||||
for (u8 i = 0; i < reg_len; i++) {
|
||||
ack = hw_iic_tx_byte(iic, reg_addr[i]);
|
||||
if (ack == 0) {
|
||||
printf("<err>:reg_addr no ack!\n");
|
||||
ret = IIC_ERROR_REG_ADDR_ACK_ERROR; //无应答
|
||||
goto _read_exit1;
|
||||
}
|
||||
}
|
||||
|
||||
hw_iic_start(iic);
|
||||
}
|
||||
|
||||
ack = hw_iic_tx_byte(iic, dev_addr | BIT(0));
|
||||
if (ack == 0) {
|
||||
printf("<err>:dev_addr no ack!\n");
|
||||
ret = IIC_ERROR_DEV_ADDR_ACK_ERROR; //无应答
|
||||
goto _read_exit1;
|
||||
}
|
||||
|
||||
ret = hw_iic_read_buf(iic, read_buf, read_len);
|
||||
_read_exit1:
|
||||
hw_iic_stop(iic);
|
||||
if (ret != read_len) {
|
||||
hw_iic_err_reset(iic);
|
||||
hw_iic_reset(iic);
|
||||
}
|
||||
_read_exit2:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//如果无reg_addr:reg_addr=NULL,reg_len=0
|
||||
//return: =write_len:ok, other:error
|
||||
int hw_i2c_master_write_nbytes_to_device_reg(hw_iic_dev iic,
|
||||
unsigned char dev_addr, //设备地址
|
||||
unsigned char *reg_addr, unsigned char reg_len,//设备寄存器地址,长度
|
||||
unsigned char *write_buf, int write_len)//数据buf, 写入长度
|
||||
{
|
||||
#if HW_IIC_MASTER_ISR_EN
|
||||
#if defined(P11_HW_IIC_NUM)&&P11_HW_IIC_NUM
|
||||
if (iic != HW_P11_IIC_0)
|
||||
#endif
|
||||
{
|
||||
struct hw_iic_master_isr_transmit iic_isr_info = {
|
||||
.dev_addr = dev_addr,
|
||||
.restart_flag = 0,
|
||||
.reg_buf = reg_addr,
|
||||
.reg_len = reg_len,
|
||||
.data_buf = write_buf,
|
||||
.rx_len = 0,
|
||||
.tx_len = write_len,
|
||||
};
|
||||
enum iic_state_enum iic_sta = hw_iic_master_isr_transmit_cfg(iic, &iic_isr_info, 20);//byte间隔超时20:20*30ms
|
||||
if (iic_sta != IIC_OK) {
|
||||
log_error("iic%d isr sta:%d\n", iic, iic_sta);
|
||||
if (iic_sta == IIC_ERROR_MASTER_ERROR) {
|
||||
hw_iic_reset(iic);
|
||||
}
|
||||
return iic_sta;
|
||||
}
|
||||
return iic_isr_info.xfer_postion;
|
||||
}
|
||||
#endif
|
||||
|
||||
int res;
|
||||
u8 ack;
|
||||
if (hw_iic_check_busy(iic) != IIC_OK) { //busy
|
||||
res = IIC_ERROR_BUSY; //busy
|
||||
goto _write_exit2;
|
||||
}
|
||||
|
||||
res = hw_iic_start(iic);
|
||||
if (res < 0) {
|
||||
printf("<err>:iic lock busy!%d\n", res);
|
||||
goto _write_exit2;
|
||||
}
|
||||
ack = hw_iic_tx_byte(iic, dev_addr);
|
||||
if (ack == 0) {
|
||||
printf("<err>:dev_addr no ack!\n");
|
||||
res = IIC_ERROR_DEV_ADDR_ACK_ERROR; //无应答
|
||||
goto _write_exit1;
|
||||
}
|
||||
|
||||
if ((reg_addr != NULL) && (reg_len != 0)) {
|
||||
for (u8 i = 0; i < reg_len; i++) {
|
||||
ack = hw_iic_tx_byte(iic, reg_addr[i]);
|
||||
if (ack == 0) {
|
||||
printf("<err>:reg_addr no ack!\n");
|
||||
res = IIC_ERROR_REG_ADDR_ACK_ERROR; //无应答
|
||||
goto _write_exit1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (res = 0; res < write_len; res++) {
|
||||
if (0 == hw_iic_tx_byte(iic, write_buf[res])) {
|
||||
printf("<err>:write data no ack!\n");
|
||||
goto _write_exit1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
res = hw_iic_write_buf(iic, write_buf, write_len);
|
||||
#endif
|
||||
_write_exit1:
|
||||
hw_iic_stop(iic);
|
||||
if (res != write_len) {
|
||||
hw_iic_err_reset(iic);
|
||||
hw_iic_reset(iic);
|
||||
}
|
||||
_write_exit2:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************hw iic slave*****************************/
|
||||
|
||||
//rx协议:start,addr write,data0,data1,,,,,,stop
|
||||
int hw_iic_slave_polling_rx(hw_iic_dev iic, u8 *rx_buf)
|
||||
{
|
||||
int rx_cnt = 0;
|
||||
int rx_state = 0;
|
||||
|
||||
printf("--iic slave polling rx --\n");
|
||||
local_irq_disable();//关闭所有中断
|
||||
rx_state = hw_iic_slave_rx_prepare(iic, 0, 600000);//1s
|
||||
if (rx_state == IIC_SLAVE_RX_PREPARE_OK) { //rx
|
||||
} else if (rx_state == IIC_SLAVE_RX_PREPARE_TIMEOUT) { //error
|
||||
printf("<err>:iic slave wait addr timeout!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
} else if (rx_state == IIC_SLAVE_RX_PREPARE_END_OK) { //end
|
||||
printf("<err>:iic slave wait end!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
rx_state = hw_iic_slave_rx_byte(iic, &rx_buf[0]);//addr
|
||||
if (rx_state >= IIC_SLAVE_RX_ADDR_RX) { //rx
|
||||
} else if (rx_state == IIC_SLAVE_RX_ADDR_NO_MATCH) { //error
|
||||
printf("<err>:iic slave rx addr error!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
} else if (rx_state == IIC_SLAVE_RX_ADDR_TX) { //tx
|
||||
|
||||
}
|
||||
rx_state = hw_iic_slave_rx_prepare(iic, 1, 100000);//1s, 1:收到数据应答
|
||||
if (rx_state == IIC_SLAVE_RX_PREPARE_OK) { //rx
|
||||
} else if (rx_state == IIC_SLAVE_RX_PREPARE_TIMEOUT) { //error
|
||||
printf("<err>:iic slave wait reg timeout!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
} else if (rx_state == IIC_SLAVE_RX_PREPARE_END_OK) { //end
|
||||
printf("iic slave wait end!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
rx_cnt = hw_iic_slave_rx_nbyte(iic, &rx_buf[1]);
|
||||
local_irq_enable();
|
||||
/* printf("rx addr:%x, slave addr:%x\n", rx_buf[0], hw_iic_slave_get_addr(iic)); */
|
||||
rx_cnt++;
|
||||
/* log_info_hexdump(rx_buf, rx_cnt); */
|
||||
printf("~~~~~iic rx polling end~~~~~\n");
|
||||
memset(rx_buf, 0, rx_cnt);
|
||||
return rx_cnt;
|
||||
}
|
||||
|
||||
//tx协议:start,addr read,data0,data1,,,,,nack,stop
|
||||
int hw_iic_slave_polling_tx(hw_iic_dev iic, u8 *tx_buf)
|
||||
{
|
||||
u8 slave_rx_data[3] = {0, 0, 0};
|
||||
int rx_cnt = 0, tx_cnt = 0;
|
||||
int rx_state = 0;
|
||||
printf("--iic slave polling tx --\n");
|
||||
local_irq_disable();//关闭所有中断
|
||||
rx_state = hw_iic_slave_rx_prepare(iic, 0, 600000);//1s
|
||||
if (rx_state == IIC_SLAVE_RX_PREPARE_OK) { //rx
|
||||
} else if (rx_state == IIC_SLAVE_RX_PREPARE_TIMEOUT) { //error
|
||||
printf("<err>:iic slave wait addr timeout!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
} else if (rx_state == IIC_SLAVE_RX_PREPARE_END_OK) { //end
|
||||
printf("<err>:iic slave wait end!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
rx_state = hw_iic_slave_rx_byte(iic, &slave_rx_data[rx_cnt++]);//addr
|
||||
if (rx_state >= IIC_SLAVE_RX_ADDR_RX) { //rx
|
||||
} else if (rx_state == IIC_SLAVE_RX_ADDR_TX) { //tx
|
||||
hw_iic_slave_tx_byte(iic, tx_buf[tx_cnt++]);
|
||||
goto _tx_strat;
|
||||
} else { //error
|
||||
printf("<err>:iic slave rx addr error!\n");
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
_tx_strat:
|
||||
tx_cnt = hw_iic_slave_tx_nbyte(iic, &tx_buf[tx_cnt]);
|
||||
|
||||
local_irq_enable();
|
||||
/* printf("rx0 addr:%x, slave addr:%x\n", slave_rx_data[0], hw_iic_slave_get_addr(iic)); */
|
||||
/* log_info_hexdump(slave_rx_data, rx_cnt); */
|
||||
printf("~~~~~iic tx polling end~~~~~\n");
|
||||
return tx_cnt + 1; //ok
|
||||
}
|
||||
|
||||
|
||||
void hw_iic_master_module_init()
|
||||
{
|
||||
struct iic_master_config hw_iic_config = {
|
||||
.role = IIC_MASTER,
|
||||
.scl_io = P11_HW_IIC_SCL,
|
||||
.sda_io = P11_HW_IIC_SDA,
|
||||
.io_mode = P11_HW_IIC_PU_EN ,//1:上拉或0:浮空
|
||||
.hdrive = PORT_DRIVE_STRENGT_2p4mA, //enum GPIO_HDRIVE 0:2.4MA, 1:8MA, 2:26.4MA, 3:40MA
|
||||
.master_frequency = P11_HW_IIC_FREQ , //软件iic频率不准(hz)
|
||||
.io_filter = 1, //软件无效
|
||||
.ie_en = 0,//1:注册中断
|
||||
.irq_priority = 3,//优先级
|
||||
};
|
||||
hw_iic_dev iic_dev = HW_IIC_0;
|
||||
hw_iic_init(HW_IIC_0, &hw_iic_config);
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".iic.bss")
|
||||
#pragma data_seg(".iic.data")
|
||||
#pragma const_seg(".iic.const")
|
||||
#pragma code_seg(".iic.text")
|
||||
#pragma str_literal_override(".iic.text")
|
||||
#endif /* #ifdef SUPPORT_MS_EXTENSIONS */
|
||||
|
||||
#include "includes.h"
|
||||
#include "gpio.h"
|
||||
#include "iic_soft.h"
|
||||
|
||||
|
||||
|
||||
static u8 soft_iic_state[MAX_SOFT_IIC_NUM];
|
||||
static struct iic_master_config soft_iic_cfg_cache[MAX_SOFT_IIC_NUM];
|
||||
|
||||
//input pull up
|
||||
#define IIC_SCL_H(scl) \
|
||||
gpio_set_direction(scl, 1)
|
||||
|
||||
#define IIC_SCL_L(scl) \
|
||||
gpio_set_direction(scl, 0); \
|
||||
gpio_set_output_value(scl, 0)
|
||||
|
||||
|
||||
#define IIC_SDA_DIR(sda, val) \
|
||||
gpio_set_direction(sda, val)
|
||||
|
||||
//input pull up
|
||||
#define IIC_SDA_H(sda) \
|
||||
gpio_set_direction(sda, 1)
|
||||
|
||||
#define IIC_SDA_L(sda) \
|
||||
gpio_set_direction(sda, 0); \
|
||||
gpio_set_output_value(sda, 0)
|
||||
|
||||
#define IIC_SDA_READ(sda) \
|
||||
gpio_read(sda)
|
||||
|
||||
#define soft_iic_delay(num) \
|
||||
delay_cnt= num; \
|
||||
while (delay_cnt--) { \
|
||||
asm("nop"); \
|
||||
}
|
||||
static inline u32 iic_get_delay(soft_iic_dev iic)
|
||||
{
|
||||
u32 hsb_clk = 16000000;//clk_get("sys");
|
||||
u32 delay_num = 0;
|
||||
return delay_num;
|
||||
}
|
||||
|
||||
extern const struct iic_master_config soft_iic_cfg_const[MAX_SOFT_IIC_NUM];
|
||||
struct iic_master_config *get_soft_iic_config(soft_iic_dev iic)
|
||||
{
|
||||
return (struct iic_master_config *)&soft_iic_cfg_const[iic];
|
||||
}
|
||||
enum iic_state_enum soft_iic_init(soft_iic_dev iic, struct iic_master_config *i2c_config)
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
if (i2c_config == NULL) {
|
||||
printf("error: soft iic%d param error!\n", iic);
|
||||
return IIC_ERROR_PARAM_ERROR;
|
||||
}
|
||||
if (iic >= MAX_SOFT_IIC_NUM) {
|
||||
printf("error: soft iic index:%d error!\n", iic);
|
||||
return IIC_ERROR_INDEX_ERROR;
|
||||
}
|
||||
if ((soft_iic_state[iic]&BIT(7)) != 0) {
|
||||
printf("error: soft iic%d has been occupied!\n", iic);
|
||||
return IIC_ERROR_INIT_FAIL;
|
||||
}
|
||||
soft_iic_state[iic] = BIT(7);//init ok
|
||||
memcpy(&soft_iic_cfg_cache[iic], i2c_config, sizeof(struct iic_master_config));
|
||||
|
||||
//freq:
|
||||
|
||||
if (i2c_config->io_mode) {//pull up
|
||||
gpio_set_pull_up(i2c_config->scl_io, 1);
|
||||
gpio_set_pull_up(i2c_config->sda_io, 1);
|
||||
} else {
|
||||
gpio_set_pull_up(i2c_config->scl_io, 0);
|
||||
gpio_set_pull_up(i2c_config->sda_io, 0);
|
||||
}
|
||||
gpio_set_hd(i2c_config->scl_io, i2c_config->hdrive);
|
||||
gpio_set_hd(i2c_config->sda_io, i2c_config->hdrive);
|
||||
IIC_SDA_H(i2c_config->sda_io);
|
||||
IIC_SCL_H(i2c_config->scl_io);
|
||||
gpio_set_pull_down(i2c_config->scl_io, 0);
|
||||
gpio_set_pull_down(i2c_config->sda_io, 0);
|
||||
gpio_set_die(i2c_config->scl_io, 1);//en 1.1v
|
||||
gpio_set_die(i2c_config->sda_io, 1);//en 1.1v
|
||||
/* gpio_set_dieh(i2c_config->scl_io, 1);//en 3.3v */
|
||||
/* gpio_set_dieh(i2c_config->sda_io, 1);//en 3.3v */
|
||||
return IIC_OK;//ok
|
||||
}
|
||||
|
||||
enum iic_state_enum soft_iic_deinit(soft_iic_dev iic)
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
if (soft_iic_state[iic] == 0) {
|
||||
printf("error: soft iic%d has been no init!\n", iic);
|
||||
return IIC_ERROR_NO_INIT;
|
||||
}
|
||||
soft_iic_state[iic] = 0;//no init
|
||||
|
||||
gpio_set_direction(soft_iic_cfg_cache[iic].scl_io, 1);
|
||||
gpio_set_direction(soft_iic_cfg_cache[iic].sda_io, 1);
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].scl_io, 0);
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
gpio_set_die(soft_iic_cfg_cache[iic].scl_io, 0);
|
||||
gpio_set_die(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
/* gpio_set_dieh(i2c_config->scl_io, 0);//en 3.3v */
|
||||
/* gpio_set_dieh(i2c_config->sda_io, 0);//en 3.3v */
|
||||
gpio_set_hd(soft_iic_cfg_cache[iic].scl_io, PORT_DRIVE_STRENGT_2p4mA);
|
||||
gpio_set_hd(soft_iic_cfg_cache[iic].sda_io, PORT_DRIVE_STRENGT_2p4mA);
|
||||
return IIC_OK;//ok
|
||||
}
|
||||
|
||||
enum iic_state_enum soft_iic_suspend(soft_iic_dev iic)
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
if ((soft_iic_state[iic] & 0xc0) != 0x80) {
|
||||
printf("error: soft iic%d is no init or suspend!\n", iic);
|
||||
return IIC_ERROR_SUSPEND_FAIL;
|
||||
}
|
||||
if ((soft_iic_state[iic] & 0x3f) != 0) {
|
||||
printf("error: soft iic%d is busy!\n", iic);
|
||||
return IIC_ERROR_BUSY;
|
||||
}
|
||||
soft_iic_state[iic] |= BIT(6);//suspend ok
|
||||
|
||||
gpio_set_direction(soft_iic_cfg_cache[iic].scl_io, 1);
|
||||
gpio_set_direction(soft_iic_cfg_cache[iic].sda_io, 1);
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].scl_io, 0);
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
gpio_set_die(soft_iic_cfg_cache[iic].scl_io, 0);
|
||||
gpio_set_die(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
/* gpio_set_dieh(i2c_config->scl_io, 0);//en 3.3v */
|
||||
/* gpio_set_dieh(i2c_config->sda_io, 0);//en 3.3v */
|
||||
gpio_set_hd(soft_iic_cfg_cache[iic].scl_io, PORT_DRIVE_STRENGT_2p4mA);
|
||||
gpio_set_hd(soft_iic_cfg_cache[iic].sda_io, PORT_DRIVE_STRENGT_2p4mA);
|
||||
return IIC_OK;//ok
|
||||
}
|
||||
|
||||
enum iic_state_enum soft_iic_resume(soft_iic_dev iic)
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
if ((soft_iic_state[iic] & 0xc0) != 0xc0) {
|
||||
printf("error: soft iic%d is no init or no suspend!\n", iic);
|
||||
return IIC_ERROR_RESUME_FAIL;
|
||||
}
|
||||
soft_iic_state[iic] &= ~ BIT(6); //resume ok
|
||||
|
||||
|
||||
if (soft_iic_cfg_cache[iic].io_mode) {//pull up
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].scl_io, 1);
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].sda_io, 1);
|
||||
} else {
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].scl_io, 0);
|
||||
gpio_set_pull_up(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
}
|
||||
gpio_set_hd(soft_iic_cfg_cache[iic].scl_io, soft_iic_cfg_cache[iic].hdrive);
|
||||
gpio_set_hd(soft_iic_cfg_cache[iic].sda_io, soft_iic_cfg_cache[iic].hdrive);
|
||||
IIC_SDA_H(soft_iic_cfg_cache[iic].sda_io);
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
gpio_set_pull_down(soft_iic_cfg_cache[iic].scl_io, 0);
|
||||
gpio_set_pull_down(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
gpio_set_die(soft_iic_cfg_cache[iic].scl_io, 1);
|
||||
gpio_set_die(soft_iic_cfg_cache[iic].sda_io, 1);
|
||||
/* gpio_set_dieh(i2c_config->scl_io, 1);//en 3.3v */
|
||||
/* gpio_set_dieh(i2c_config->sda_io, 1);//en 3.3v */
|
||||
return IIC_OK;//ok
|
||||
}
|
||||
|
||||
|
||||
|
||||
//return:0:error, 1:ok
|
||||
enum iic_state_enum soft_iic_check_busy(soft_iic_dev iic)
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
if (soft_iic_state[iic] & 0x0f) {
|
||||
return IIC_ERROR_BUSY;//error
|
||||
}
|
||||
soft_iic_state[iic]++;//busy
|
||||
return IIC_OK;//ok
|
||||
}
|
||||
void soft_iic_idle(soft_iic_dev iic)
|
||||
{
|
||||
soft_iic_state[iic] &= 0xf0;//idle
|
||||
}
|
||||
|
||||
enum iic_state_enum soft_iic_start(soft_iic_dev iic)
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
/* printf("soft_iic_init hsb clock:%d, delay cnt:%d\n",clk_get("sys"),dly_t); */
|
||||
|
||||
IIC_SDA_H(soft_iic_cfg_cache[iic].sda_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t * 2);
|
||||
|
||||
IIC_SDA_L(soft_iic_cfg_cache[iic].sda_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
return IIC_OK;//ok
|
||||
}
|
||||
|
||||
void soft_iic_stop(soft_iic_dev iic)
|
||||
{
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
IIC_SDA_L(soft_iic_cfg_cache[iic].sda_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t * 2);
|
||||
|
||||
IIC_SDA_H(soft_iic_cfg_cache[iic].sda_io);
|
||||
soft_iic_delay(dly_t);
|
||||
soft_iic_idle(iic);
|
||||
}
|
||||
|
||||
void soft_iic_reset(soft_iic_dev iic)//同iic_v2
|
||||
{
|
||||
ASSERT(iic < MAX_SOFT_IIC_NUM, "iic > MAX_SOFT_IIC_NUM");
|
||||
soft_iic_start(iic);
|
||||
soft_iic_stop(iic);
|
||||
soft_iic_idle(iic);
|
||||
}
|
||||
|
||||
static u8 soft_iic_check_ack(soft_iic_dev iic)
|
||||
{
|
||||
u8 ack;
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
|
||||
IIC_SDA_DIR(soft_iic_cfg_cache[iic].sda_io, 1);
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
if (IIC_SDA_READ(soft_iic_cfg_cache[iic].sda_io) == 0) {
|
||||
ack = 1;
|
||||
} else {
|
||||
ack = 0;
|
||||
}
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
IIC_SDA_DIR(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
IIC_SDA_L(soft_iic_cfg_cache[iic].sda_io);
|
||||
|
||||
return ack;//1:有应答, 0:无
|
||||
}
|
||||
|
||||
static void soft_iic_rx_ack(soft_iic_dev iic)
|
||||
{
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
IIC_SDA_L(soft_iic_cfg_cache[iic].sda_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t * 2);
|
||||
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
}
|
||||
|
||||
static void soft_iic_rx_nack(soft_iic_dev iic)
|
||||
{
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
IIC_SDA_H(soft_iic_cfg_cache[iic].sda_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t * 2);
|
||||
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
}
|
||||
|
||||
u8 soft_iic_tx_byte(soft_iic_dev iic, u8 byte)
|
||||
{
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
|
||||
local_irq_disable();
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
for (u32 i = 0; i < 8; i++) { //MSB FIRST
|
||||
if ((byte << i) & 0x80) {
|
||||
IIC_SDA_H(soft_iic_cfg_cache[iic].sda_io);
|
||||
} else {
|
||||
IIC_SDA_L(soft_iic_cfg_cache[iic].sda_io);
|
||||
}
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t * 2);
|
||||
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
}
|
||||
u8 ack = soft_iic_check_ack(iic);//1:有应答, 0:无
|
||||
local_irq_enable();
|
||||
return ack;
|
||||
}
|
||||
|
||||
u8 soft_iic_rx_byte(soft_iic_dev iic, u8 ack, s8 *err)
|
||||
{
|
||||
u32 delay_cnt;
|
||||
u32 dly_t = iic_get_delay(iic);
|
||||
u8 byte = 0;
|
||||
|
||||
local_irq_disable();
|
||||
IIC_SDA_DIR(soft_iic_cfg_cache[iic].sda_io, 1);
|
||||
|
||||
for (u32 i = 0; i < 8; i++) {
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_H(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
byte = byte << 1;
|
||||
if (IIC_SDA_READ(soft_iic_cfg_cache[iic].sda_io)) {
|
||||
byte |= 1;
|
||||
}
|
||||
soft_iic_delay(dly_t);
|
||||
|
||||
IIC_SCL_L(soft_iic_cfg_cache[iic].scl_io);
|
||||
soft_iic_delay(dly_t);
|
||||
}
|
||||
|
||||
IIC_SDA_DIR(soft_iic_cfg_cache[iic].sda_io, 0);
|
||||
if (ack) {
|
||||
soft_iic_rx_ack(iic);
|
||||
} else {
|
||||
soft_iic_rx_nack(iic);
|
||||
}
|
||||
|
||||
local_irq_enable();
|
||||
if (err) {
|
||||
*err = IIC_OK;
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
//return: =len:ok
|
||||
int soft_iic_read_buf(soft_iic_dev iic, void *buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!buf || !len) {
|
||||
return IIC_ERROR_PARAM_ERROR;
|
||||
}
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
((u8 *)buf)[i] = soft_iic_rx_byte(iic, 1, NULL);
|
||||
}
|
||||
((u8 *)buf)[len - 1] = soft_iic_rx_byte(iic, 0, NULL);
|
||||
return len;
|
||||
}
|
||||
|
||||
//return: =len:ok
|
||||
int soft_iic_write_buf(soft_iic_dev iic, const void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
u8 ack;
|
||||
|
||||
if (!buf || !len) {
|
||||
return IIC_ERROR_PARAM_ERROR;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
ack = soft_iic_tx_byte(iic, ((u8 *)buf)[i]);
|
||||
if (ack == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "includes.h"
|
||||
#include "ipc_spin_lock.h"
|
||||
|
||||
void ipc_spin_lock_init()
|
||||
{
|
||||
for (u8 i = 0; i < 16; i++) {
|
||||
P11_RESLOCK->LOCK[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
volatile u16 ipc_debug_bit;
|
||||
|
||||
|
||||
AT(.ipc_spin_lock.text.cache.L1)
|
||||
__attribute__((noinline))
|
||||
void ipc_spin_lock(enum ipc_spin_lock_event event)//0~15
|
||||
{
|
||||
ASSERT(event <= 15);
|
||||
|
||||
if (cpu_in_irq()) {
|
||||
ipc_debug_bit |= BIT(event);
|
||||
} else {
|
||||
if (ipc_debug_bit & BIT(event)) {
|
||||
ASSERT(cpu_irq_disable(), "%x\n", event);
|
||||
}
|
||||
}
|
||||
|
||||
while (P11_RESLOCK->LOCK[event]);
|
||||
}
|
||||
AT(.ipc_spin_lock.text.cache.L1)
|
||||
__attribute__((noinline))
|
||||
void ipc_spin_unlock(enum ipc_spin_lock_event event)//0~15
|
||||
{
|
||||
ASSERT(event <= 15);
|
||||
P11_RESLOCK->LOCK[event] = 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,185 @@
|
||||
// *INDENT-OFF*
|
||||
#include "p11_rom_stubs.ld"
|
||||
|
||||
#include "power/p11/p11_mmap.h"
|
||||
|
||||
/*
|
||||
p11 memory地址图
|
||||
|
||||
0xf28000, end
|
||||
0xf27fe0, poff ram, 0x20
|
||||
0xf27f00, m2p_message, 0xe0
|
||||
0xf27ec0, p2m_message, 0x40
|
||||
0xf2xxxx, stack, 0x600
|
||||
0xf2xxxx, bss
|
||||
0xf20080, code/data
|
||||
0xf20000, isr_vertor, 0x80
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
p11_message_ram(rw) : ORIGIN = P2M_MESSAGE_RAM_BEGIN, LENGTH = (P2M_MESSAGE_SIZE+M2P_MESSAGE_SIZE)
|
||||
msys_poweroff_ram(rw) : ORIGIN = MSYS_POFF_RAM_BEGIN, LENGTH = MSYS_POFF_RAM_SIZE
|
||||
p11_ram0(rw) : ORIGIN = P11_RAM0_BEGIN, LENGTH = P11_RAM0_SIZE
|
||||
|
||||
|
||||
}
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ORIGIN(p11_ram0);
|
||||
.text ALIGN(32):
|
||||
{
|
||||
*startup.o(.text)
|
||||
*(.text*)
|
||||
*(.*.text)
|
||||
*(.*.const)
|
||||
|
||||
*(.*.text)
|
||||
*(.ipc_spin_lock.text.cache.L1)
|
||||
|
||||
. = ALIGN(4);
|
||||
sensor_dev_begin = .;
|
||||
KEEP(*(.sensor_dev))
|
||||
sensor_dev_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.rodata*)
|
||||
|
||||
#include "power/ld/power_text.ld"
|
||||
|
||||
. = ALIGN(4);
|
||||
*(.*.data)
|
||||
. = ALIGN(4);
|
||||
*(.data*)
|
||||
. = ALIGN(4);
|
||||
} > p11_ram0
|
||||
|
||||
.data ALIGN(32):
|
||||
{
|
||||
/* *(.data*) */
|
||||
} > p11_ram0
|
||||
|
||||
.bss ALIGN(4):
|
||||
{
|
||||
*(.bss)
|
||||
*(.*.bss)
|
||||
*(COMMON)
|
||||
} > p11_ram0
|
||||
|
||||
.stack_bss ALIGN(32):
|
||||
{
|
||||
*(.stack_magic0)
|
||||
PROVIDE(_stack_begin = .);
|
||||
PROVIDE(_sstack_begin = .);
|
||||
*(.sstack)
|
||||
PROVIDE(_sstack_end = .);
|
||||
|
||||
PROVIDE(_ustack_begin = .);
|
||||
*(.ustack)
|
||||
PROVIDE(_ustack_end = .);
|
||||
|
||||
PROVIDE(_stack_end = .);
|
||||
*(.stack_magic1)
|
||||
} > p11_ram0
|
||||
|
||||
#if 0
|
||||
PROVIDE(overlay_demo_begin = .);
|
||||
OVERLAY : AT(0x200000) SUBALIGN(4)
|
||||
{
|
||||
.overlay_bank_demo_init
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.demo.code.bank.0)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
.overlay_bank_demo_normal0
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.demo.code.bank.1)
|
||||
}
|
||||
|
||||
.overlay_bank_demo_normal1
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.demo.code.bank.2)
|
||||
}
|
||||
} > p11_ram0
|
||||
PROVIDE(overlay_demo_end = .);
|
||||
|
||||
|
||||
PROVIDE(overlay_sensor_begin = .);
|
||||
OVERLAY : AT(0x210000) SUBALIGN(4)
|
||||
{
|
||||
/* TODO: */
|
||||
.overlay_bank_sensor_init
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.sensor.code.bank.0)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
.overlay_bank_sensor_normal0
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.sensor.code.bank.1)
|
||||
}
|
||||
.overlay_bank_sensor_normal1
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.sensor.code.bank.2)
|
||||
}
|
||||
|
||||
} > p11_ram0
|
||||
PROVIDE(overlay_sensor_end = .);
|
||||
|
||||
PROVIDE(overlay_sys_begin = .);
|
||||
OVERLAY : AT(0x220000) SUBALIGN(4)
|
||||
{
|
||||
/* TODO: */
|
||||
.overlay_bank_sys_init
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.sys.code.bank.0)
|
||||
. = ALIGN(4);
|
||||
}
|
||||
.overlay_bank_sys_normal0
|
||||
{
|
||||
LONG(0xffffffff);
|
||||
*(.sys.code.bank.1)
|
||||
}
|
||||
} > p11_ram0
|
||||
PROVIDE(overlay_sys_end = .);
|
||||
#endif
|
||||
|
||||
PROVIDE(p11_heap_begin = .);
|
||||
p11_heap_end = P2M_MESSAGE_RAM_BEGIN;
|
||||
|
||||
. = ORIGIN(p11_message_ram);
|
||||
.p11_message ALIGN(32):
|
||||
{
|
||||
*(.p2m_data)
|
||||
*(.m2p_data)
|
||||
} > p11_message_ram
|
||||
|
||||
. = ORIGIN(msys_poweroff_ram);
|
||||
.p11_poweroff ALIGN(32):
|
||||
{
|
||||
*(.msys_poff_data)
|
||||
} > msys_poweroff_ram
|
||||
}
|
||||
|
||||
text_begin = ADDR(.text);
|
||||
text_size = SIZEOF(.text);
|
||||
text_end = text_begin + text_size;
|
||||
|
||||
bss_begin = ADDR(.bss);
|
||||
bss_size = SIZEOF(.bss);
|
||||
|
||||
p11_message_begin = ADDR(.p11_message);
|
||||
p11_message_size = SIZEOF(.p11_message);
|
||||
|
||||
data_addr = ADDR(.data);
|
||||
data_begin = text_begin + text_size;
|
||||
data_size = SIZEOF(.data);
|
||||
@@ -0,0 +1,6 @@
|
||||
idle = ABSOLUTE(0x8000);
|
||||
standby = ABSOLUTE(0x8008);
|
||||
standby_ext = ABSOLUTE(0x8012);
|
||||
sleep_ext = ABSOLUTE(0x8030);
|
||||
sleep = ABSOLUTE(0x804e);
|
||||
deep_sleep = ABSOLUTE(0x8058);
|
||||
Binary file not shown.
@@ -0,0 +1,103 @@
|
||||
rem @echo off
|
||||
|
||||
@echo *****************************************************************
|
||||
@echo SDK BR35 P11
|
||||
@echo *****************************************************************
|
||||
@echo %date%
|
||||
|
||||
cd %~dp0
|
||||
|
||||
set OBJDUMP=C:\JL\pi32\bin\llvm-objdump.exe
|
||||
set OBJSIZEDUMP=C:\JL\pi32\bin\llvm-objsizedump.exe
|
||||
set OBJCOPY=C:\JL\pi32\bin\llvm-objcopy.exe
|
||||
set BANKLINK=.\BankLink.exe
|
||||
set ELFFILE=p11.elf
|
||||
|
||||
REM %OBJDUMP% -D -address-mask=0x1ffffff -print-imm-hex -print-dbg %ELFFILE% > p11.lst
|
||||
|
||||
%OBJCOPY% -O binary -j .text %ELFFILE% text.bin
|
||||
%OBJCOPY% -O binary -j .overlay_bank_demo_init %ELFFILE% bank_demo_init.bin
|
||||
%OBJCOPY% -O binary -j .overlay_bank_demo_normal0 %ELFFILE% bank_demo_normal0.bin
|
||||
%OBJCOPY% -O binary -j .overlay_bank_demo_normal1 %ELFFILE% bank_demo_normal1.bin
|
||||
%OBJCOPY% -O binary -j .overlay_bank_demo_normal2 %ELFFILE% bank_demo_normal2.bin
|
||||
|
||||
%OBJCOPY% -O binary -j .overlay_bank_sensor_init %ELFFILE% bank_sensor_init.bin
|
||||
%OBJCOPY% -O binary -j .overlay_bank_sensor_normal0 %ELFFILE% bank_sensor_normal0.bin
|
||||
%OBJCOPY% -O binary -j .overlay_bank_sensor_normal1 %ELFFILE% bank_sensor_normal1.bin
|
||||
|
||||
|
||||
|
||||
%OBJDUMP% -section-headers -address-mask=0x1ffffff %ELFFILE%
|
||||
%OBJDUMP% -t %ELFFILE% > symbol_tbl.txt
|
||||
|
||||
%OBJSIZEDUMP% -dump-stack-size -enable-dbg-info %ELFFILE% > dump_stack_size.txt
|
||||
%OBJSIZEDUMP% -dump-function-call -enable-dbg-info %ELFFILE% > dump_func_call.txt
|
||||
|
||||
set LZ4_PACKET=.\lz4_packet.exe
|
||||
|
||||
set bank_files=0x80 text.bin
|
||||
|
||||
%LZ4_PACKET% -input text.bin 0 -o text.lz4
|
||||
set bank_lz4_files=0x80 text.lz4
|
||||
|
||||
for %%a in (bank_demo_init.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_demo_init.bin
|
||||
%LZ4_PACKET% -input bank_demo_init.bin 0 -o bank_demo_init.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_demo_init.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_demo_normal0.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_demo_normal0.bin
|
||||
%LZ4_PACKET% -input bank_demo_normal0.bin 0 -o bank_demo_normal0.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_demo_normal0.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_demo_normal1.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_demo_normal1.bin
|
||||
%LZ4_PACKET% -input bank_demo_normal1.bin 0 -o bank_demo_normal1.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_demo_normal1.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_sensor_init.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_sensor_init.bin
|
||||
%LZ4_PACKET% -input bank_sensor_init.bin 0 -o bank_sensor_init.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_sensor_init.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_sensor_normal0.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_sensor_normal0.bin
|
||||
%LZ4_PACKET% -input bank_sensor_normal0.bin 0 -o bank_sensor_normal0.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_sensor_normal0.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_sensor_normal1.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_sensor_normal1.bin
|
||||
%LZ4_PACKET% -input bank_sensor_normal1.bin 0 -o bank_sensor_normal1.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_sensor_normal1.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_sys_init.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_sys_init.bin
|
||||
%LZ4_PACKET% -input bank_sys_init.bin 0 -o bank_sys_init.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_sys_init.lz4
|
||||
)
|
||||
|
||||
for %%a in (bank_sys_normal0.bin) do if %%~za gtr 0 (
|
||||
set bank_files=%bank_files% 0xAA55AA55 bank_sys_normal0.bin
|
||||
%LZ4_PACKET% -input bank_sys_normal0.bin 0 -o bank_sys_normal0.lz4
|
||||
set bank_lz4_files=%bank_lz4_files% 0xAA55AA55 bank_sys_normal0.lz4
|
||||
)
|
||||
|
||||
echo %bank_files%
|
||||
echo %bank_lz4_files%
|
||||
|
||||
%BANKLINK% %bank_files% p11_bank_code.bin
|
||||
%BANKLINK% %bank_lz4_files% p11_bank_code.lz4
|
||||
|
||||
if exist "..\..\..\..\..\..\sdk\cpu\br35\tools\" (
|
||||
copy .\p11_bank_code.bin ..\..\..\..\..\..\sdk\cpu\br35\tools\p11_code.bin
|
||||
copy .\p11_bank_code.lz4 ..\..\..\..\..\..\sdk\cpu\br35\tools\p11_code.lz4
|
||||
)
|
||||
|
||||
::pause
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
##!/bin/sh
|
||||
${OBJDUMP} -D -address-mask=0x1ffffff -print-imm-hex -print-dbg $1.elf > $1.lst
|
||||
|
||||
${OBJCOPY} -O binary -j .text $1.elf text.bin
|
||||
##${OBJCOPY} -O binary -j .p11_poweroff_code $1.elf p11_poweroff_code.bin
|
||||
${OBJCOPY} -O binary -j .overlay_bank_demo_init $1.elf bank_demo_init.bin
|
||||
${OBJCOPY} -O binary -j .overlay_bank_demo_normal0 $1.elf bank_demo_normal0.bin
|
||||
${OBJCOPY} -O binary -j .overlay_bank_demo_normal1 $1.elf bank_demo_normal1.bin
|
||||
${OBJCOPY} -O binary -j .overlay_bank_demo_normal2 $1.elf bank_demo_normal2.bin
|
||||
|
||||
${OBJCOPY} -O binary -j .overlay_bank_sensor_init $1.elf bank_sensor_init.bin
|
||||
${OBJCOPY} -O binary -j .overlay_bank_sensor_normal0 $1.elf bank_sensor_normal0.bin
|
||||
${OBJCOPY} -O binary -j .overlay_bank_sensor_normal1 $1.elf bank_sensor_normal1.bin
|
||||
|
||||
|
||||
|
||||
${OBJDUMP} -section-headers -address-mask=0x1ffffff $1.elf > segment_list.txt
|
||||
|
||||
${OBJSIZEDUMP} -lite -skip-zero -enable-dbg-info $1.elf | sort -k 1 > symbol_tbl.txt
|
||||
|
||||
${OBJSIZEDUMP} -dump-stack-size -enable-dbg-info $1.elf > dump_stack_size.txt
|
||||
${OBJSIZEDUMP} -dump-function-call -enable-dbg-info $1.elf > dump_func_call.txt
|
||||
/opt/utils/calc_min_stack_size.py --stack dump_stack_size.txt --call dump_func_call.txt > analyze.txt
|
||||
|
||||
compress_tool=lz4_packet
|
||||
|
||||
#bank_files="0x80 p11_poweroff_code.bin "
|
||||
bank_files=${bank_files}"0x80 text.bin "
|
||||
|
||||
$compress_tool -input text.bin 0 -o text.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0x80 text.lz4 "
|
||||
|
||||
if [ -s bank_demo_init.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_demo_init.bin "
|
||||
$compress_tool -input bank_demo_init.bin 0 -o bank_demo_init.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_demo_init.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_demo_normal0.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_demo_normal0.bin "
|
||||
$compress_tool -input bank_demo_normal0.bin 0 -o bank_demo_normal0.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_demo_normal0.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_demo_normal1.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_demo_normal1.bin "
|
||||
$compress_tool -input bank_demo_normal1.bin 0 -o bank_demo_normal1.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_demo_normal1.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_sensor_init.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_sensor_init.bin "
|
||||
$compress_tool -input bank_sensor_init.bin 0 -o bank_sensor_init.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_sensor_init.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_sensor_normal0.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_sensor_normal0.bin "
|
||||
$compress_tool -input bank_sensor_normal0.bin 0 -o bank_sensor_normal0.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_sensor_normal0.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_sensor_normal1.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_sensor_normal1.bin "
|
||||
$compress_tool -input bank_sensor_normal1.bin 0 -o bank_sensor_normal1.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_sensor_normal1.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_sys_init.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_sys_init.bin "
|
||||
$compress_tool -input bank_sys_init.bin 0 -o bank_sys_init.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_sys_init.lz4 "
|
||||
fi
|
||||
|
||||
if [ -s bank_sys_normal0.bin ]
|
||||
then
|
||||
bank_files=${bank_files}"0xAA55AA55 bank_sys_normal0.bin "
|
||||
$compress_tool -input bank_sys_normal0.bin 0 -o bank_sys_normal0.lz4
|
||||
bank_lz4_files=${bank_lz4_files}"0xAA55AA55 bank_sys_normal0.lz4 "
|
||||
fi
|
||||
|
||||
echo ${bank_files}
|
||||
echo ${bank_lz4_files}
|
||||
|
||||
BankLink ${bank_files} p11_bank_code.bin
|
||||
BankLink ${bank_lz4_files} p11_bank_code.lz4
|
||||
|
||||
cat p11_bank_code.bin > ${NICKNAME}_code.bin
|
||||
cat p11_bank_code.lz4 > ${NICKNAME}_code.lz4
|
||||
|
||||
# cp ${NICKNAME}_code.bin /home/chenrixin/work_space/code_refacter/wsdk/watch_sdk/cpu/br35/tools/p11_code.bin
|
||||
|
||||
cat segment_list.txt
|
||||
/opt/utils/report_segment_usage --sdk_path ${ROOT} \
|
||||
--tbl_file symbol_tbl.txt \
|
||||
--seg_file segment_list.txt \
|
||||
--map_file p11.map \
|
||||
--module_depth "{\"app\":1,\"lib\":2,\"[lib]\":2}"
|
||||
|
||||
host-client -project ${NICKNAME}$2 -f ${NICKNAME}_code.bin ${NICKNAME}_code.lz4
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,68 @@
|
||||
#include "power_interface.h"
|
||||
#include "io_imap.h"
|
||||
#include "main.h"
|
||||
/* ------------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief io_map_to_gpio imap 转成标准io口
|
||||
*
|
||||
* @param imap
|
||||
*
|
||||
* @return -1 imap非法
|
||||
* other io口
|
||||
*/
|
||||
/* ------------------------------------------------------------------------------------*/
|
||||
static int io_map_to_gpio(u32 imap)
|
||||
{
|
||||
#define GROUP 16
|
||||
if (imap >= PA0_IN && imap < PB0_IN) {
|
||||
return imap + (0 * GROUP - PA0_IN);
|
||||
} else if (imap >= PB0_IN && imap < PC0_IN) {//IO_PORTB_XX
|
||||
return imap + (1 * GROUP - PB0_IN);
|
||||
} else if (imap >= PC0_IN && imap < USBDP_IN) {
|
||||
return imap + (2 * GROUP - PC0_IN);
|
||||
} else if (imap == USBDP_IN) {
|
||||
return 14 * GROUP;
|
||||
} else if (imap == USBDM_IN) {
|
||||
return 14 * GROUP + 1;
|
||||
} else if (imap == PP0_IN) {
|
||||
return 13 * GROUP;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief io_wkup_callback io唤醒回调(中断)
|
||||
*
|
||||
* @param imap
|
||||
* @param edge
|
||||
*
|
||||
* @return 0 唤醒主系统处理
|
||||
* 1 P11处理,不唤醒主系统
|
||||
*/
|
||||
/* ------------------------------------------------------------------------------------*/
|
||||
static u32 io_wkup_callback(u32 imap, P33_IO_WKUP_EDGE edge)
|
||||
{
|
||||
/* printf("imap: %d, %d\n", imap, edge); */
|
||||
#if CONFIG_SENSOR_SLEEP_ENABLE
|
||||
if (imap == PB3_IN) {
|
||||
task_post_msg(NULL, 1, MSG_P11_SENSOR_IRQ);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void power_early_flowing()
|
||||
{
|
||||
power_early_init(0);
|
||||
|
||||
p33_io_wakeup_set_callback(io_wkup_callback);
|
||||
}
|
||||
|
||||
int power_later_flowing()
|
||||
{
|
||||
power_later_init(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "power_interface.h"
|
||||
|
||||
void board_power_init()
|
||||
{
|
||||
message_init();
|
||||
|
||||
power_init(NULL);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "includes.h"
|
||||
#include "gpio.h"
|
||||
#include "ipc_spin_lock.h"
|
||||
|
||||
void app_main();
|
||||
|
||||
int main(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
ipc_spin_lock_init();
|
||||
|
||||
clock_early_init();
|
||||
|
||||
power_early_flowing(0);
|
||||
|
||||
#if CONFIG_UART_DEBUG_ENABLE
|
||||
debug_uart_init(CONFIG_DEBUG_UART_TX_PIN);
|
||||
#endif /* #if CONFIG_UART_DEBUG_ENABLE */
|
||||
|
||||
printf("\n============ Hello BR35 P11 ============\n");
|
||||
|
||||
//p11_q32s(0)->PMU_CON0 |= BIT(2); //P11 WKUP EN
|
||||
printf("p11_q32s(0)->PMU_CON0 = 0x%x\n", p11_q32s(0)->PMU_CON0);
|
||||
|
||||
debug_init(); //异常检测初始化
|
||||
|
||||
board_power_init();
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
while (M2P_WAIT_RELEASE == 0) {
|
||||
asm("csync");
|
||||
}
|
||||
M2P_WAIT_RELEASE = 0;
|
||||
|
||||
app_main();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".uart.bss")
|
||||
#pragma data_seg(".uart.data")
|
||||
#pragma const_seg(".uart.const")
|
||||
#pragma code_seg(".uart.text")
|
||||
#pragma str_literal_override(".uart.text")
|
||||
#endif /* #ifdef SUPPORT_MS_EXTENSIONS */
|
||||
|
||||
#include "includes.h"
|
||||
#include "uart.h"
|
||||
#include "gpio.h"
|
||||
#include "ipc_spin_lock.h"
|
||||
|
||||
//uart时钟选择:
|
||||
//#define UART_CLK_SEL UART_CLK_SYS_CLK //由主系统gpcnt模块算出rc16m频率,rc16m频率跟pvdd有关,注意配置被覆盖。
|
||||
#define UART_CLK_SEL UART_CLK_STD_12M //低功耗不能使用该时钟源
|
||||
|
||||
//uart波特率选择:
|
||||
#define UART_TARGET_BAUD CONFIG_DEBUG_UART_BAUD
|
||||
//#define UART_TARGET_BAUD 1000000L
|
||||
|
||||
//调试串口选择: P11_UART0/P11_UART1
|
||||
#define DEBUG_UART_SELECT P11_UART0
|
||||
|
||||
//输入选择. 只有UART0有输入功能
|
||||
#define DEBUG_UART_RX_ENABLE 0
|
||||
#if DEBUG_UART_RX_ENABLE
|
||||
#define DEBUG_UART_RX_IO IO_PORTB_05
|
||||
#define DEBUG_UART_RX_OVERTIME 100 //ms
|
||||
#endif /* #if DEBUG_UART_RX_ENABLE */
|
||||
|
||||
static u8 init = 0;
|
||||
|
||||
#define P11_UART_CLK_SEL(x) SFR(P11_CLOCK->CLK_CON2, 2, 2, x)
|
||||
|
||||
|
||||
#define UART_ENTER_CRITICAL() irq_disable_core();//ipc_spin_lock(IPC_SPIN_LOCK_EVENT_UART)
|
||||
#define UART_EXIT_CRITICAL() irq_enable_core(); //ipc_spin_unlock(IPC_SPIN_LOCK_EVENT_UART)
|
||||
|
||||
|
||||
|
||||
|
||||
___interrupt
|
||||
static void uart0_isr(void)
|
||||
{
|
||||
u8 rx = 0;
|
||||
|
||||
if (UART_RX_PENDING_IS(P11_UART0)) {
|
||||
rx = UART_BUF_READ(P11_UART0);
|
||||
UART_RX_PENDING_CLEAR(P11_UART0);
|
||||
printf("RX pending, rx: 0x%x\n", rx);
|
||||
}
|
||||
|
||||
if (UART_OT_PENDING_IS(P11_UART0)) {
|
||||
rx = UART_BUF_READ(P11_UART0);
|
||||
UART_OT_PENDING_CLEAR(P11_UART0);
|
||||
printf("OT pending, rx: 0x%x\n", rx);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 uart_src_clk_get(void)
|
||||
{
|
||||
u32 freq = 0;
|
||||
|
||||
if (UART_CLK_SEL == UART_CLK_STD_12M) {
|
||||
SFR(P11_CLOCK->CLK_CON1, 15, 2, 1); //MSYS_BT24M --> P11_BT24M
|
||||
SFR(P11_CLOCK->CLK_CON1, 17, 3, 1); //STD12M sel P11_BT24M input
|
||||
SFR(P11_CLOCK->CLK_CON1, 20, 2, 0); // div0
|
||||
SFR(P11_CLOCK->CLK_CON1, 22, 2, 1); // div1
|
||||
freq = 12000000;
|
||||
} else if (UART_CLK_SEL == UART_CLK_RC16M) {
|
||||
freq = 16000000;//(u32)((u32)m2p_message[M2P_RCH_FEQ_H] << 8 | m2p_message[M2P_RCH_FEQ_L]) * 1000;
|
||||
} else if (UART_CLK_SEL == UART_CLK_SYS_CLK) {
|
||||
freq = 24000000;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
void uart_clk_sel(enum UART_CLK_TABLE clk)
|
||||
{
|
||||
u32 freq = 0;
|
||||
|
||||
if (clk == UART_CLK_STD_12M) {
|
||||
freq = 12000000;
|
||||
} else if (clk == UART_CLK_RC16M) {
|
||||
freq = 16000000;
|
||||
} else if (clk == UART_CLK_SYS_CLK) {
|
||||
freq = 24000000;
|
||||
}
|
||||
|
||||
P11_UART_CLK_SEL(clk);
|
||||
|
||||
u16 baud_reg = (freq / UART_TARGET_BAUD) / 4 - 1;
|
||||
|
||||
UART_BAUD_SET(DEBUG_UART_SELECT, baud_reg);
|
||||
}
|
||||
|
||||
void debug_uart_init(u8 tx_port)
|
||||
{
|
||||
UART_CON0_CLEAR(DEBUG_UART_SELECT);
|
||||
UART_CON1_CLEAR(DEBUG_UART_SELECT);
|
||||
|
||||
uart_clk_sel(UART_CLK_SEL);
|
||||
|
||||
//tx io inita
|
||||
gpio_set_output_value(tx_port, 1);
|
||||
gpio_set_direction(tx_port, 0);
|
||||
|
||||
if (DEBUG_UART_SELECT == P11_UART1) {
|
||||
//gpio_set_fun_output_port(tx_port, P11_FO_UART1_TX, 1, 1);
|
||||
} else if (DEBUG_UART_SELECT == P11_UART0) {
|
||||
gpio_set_fun_output_port(tx_port, P11_FO_UART0_TX, 1, 1);
|
||||
}
|
||||
|
||||
#if DEBUG_UART_RX_ENABLE
|
||||
u32 ot_value = 0;
|
||||
if (DEBUG_UART_SELECT == P11_UART0) {
|
||||
//rx io init:
|
||||
gpio_set_direction(DEBUG_UART_RX_IO, 1);
|
||||
gpio_set_pull_up(DEBUG_UART_RX_IO, 1);
|
||||
gpio_set_pull_down(DEBUG_UART_RX_IO, 0);
|
||||
gpio_set_die(DEBUG_UART_RX_IO, 1);
|
||||
//iomc:
|
||||
gpio_set_fun_input_port(DEBUG_UART_RX_IO, PFI_UART0_RX);
|
||||
|
||||
//rx config:
|
||||
UART_OT_PENDING_CLEAR(P11_UART0);
|
||||
UART_RX_PENDING_CLEAR(P11_UART0);
|
||||
ot_value = (uart_src_clk_get() * DEBUG_UART_RX_OVERTIME) / 1000;
|
||||
UART_OTCNT_SET(P11_UART0, ot_value);
|
||||
UART_OT_INT_ENABLE(P11_UART0);
|
||||
UART_RX_INT_ENABLE(P11_UART0);
|
||||
UART_RX_ENABLE(P11_UART0);
|
||||
P11_CLOCK->WKUP_EN |= BIT(IRQ_UART0_IDX);
|
||||
request_irq(IRQ_UART0_IDX, uart0_isr, 0);
|
||||
}
|
||||
#endif /* #if DEBUG_UART_RX_ENABLE */
|
||||
|
||||
UART_TX_ENABLE(DEBUG_UART_SELECT);
|
||||
|
||||
init = 1;
|
||||
}
|
||||
void uart_putbyte(char a)
|
||||
{
|
||||
u32 ot = 400;
|
||||
while (!UART_TX_PENDING_IS(DEBUG_UART_SELECT)) {
|
||||
if (ot-- == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
UART_TX_PENDING_CLEAR(DEBUG_UART_SELECT);
|
||||
UART_BUF_WRITE(DEBUG_UART_SELECT, a);
|
||||
}
|
||||
__WEAK__
|
||||
void putchar(char a)
|
||||
{
|
||||
if (init == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (a == '\r') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (a == '\n') {
|
||||
uart_putbyte('\r');
|
||||
}
|
||||
uart_putbyte(a);
|
||||
}
|
||||
|
||||
__WEAK__
|
||||
void putbyte(char a)
|
||||
{
|
||||
putchar(a);
|
||||
}
|
||||
|
||||
#include "power_interface.h"
|
||||
|
||||
static P11_UART_TypeDef UART0_POWEROFF;
|
||||
|
||||
static u8 uart_enter_deepsleep(void)
|
||||
{
|
||||
UART0_POWEROFF.CON0 = DEBUG_UART_SELECT->CON0;
|
||||
UART0_POWEROFF.CON1 = DEBUG_UART_SELECT->CON1;
|
||||
UART0_POWEROFF.CON2 = DEBUG_UART_SELECT->CON2;
|
||||
UART0_POWEROFF.BAUD = DEBUG_UART_SELECT->BAUD;
|
||||
UART0_POWEROFF.OTCNT = DEBUG_UART_SELECT->OTCNT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 uart_exit_deepsleep(void)
|
||||
{
|
||||
DEBUG_UART_SELECT->CON1 = UART0_POWEROFF.CON1;
|
||||
DEBUG_UART_SELECT->BAUD = UART0_POWEROFF.BAUD;
|
||||
DEBUG_UART_SELECT->OTCNT = UART0_POWEROFF.OTCNT;
|
||||
DEBUG_UART_SELECT->CON2 = UART0_POWEROFF.CON2;
|
||||
|
||||
DEBUG_UART_SELECT->CON0 = UART0_POWEROFF.CON0;
|
||||
DEBUG_UART_SELECT->CON0 |= (BIT(13) | BIT(12) | BIT(10));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_UART_DEBUG_ENABLE
|
||||
DEEPSLEEP_TARGET_REGISTER(uart) = {
|
||||
.name = "uart",
|
||||
.enter = uart_enter_deepsleep,
|
||||
.exit = uart_exit_deepsleep,
|
||||
};
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "includes.h"
|
||||
|
||||
#if (CONFIG_UART_DEBUG_ENABLE == 0)
|
||||
void putchar(char a)
|
||||
{
|
||||
}
|
||||
|
||||
void putbyte(char a)
|
||||
{
|
||||
}
|
||||
|
||||
int puts(const char *out)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void put_u32hex(unsigned int dat)
|
||||
{
|
||||
}
|
||||
|
||||
void put_buf(const u8 *buf, int len)
|
||||
{
|
||||
}
|
||||
|
||||
int printf(const char *format, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* #if (CONFIG_UART_DEBUG_ENABLE == 0) */
|
||||
@@ -0,0 +1,221 @@
|
||||
#include "includes.h"
|
||||
#include "uart.h"
|
||||
#include "debug.h"
|
||||
#include "gpio.h"
|
||||
#include "bank_switch.h"
|
||||
#include "usr_timer.h"
|
||||
#include "iic_api.h"
|
||||
#include "main.h"
|
||||
#include "bsp.h"
|
||||
#include "sensor/sensor_driver.h"
|
||||
|
||||
/*
|
||||
function: m2p消息处理,主循环不会收到ack消息
|
||||
param index:等待返回ack的消息序号
|
||||
return val:1, 收到对应ack消息 0,未收到对应ack消息
|
||||
*/
|
||||
int m2p_msg_hdl(u32 index)
|
||||
{
|
||||
struct lp_msg_handler *p;
|
||||
u8 msg[32];
|
||||
struct lp_msg_head head;
|
||||
|
||||
int ret = m2p_get_msg(&head, (u8 *)msg, ARRAY_SIZE(msg));
|
||||
|
||||
//成功读取到消息
|
||||
if (ret == MSG_NO_ERROR) {
|
||||
list_for_each_m2p_msg_handler(p) {
|
||||
if (p->type == head.type) {
|
||||
if (head.ack) {
|
||||
config_post_ack_flag(0);
|
||||
}
|
||||
p->handler(p->priv, (u8 *)msg, head.len);
|
||||
if (head.ack) {
|
||||
//若是应答消息则返回应答
|
||||
p11_ack_msys(head.index);
|
||||
config_post_ack_flag(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ret == MSG_NO_MSG) {
|
||||
//未读取到消息
|
||||
|
||||
} else {
|
||||
ASSERT(0, "ret: %d, type: %d, ack: %d, index: %d, len: %d\n", ret, head.type, head.ack, head.index, head.len);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void callback(u32 *priv)
|
||||
{
|
||||
printf("function: callback, %d\n", (u32)priv);
|
||||
}
|
||||
|
||||
|
||||
#include "circular_buf.h"
|
||||
#include "ipc_spin_lock.h"
|
||||
#define P11_CBUF_TEST 0
|
||||
|
||||
#if P11_CBUF_TEST
|
||||
|
||||
static cbuffer_t cbuffer;
|
||||
static u8 cbuf_test[256];
|
||||
static cbuffer_child_t entry[3];//支持3个成员读取
|
||||
|
||||
static void p11_cbuf_test_init()
|
||||
{
|
||||
int msg[2];
|
||||
msg[0] = MSG_P11_SYS_RAM_INIT;
|
||||
msg[1] = (int)&cbuffer;
|
||||
p2m_post_msg(MSG_APP, 0, (u8 *)msg, sizeof(msg));
|
||||
cbuf_mult_read_init(&cbuffer, cbuf_test, sizeof(cbuf_test), 3, entry);
|
||||
|
||||
|
||||
cbuf_mult_entry_enable(&cbuffer, 0, 1); //开启节点
|
||||
cbuf_mult_entry_enable(&cbuffer, 1, 1);
|
||||
cbuf_mult_entry_enable(&cbuffer, 2, 1);
|
||||
|
||||
printf("%s %d %x\n", __func__, __LINE__, (int)&cbuffer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void p11_cbuf_write_test()
|
||||
{
|
||||
u8 test[50];
|
||||
static int count_add = 0;
|
||||
int count = count_add;
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
test[i] = (count++) & 0xff;
|
||||
}
|
||||
|
||||
|
||||
int len = cbuf_write(&cbuffer, test, 50);
|
||||
/* int len = 0; */
|
||||
if (len == 50) {
|
||||
printf("\nwrite succ %x\n", count_add);
|
||||
count_add += 50;
|
||||
} else {
|
||||
/* printf("falil \n"); */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void app_main()
|
||||
{
|
||||
bsp_init();
|
||||
usr_timer_init();
|
||||
|
||||
lptmr1_init();
|
||||
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE
|
||||
sensor_driver_check();
|
||||
#endif
|
||||
|
||||
#if P11_CBUF_TEST
|
||||
p11_cbuf_test_init();
|
||||
p11_cbuf_write_test();
|
||||
#endif
|
||||
/* task_post_msg(NULL,1,MSG_P11_SYS_KICK); */
|
||||
while (1) {
|
||||
m2p_msg_hdl(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function: 主循环回调处理
|
||||
*/
|
||||
void app_handler_add(void (*callback)(u32 *priv), u32 *priv)
|
||||
{
|
||||
u8 msg[9];
|
||||
u32 msg_cb = (u32)callback;
|
||||
u32 msg_priv = (u32)priv;
|
||||
|
||||
msg[0] = MSG_APP_CALLBACK;
|
||||
memcpy(msg + 1, &msg_cb, 4);
|
||||
|
||||
if (priv != NULL) {
|
||||
memcpy(msg + 5, &msg_priv, 4);
|
||||
m2p_post_msg(MSG_APP, 0, msg, 9);
|
||||
} else {
|
||||
m2p_post_msg(MSG_APP, 0, msg, 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int task_post_msg(char *name, int argc, ...)
|
||||
{
|
||||
int msg[16];
|
||||
va_list argptr;
|
||||
va_start(argptr, argc);
|
||||
int param;
|
||||
ASSERT(argc < sizeof(msg) / sizeof(msg[0]))
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
param = va_arg(argptr, int);
|
||||
msg[i] = param;
|
||||
}
|
||||
m2p_post_msg(MSG_APP, 0, (u8 *)msg, argc * sizeof(int));
|
||||
va_end(argptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void app_msg_handler(void *priv, u8 *msg, u32 len)
|
||||
{
|
||||
|
||||
printf("app_msg_handler = %d\n", msg[0]);
|
||||
if (msg[0] == MSG_APP_CALLBACK) {
|
||||
u32 *msg_priv;
|
||||
void (*msg_cb)(u32 * priv);
|
||||
memcpy(&msg_cb, msg + 1, 4);
|
||||
memcpy(&msg_priv, msg + 5, 4);
|
||||
msg_cb(msg_priv);
|
||||
}
|
||||
|
||||
|
||||
switch (msg[0]) {
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE
|
||||
case MSG_P11_SYS_KICK:
|
||||
printf("MSG_P11_SYS_KICK\n");
|
||||
sensor_driver_run();
|
||||
break;
|
||||
case MSG_P11_SENSOR_SLEEP:
|
||||
printf("MSG_P11_SENSOR_SLEEP\n");
|
||||
sensor_driver_sleep(msg[1], msg[2]);
|
||||
break;
|
||||
|
||||
case MSG_P11_SENSOR_IRQ:
|
||||
printf("MSG_P11_SENSOR_IRQ\n");
|
||||
sensor_driver_irq_handle();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if P11_CBUF_TEST
|
||||
p11_cbuf_write_test();
|
||||
#endif
|
||||
//test
|
||||
break;
|
||||
case MSG_P11_SENSOR_INIT: {
|
||||
printf("m2p_post_msg len=%d\n", len);
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE
|
||||
sensor_driver_init(msg[1], msg[2], msg[3] << 8 | msg[4], msg[5]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_P11_SOFF_EVENT: {
|
||||
lptmr1_set_wkup_time(0, P11_LPTMR_WKUP_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
REGISTER_M2P_MSG_HANDLER(0, MSG_APP, app_msg_handler);
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
enum {
|
||||
MSG_APP_CALLBACK = 1,
|
||||
MSG_P11_SYS_RAM_INIT = 2,
|
||||
MSG_P11_SYS_KICK = 3,
|
||||
MSG_P11_SYS_TO_SELF = 4,
|
||||
MSG_P11_SENSOR_INFO = 5,
|
||||
MSG_P11_SENSOR_INIT = 6,
|
||||
MSG_P11_SENSOR_EVENT = 7,
|
||||
MSG_P11_SENSOR_TIMER = 8,
|
||||
MSG_P11_ALGORITHM_EVENT = 9,
|
||||
MSG_P11_SOFF_EVENT = 10,
|
||||
MSG_P11_SENSOR_SLEEP = 11,
|
||||
MSG_P11_SENSOR_IRQ = 12,
|
||||
MSG_P11_SYS_WAKE = 0xff,
|
||||
};
|
||||
|
||||
void app_handler_add(void (*callback)(u32 *priv), u32 *priv);
|
||||
|
||||
extern int task_post_msg(char *name, int argc, ...);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
#include "includes.h"
|
||||
|
||||
/*
|
||||
1.共享buf互斥操作,注意P11在等待主系统BUF锁时候需要响应主系统的操作,
|
||||
防止主系统等待导致死锁,处理来自主系统的M2P中断(通过硬件lock不需要这一点)
|
||||
|
||||
2.接口互斥,不能同时操作
|
||||
P11在等待主系统ack消息时,也要防止死锁(P11和主系统同时发送ACK消息时会死锁),
|
||||
有以下处理:
|
||||
|
||||
主系统
|
||||
1.主系统不能在关中断/中断中发送ACK类型的消息
|
||||
2.发送ACK类型的消息需要互斥,即不允许同时发多个ACK类型消息
|
||||
3.不允许在收到ACK类型消息处理函数中发送ACK类型消息的嵌套,收到ACK类型消息
|
||||
调用post_ack_flag=0,发送函数判断post_ack_flag=0且当前任务为pmu_task则断言
|
||||
|
||||
P11系统:
|
||||
1.P11系统不能在关中断/中断中发送ACK类型的消息
|
||||
2.不允许在收到ACK类型消息后,又发送ACK类型消息,由于不会在中断中发送ACK类型消息,
|
||||
在收到ACK类型的消息后调用post_ack_flag=0,发送函数内部检查post_ack_flag=0则断言
|
||||
3.不允许重复发送ACK类型的消息,由于一点的保证
|
||||
4.主系统和P11同时发ACK类型的消息,P11需要响应主系统
|
||||
*/
|
||||
|
||||
#define MSG_ENTER_CRITICAL() lp_lock()
|
||||
#define MSG_EXIT_CRITICAL() lp_unlock()
|
||||
|
||||
#define P11_WKUP_MSYS(msg) P11_SYSTEM->P2M_INT_SET = BIT(P2M_APP_INDEX)
|
||||
#define MSYS_WKUP_P11(msg) //P11_SYSTEM->M2P_INT_SET = BIT(M2P_APP_INDEX)
|
||||
|
||||
static LP_Q m2p_msg_q;
|
||||
static LP_Q p2m_msg_q;
|
||||
static u8 m2p_pool[MAX_POOL] ALIGNED(4);
|
||||
static u8 p2m_pool[MAX_POOL] ALIGNED(4);
|
||||
static bool post_ack_flag = 1;
|
||||
|
||||
|
||||
/*
|
||||
function: 从缓存buf读取指定长度数据
|
||||
param len: 读取数据长度
|
||||
*/
|
||||
static int lp_buf_read(LP_Q *q, u8 *buf, u32 len)
|
||||
{
|
||||
if (q->count == 0) {
|
||||
return LP_BUF_READ_NO_DATA;
|
||||
}
|
||||
|
||||
if (q->count < len) {
|
||||
return LP_BUF_READ_NOT_ENOUGH_DATA;
|
||||
}
|
||||
|
||||
u32 end = (q->out + len) % q->size;
|
||||
if (end > q->out) {
|
||||
memcpy(buf, (void *)(P11_RAM_BASE + q->start + q->out), len);
|
||||
} else {
|
||||
memcpy(buf, (void *)(P11_RAM_BASE + q->start + q->out), q->size - q->out);
|
||||
memcpy(buf + (q->size - q->out), (void *)(P11_RAM_BASE + q->start), end);
|
||||
}
|
||||
|
||||
q->out = end;
|
||||
q->count -= len;
|
||||
|
||||
return LP_BUF_NO_ERR;
|
||||
}
|
||||
|
||||
static int lp_buf_write_enable(LP_Q *q, u32 len)
|
||||
{
|
||||
if ((q->count + len) > q->size) {
|
||||
return LP_BUF_WRITE_OVER;
|
||||
} else {
|
||||
return LP_BUF_NO_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function: 从缓存buf写入指定长度数据
|
||||
return val: 0,写入成功
|
||||
param len: 写入的数据长度
|
||||
*/
|
||||
static int lp_buf_write(LP_Q *q, u8 *buf, u32 len)
|
||||
{
|
||||
u32 end = (q->in + len) % q->size;
|
||||
if (end > q->in) {
|
||||
memcpy((void *)(P11_RAM_BASE + q->start + q->in), buf, len);
|
||||
} else {
|
||||
memcpy((void *)(P11_RAM_BASE + q->start + q->in), buf, q->size - q->in);
|
||||
memcpy((void *)(P11_RAM_BASE + q->start), buf + (q->size - q->in), end);
|
||||
}
|
||||
|
||||
q->in = end;
|
||||
q->count += len;
|
||||
|
||||
return LP_BUF_NO_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* function:从消息池中获取主系统发送过来的消息
|
||||
* param head:消息的头部,包含消息类型、长度等信息
|
||||
* param len:读取消息内存的长度
|
||||
* param msg:读取到消息
|
||||
*
|
||||
* return val: MSG_NO_MSG
|
||||
* MSG_NO_ERROR
|
||||
* MSG_BUF_ERROR
|
||||
* MSG_BUF_READ_OVER
|
||||
*
|
||||
*/
|
||||
int m2p_get_msg(struct lp_msg_head *head, u8 *msg, u32 len)
|
||||
{
|
||||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF_ADDR0 | P2M_CBUF_ADDR1 << 8 | P2M_CBUF_ADDR2 << 16 | P2M_CBUF_ADDR3 << 24));
|
||||
|
||||
//长度至少是头+1byte数据
|
||||
if (len < sizeof(struct lp_msg_head) + 1) {
|
||||
return MSG_BUF_READ_OVER;
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
//先读取头部数据
|
||||
int ret = lp_buf_read(msg_q_p, (u8 *)head, sizeof(struct lp_msg_head));
|
||||
if (ret == LP_BUF_READ_NO_DATA) {
|
||||
//若没有数据则进入低功耗
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
//确保每次事件都能唤醒p11
|
||||
//get no msg,cpu enter lowpower
|
||||
p11_lowpower_schedule();
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
return MSG_NO_MSG;
|
||||
|
||||
} else if (ret == LP_BUF_READ_NOT_ENOUGH_DATA) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
local_irq_enable();
|
||||
//读取头部的数据长度不够返回错误
|
||||
return MSG_BUF_ERROR;
|
||||
|
||||
} else {
|
||||
|
||||
//判断长度够不够
|
||||
if (len < head->len) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
local_irq_enable();
|
||||
//读了头,数据读不了返回错误
|
||||
return MSG_BUF_READ_OVER;
|
||||
}
|
||||
|
||||
ret = lp_buf_read(msg_q_p, msg, head->len);
|
||||
if (ret != LP_BUF_NO_ERR) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
local_irq_enable();
|
||||
//数据长度为控不对返回格式错误
|
||||
return MSG_BUF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
local_irq_enable();
|
||||
|
||||
return MSG_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* function:主系统向P11发送消息,往消息池丢数据,该函数可实现向P11主循环推数据
|
||||
*
|
||||
* param type: 消息类型,P11收到消息后根据消息类型匹配回调函数
|
||||
* param ack:该函数不需要ack参数,也即发送的头index为0,预留给该函数使用
|
||||
* param len:发送消息的长度,单位为一个字节
|
||||
* param msg:发送的消息
|
||||
*
|
||||
*/
|
||||
int m2p_post_msg(u32 type, u32 ack, u8 *msg, u32 len)
|
||||
{
|
||||
struct lp_msg_head head;
|
||||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF_ADDR0 | P2M_CBUF_ADDR1 << 8 | P2M_CBUF_ADDR2 << 16 | P2M_CBUF_ADDR3 << 24));
|
||||
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
/*P11的m2p接口不需要ack与index*/
|
||||
head.type = type;
|
||||
head.ack = 0;
|
||||
head.len = len;
|
||||
head.index = 0;
|
||||
|
||||
if (lp_buf_write_enable(msg_q_p, len + sizeof(struct lp_msg_head)) == LP_BUF_WRITE_OVER) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
return MSG_BUF_WRITE_OVER;
|
||||
}
|
||||
|
||||
//写头
|
||||
lp_buf_write(msg_q_p, (u8 *)&head, sizeof(struct lp_msg_head));
|
||||
|
||||
//写数据
|
||||
lp_buf_write(msg_q_p, msg, len);
|
||||
|
||||
MSYS_WKUP_P11();
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
return MSG_NO_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* 接收到ack消息处理过程中调用
|
||||
*/
|
||||
void config_post_ack_flag(u32 enable)
|
||||
{
|
||||
local_irq_disable();
|
||||
if (enable) {
|
||||
post_ack_flag = 1;
|
||||
} else {
|
||||
post_ack_flag = 0;
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static u32 p2m_get_ack_flag(u32 index)
|
||||
{
|
||||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF1_ADDR0 | P2M_CBUF1_ADDR1 << 8 | P2M_CBUF1_ADDR2 << 16 | P2M_CBUF1_ADDR3 << 24));
|
||||
|
||||
MSG_ENTER_CRITICAL();
|
||||
u32 ret = msg_q_p->ack_flag & BIT(index);
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
u32 p11_ack_msys(u32 index)
|
||||
{
|
||||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF_ADDR0 | P2M_CBUF_ADDR1 << 8 | P2M_CBUF_ADDR2 << 16 | P2M_CBUF_ADDR3 << 24));
|
||||
MSG_ENTER_CRITICAL();
|
||||
msg_q_p->ack_flag &= ~BIT(index);
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* function:P11向主系统发送消息,往消息池丢数据
|
||||
*
|
||||
* param type: 消息类型,主系统收到消息后根据消息类型匹配回调函数
|
||||
* param ack:P11收到消息执行完成后是否发送应答消息给主系统,P11死等消息
|
||||
* 并处理主系统发送过来的所有消息
|
||||
* param len:发送消息的长度,单位为一个字节
|
||||
* param msg:发送的消息
|
||||
*
|
||||
*/
|
||||
int p2m_post_msg(u32 type, u32 ack, u8 *msg, u32 len)
|
||||
{
|
||||
u32 param;
|
||||
struct lp_msg_head head;
|
||||
LP_Q *msg_q_p = (LP_Q *)(P11_RAM_BASE + (P2M_CBUF1_ADDR0 | P2M_CBUF1_ADDR1 << 8 | P2M_CBUF1_ADDR2 << 16 | P2M_CBUF1_ADDR3 << 24));
|
||||
|
||||
/*不允许在中断函数/关中断发阻塞操作,因为阻塞的同时要处理
|
||||
主系统发的消息,不建议在中断函数处理/关闭中断处理*/
|
||||
if (ack == 1) {
|
||||
ASSERT(!(cpu_in_irq() || cpu_irq_disable()), "p2m_post_msg ack");
|
||||
}
|
||||
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
u32 index = 0;
|
||||
if (ack) {
|
||||
msg_q_p->ack_flag |= BIT(0);
|
||||
/*收到ACK消息处理函数,不允许发送ACK消息*/
|
||||
if (post_ack_flag != 1) {
|
||||
ASSERT(0, "post_ack_flag check fail!");
|
||||
}
|
||||
}
|
||||
|
||||
head.type = type;
|
||||
head.ack = ack;
|
||||
head.len = len;
|
||||
head.index = index;
|
||||
|
||||
if (lp_buf_write_enable(msg_q_p, len + sizeof(struct lp_msg_head)) == LP_BUF_WRITE_OVER) {
|
||||
MSG_EXIT_CRITICAL();
|
||||
return MSG_BUF_WRITE_OVER;
|
||||
}
|
||||
|
||||
//写头
|
||||
lp_buf_write(msg_q_p, (u8 *)&head, sizeof(struct lp_msg_head));
|
||||
|
||||
//写数据
|
||||
lp_buf_write(msg_q_p, msg, len);
|
||||
|
||||
__power_recover();
|
||||
|
||||
P11_WKUP_MSYS();
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
|
||||
if (ack) {
|
||||
while (1) {
|
||||
if (p2m_get_ack_flag(index)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*主系统可能在等待P11的消息,处理来自主系统的消息,防止死锁*/
|
||||
if (m2p_msg_hdl(head.index)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MSG_NO_ERROR;
|
||||
}
|
||||
|
||||
void message_init()
|
||||
{
|
||||
MSG_ENTER_CRITICAL();
|
||||
|
||||
memset((void *)m2p_pool, 0, MAX_POOL);
|
||||
memset((void *)p2m_pool, 0, MAX_POOL);
|
||||
|
||||
//初始化m2p消息队列
|
||||
m2p_msg_q.in = 0;
|
||||
m2p_msg_q.out = 0;
|
||||
m2p_msg_q.start = (u32)m2p_pool;
|
||||
m2p_msg_q.count = 0;
|
||||
m2p_msg_q.size = MAX_POOL;
|
||||
m2p_msg_q.ack_flag = 0;
|
||||
|
||||
//初始化p2m消息队列
|
||||
p2m_msg_q.in = 0;
|
||||
p2m_msg_q.out = 0;
|
||||
p2m_msg_q.start = (u32)p2m_pool;
|
||||
p2m_msg_q.count = 0;
|
||||
p2m_msg_q.size = MAX_POOL;
|
||||
p2m_msg_q.ack_flag = 0;
|
||||
|
||||
//赋值m2p消息队列描述地址
|
||||
u32 addr = (u32)&m2p_msg_q;
|
||||
P2M_CBUF_ADDR0 = (addr) & 0xff;
|
||||
P2M_CBUF_ADDR1 = (addr >> 8) & 0xff;
|
||||
P2M_CBUF_ADDR2 = (addr >> 16) & 0xff;
|
||||
P2M_CBUF_ADDR3 = (addr >> 24) & 0xff;
|
||||
|
||||
//赋值p2m消息队列描述地址
|
||||
addr = (u32)&p2m_msg_q;
|
||||
P2M_CBUF1_ADDR0 = (addr) & 0xff;
|
||||
P2M_CBUF1_ADDR1 = (addr >> 8) & 0xff;
|
||||
P2M_CBUF1_ADDR2 = (addr >> 16) & 0xff;
|
||||
P2M_CBUF1_ADDR3 = (addr >> 24) & 0xff;
|
||||
|
||||
MSG_EXIT_CRITICAL();
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "sdk_config.h"
|
||||
#include "sensor_driver.h"
|
||||
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE && TCFG_MMC5603_ENABLE
|
||||
|
||||
#define LOG(fmt,...) printf("[5603] %s " fmt "\n", __func__, ##__VA_ARGS__)
|
||||
|
||||
#define IIC_ADDR_W (0x30 << 1 | 0x0)
|
||||
#define IIC_ADDR_R (0x30 << 1 | 0x1)
|
||||
|
||||
static axis_data_t sensor_data[50];
|
||||
static cbuffer_t sensor_cbuffer;
|
||||
static cbuffer_child_t entry[1];//支持3个成员读取
|
||||
|
||||
static sensor_info_t sensor_info = {
|
||||
.type = SENSOR_DRV_MAGNETIC,
|
||||
.name = "mmc5603",
|
||||
.range = {2, 4, 8, 16},
|
||||
.odr = {10, 25, 50, 100},
|
||||
.cbuffer = 0,
|
||||
};
|
||||
|
||||
static s8 sensor_check(void)
|
||||
{
|
||||
u8 dev_id = 0;
|
||||
sensor_read(IIC_ADDR_R, 0x39, &dev_id, 1, 0);
|
||||
|
||||
if (sensor_info.cbuffer == NULL) {
|
||||
sensor_info.cbuffer = &sensor_cbuffer;
|
||||
cbuf_mult_read_init(sensor_info.cbuffer, sensor_data, sizeof(sensor_data), 1, entry);
|
||||
}
|
||||
LOG("dev_id=%02x cbuf=%x", dev_id, sensor_info.cbuffer);
|
||||
return ((dev_id == 0x10) && sensor_info.cbuffer) ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
|
||||
static s8 sensor_open(u16 range, u16 odr)
|
||||
{
|
||||
u8 register_value = 0;
|
||||
s8 ret = RET_OK;
|
||||
|
||||
/* Write 0x10 to register 0x1B, set RESET bit high */
|
||||
if (ret == RET_OK) {
|
||||
register_value = 0x10;
|
||||
ret = sensor_write(IIC_ADDR_W, 0x1B, ®ister_value, 1); //RESET
|
||||
/* Delay to finish the RESET operation */
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/* Write reg 0x1C, Set BW<1:0> = bandwith */
|
||||
if (ret == RET_OK) {
|
||||
register_value = odr / 75;
|
||||
ret = sensor_write(IIC_ADDR_W, 0x1C, ®ister_value, 1);
|
||||
}
|
||||
|
||||
/* Write reg 0x1A, set ODR<7:0> = sampling_rate */
|
||||
if (ret == RET_OK) {
|
||||
register_value = odr;
|
||||
ret = sensor_write(IIC_ADDR_W, 0x1A, ®ister_value, 1);
|
||||
}
|
||||
|
||||
/* Write reg 0x1B */
|
||||
/* Set Auto_SR_en bit '1', Enable the function of automatic set/reset */
|
||||
/* Set Cmm_freq_en bit '1', Start the calculation of the measurement period according to the ODR*/
|
||||
if (ret == RET_OK) {
|
||||
register_value = 0x80 | 0x20;
|
||||
ret = sensor_write(IIC_ADDR_W, 0x1B, ®ister_value, 1);
|
||||
}
|
||||
|
||||
/* Write reg 0x1D */
|
||||
/* Set Cmm_en bit '1', Enter continuous mode */
|
||||
if (ret == RET_OK) {
|
||||
register_value = 0x10;
|
||||
ret = sensor_write(IIC_ADDR_W, 0x1D, ®ister_value, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static s8 sensor_close(void)
|
||||
{
|
||||
u8 val = 0;
|
||||
return sensor_write(IIC_ADDR_W, 0x1D, &val, 1);
|
||||
}
|
||||
|
||||
static s8 sensor_read_single_data(void *arg, u16 *len)
|
||||
{
|
||||
u8 data_reg[6] = {0};
|
||||
axis_data_t *mag = arg;
|
||||
|
||||
sensor_read(IIC_ADDR_R, 0x00, data_reg, 6, 0);
|
||||
|
||||
mag[0].x = (s16)(data_reg[0] << 8 | data_reg[1]);
|
||||
mag[0].y = (s16)(data_reg[2] << 8 | data_reg[3]);
|
||||
mag[0].z = (s16)(data_reg[4] << 8 | data_reg[5]);
|
||||
|
||||
mag[0].x -= 32768;
|
||||
mag[0].y -= 32768;
|
||||
mag[0].z -= 32768;
|
||||
|
||||
*len = 6;
|
||||
|
||||
if ((*len > 0) && (sensor_info.cbuffer)) {
|
||||
u32 wlen = cbuf_write(sensor_info.cbuffer, arg, *len);
|
||||
LOG("cbuf wlen=%d glen=%d", wlen, *len);
|
||||
}
|
||||
LOG("mag:%d,%d,%d", mag[0].x, mag[0].y, mag[0].z);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
REGISTER_SENSOR(sensor_magnetic) = {
|
||||
.info = &sensor_info,
|
||||
.online = sensor_check,
|
||||
.open = sensor_open,
|
||||
.close = sensor_close,
|
||||
.run = sensor_read_single_data,
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,180 @@
|
||||
#include "sdk_config.h"
|
||||
#include "sensor_driver.h"
|
||||
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE && TCFG_SC7A20_ENABLE
|
||||
|
||||
#define LOG(fmt,...) printf("[sc7a20] " fmt "\n",##__VA_ARGS__)
|
||||
|
||||
/***使用驱动前请根据实际接线情况配置(7bit)IIC地址******/
|
||||
/**SC7A20的SDO 脚接地: 0x18****************/
|
||||
/**SC7A20的SDO 脚接电源: 0x19****************/
|
||||
#define IIC_ADDR_W (0x19U << 1 | 0x0)
|
||||
#define IIC_ADDR_R (0x19U << 1 | 0x1)
|
||||
/*******************************************************/
|
||||
static axis_data_t accel_data[50]; //accel data buffer
|
||||
static cbuffer_t accel_cbuffer;
|
||||
static cbuffer_child_t entry[3];//支持3个成员读取
|
||||
static sensor_info_t sensor_info = {
|
||||
.type = SENSOR_DRV_ACCELER,
|
||||
.name = "sc7a20",
|
||||
.range = {2, 4, 8, 16},
|
||||
.odr = {10, 25, 50, 100},
|
||||
.cbuffer = 0,
|
||||
};
|
||||
static s8 sensor_open(u16 range, u16 odr);
|
||||
static const sensor_regs_t sensor_regs_array[] = {
|
||||
{0x57, 0x00},
|
||||
{0x1f, 0x00},
|
||||
{0x20, 0x3F},
|
||||
{0x21, 0x70},
|
||||
{0x23, 0x10},
|
||||
{0x24, 0x40},
|
||||
{0x2E, 0x8F},
|
||||
{0x22, 0x00},
|
||||
};
|
||||
|
||||
|
||||
static s8 sensor_check(void)
|
||||
{
|
||||
u8 dev_id = 0;
|
||||
sensor_read(IIC_ADDR_R, 0x70, &dev_id, 1, 0);
|
||||
|
||||
if (sensor_info.cbuffer == NULL) {
|
||||
sensor_info.cbuffer = &accel_cbuffer;
|
||||
cbuf_mult_read_init(sensor_info.cbuffer, accel_data, sizeof(accel_data), 3, entry);
|
||||
}
|
||||
LOG("dev_id=%02x cbuf=%x", dev_id, (u32)sensor_info.cbuffer);
|
||||
return ((dev_id == 0x28 || dev_id == 0x11) && sensor_info.cbuffer) ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
static s8 sensor_read_config(void)
|
||||
{
|
||||
u8 reg_val = 0;
|
||||
for (u8 i = 0; i < sizeof(sensor_regs_array) / sizeof(sensor_regs_t); i++) {
|
||||
if (sensor_read(IIC_ADDR_R, sensor_regs_array[i].addr, ®_val, 1, 0) == RET_ERR) {
|
||||
return RET_ERR;
|
||||
}
|
||||
LOG("reg %02x = %02x", sensor_regs_array[i].addr, reg_val);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static s8 sensor_open(u16 range, u16 odr)
|
||||
{
|
||||
const u8 config_range[4] = {0x00, 0x10, 0x20, 0x30};
|
||||
const u8 config_odr[4] = {0x2F, 0x3F, 0x4F, 0x5F};
|
||||
|
||||
u8 acc_conf_odr = 0x3F; //默认 25hz
|
||||
u8 acc_conf_range = 0x10; //默认 +-4g
|
||||
|
||||
for (u8 i = 0; i < sizeof(sensor_regs_array) / sizeof(sensor_regs_t); i++) {
|
||||
if (sensor_write(IIC_ADDR_W, sensor_regs_array[i].addr, (u8 *)&sensor_regs_array[i].value, 1) == RET_ERR) {
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
for (u8 i = 0; i < 4; i++) {
|
||||
if (sensor_info.range[i] == range) {
|
||||
acc_conf_range = config_range[i];
|
||||
}
|
||||
if (sensor_info.odr[i] == odr) {
|
||||
acc_conf_odr = config_odr[i];
|
||||
}
|
||||
}
|
||||
|
||||
sensor_write(IIC_ADDR_W, 0x20, &acc_conf_odr, 1);
|
||||
sensor_write(IIC_ADDR_W, 0x23, &acc_conf_range, 1);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
static s8 sensor_close(void)
|
||||
{
|
||||
u8 val = 0;
|
||||
return sensor_write(IIC_ADDR_W, 0x20, &val, 1);
|
||||
}
|
||||
|
||||
static s8 sensor_read_fifo_data(void *arg, u16 *len)
|
||||
{
|
||||
u8 fifo_len = 0;
|
||||
u8 temp_arry[6];
|
||||
axis_data_t *accel = arg;
|
||||
|
||||
sensor_read(IIC_ADDR_R, 0x2f, &fifo_len, 1, 0);
|
||||
fifo_len = fifo_len & 0x1f;
|
||||
|
||||
for (u8 i = 0; i < fifo_len; i++) {
|
||||
sensor_read(IIC_ADDR_R, 0xa8, temp_arry, 6, 0);
|
||||
accel[i].x = (((s16)((s16)temp_arry[1] * 256 + temp_arry[0])) >> 3);
|
||||
accel[i].y = -(((s16)((s16)temp_arry[3] * 256 + temp_arry[2])) >> 3);
|
||||
accel[i].z = (((s16)((s16)temp_arry[5] * 256 + temp_arry[4])) >> 3);
|
||||
LOG(" xyz(%d,%d): %d %d %d", fifo_len, i, accel[i].x, accel[i].y, accel[i].z);
|
||||
}
|
||||
fifo_len *= sizeof(axis_data_t);
|
||||
|
||||
if ((fifo_len > 0) && (sensor_info.cbuffer)) {
|
||||
|
||||
if (!cbuf_is_write_able(sensor_info.cbuffer, fifo_len)) {
|
||||
cbuf_mult_read_alloc_len_updata(sensor_info.cbuffer, 0, fifo_len);
|
||||
cbuf_mult_read_alloc_len_updata(sensor_info.cbuffer, 1, fifo_len);
|
||||
}
|
||||
|
||||
u32 wlen = cbuf_write(sensor_info.cbuffer, arg, fifo_len);
|
||||
LOG("cbuf wlen=%d glen=%d", wlen, fifo_len);
|
||||
}
|
||||
*len = fifo_len;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_SENSOR_SLEEP_ENABLE
|
||||
static const sensor_regs_t sensor_wakeup_regs_array[] = {
|
||||
{0x20, 0x47},
|
||||
{0x23, 0x88}, //+-2g
|
||||
{0x21, 0x31},
|
||||
{0x22, 0x40}, //AOI中断on int1
|
||||
{0x25, 0x00},
|
||||
{0x24, 0x00},
|
||||
{0x30, 0x2a}, //x,y,z高事件或检测
|
||||
{0x32, 0x02}, //检测门限: 1-127, 值越小, 灵敏度越高
|
||||
{0x33, 0x00},
|
||||
};
|
||||
|
||||
static s8 sensor_wakeup_enable(void)
|
||||
{
|
||||
LOG("sensor_wakeup_enable");
|
||||
for (u8 i = 0; i < sizeof(sensor_wakeup_regs_array) / sizeof(sensor_regs_t); i++) {
|
||||
if (sensor_write(IIC_ADDR_W, sensor_wakeup_regs_array[i].addr, (u8 *)&sensor_wakeup_regs_array[i].value, 1) == RET_ERR) {
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
__attribute__((weak)) s8 driver_sc7a20_is_wake(void)
|
||||
{
|
||||
u8 reg_val = 0;
|
||||
if (sensor_read(IIC_ADDR_R, 0x31, ®_val, 1, 0) == RET_OK) {
|
||||
LOG("reg_val=%x wake=%x", reg_val, reg_val & 0x2a);
|
||||
if (reg_val & 0x2a) {
|
||||
sensor_open(4, 25);
|
||||
} else {
|
||||
return RET_ERR;
|
||||
}
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
REGISTER_SENSOR(sensor_acc) = {
|
||||
.info = &sensor_info,
|
||||
.online = sensor_check,
|
||||
.open = sensor_open,
|
||||
.close = sensor_close,
|
||||
.run = sensor_read_fifo_data,
|
||||
#if CONFIG_SENSOR_SLEEP_ENABLE
|
||||
.sleep = sensor_wakeup_enable,
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,159 @@
|
||||
|
||||
/*********************************************************************************************************
|
||||
* Copyright(c) 2018, Vcare Corporation. All rights reserved.
|
||||
**********************************************************************************************************
|
||||
* @file module_heart_vc.c
|
||||
* @brief
|
||||
* @details
|
||||
* @author
|
||||
* @date
|
||||
* @version v1.6
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
#include "sdk_config.h"
|
||||
#include "sensor_driver.h"
|
||||
#include "vcHr11Hci.h"
|
||||
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE && TCFG_VCHR11S_ENABLE
|
||||
|
||||
#define LOG(fmt,...) printf("[vcHr11] " fmt "\n",##__VA_ARGS__)
|
||||
|
||||
#define IIC_ADDR_W (0x33<<1 | 0)
|
||||
#define IIC_ADDR_R (0x33<<1 | 1)
|
||||
|
||||
|
||||
const uint32_t mcuOscData = 30000; // Timer clock frequency Be used to adjust INT frequency
|
||||
const uint16_t mcuI2cClock = 400; // MCU I2C clock frequency
|
||||
|
||||
static vcHr11_t vcHr11;
|
||||
|
||||
static s16 sensor_data[50 * 2];
|
||||
static cbuffer_t sensor_cbuffer;
|
||||
static cbuffer_child_t entry[1];//支持3个成员读取
|
||||
|
||||
static sensor_info_t sensor_info = {
|
||||
.type = SENSOR_DRV_HR_SPO2,
|
||||
.name = "lc11s",
|
||||
.odr = {10, 25, 50, 100},
|
||||
.cbuffer = 0,
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern u64 lptmr1_get_pass_us(void);
|
||||
extern u64 __lp_timer_get_cnt(u8 lptmr_x);
|
||||
extern u32 lrc_get_avg_freq(void);
|
||||
|
||||
u32 vcHr11GetRtcCountFromMCU(void)
|
||||
{
|
||||
static u64 cnt = 0;
|
||||
u32 pass_32bitcnt;
|
||||
|
||||
if (lrc_get_avg_freq() == 0) {
|
||||
LOG("lrc_get_avg_freq is 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cnt += lptmr1_get_pass_us(); */
|
||||
|
||||
cnt = lptmr1_get_pass_us();
|
||||
pass_32bitcnt = cnt / (1000000 / mcuOscData);
|
||||
pass_32bitcnt = pass_32bitcnt & (0xffffffff);
|
||||
LOG("cnt=%d %d ", pass_32bitcnt, (u32)lptmr1_get_pass_us());
|
||||
return pass_32bitcnt;
|
||||
}
|
||||
|
||||
vcHr11Ret_t vcHr11WriteRegisters(uint8_t startAddress, uint8_t *pRegisters, uint8_t len)
|
||||
{
|
||||
u8 ret = sensor_write(IIC_ADDR_W, startAddress, pRegisters, len);
|
||||
return ret == RET_OK ? VCHR11RET_ISOK : VCHR11RET_ISERR;
|
||||
}
|
||||
|
||||
|
||||
vcHr11Ret_t vcHr11ReadRegisters(uint8_t startAddress, uint8_t *pRegisters, uint8_t len)
|
||||
{
|
||||
u8 ret = sensor_read(IIC_ADDR_R, startAddress, pRegisters, len, 0);
|
||||
return ret == RET_OK ? VCHR11RET_ISOK : VCHR11RET_ISERR;
|
||||
}
|
||||
|
||||
static s8 sensor_check(void)
|
||||
{
|
||||
u8 dev_id = 0;
|
||||
u32 vcHr11_addr = (u32)(&vcHr11);
|
||||
|
||||
sensor_read(IIC_ADDR_R, VCREG0, &dev_id, 1, 0);
|
||||
|
||||
if (sensor_info.cbuffer == NULL) {
|
||||
memcpy(sensor_info.range, &vcHr11_addr, sizeof(u32));
|
||||
sensor_info.cbuffer = &sensor_cbuffer;
|
||||
cbuf_mult_read_init(sensor_info.cbuffer, sensor_data, sizeof(sensor_data), 1, entry);
|
||||
}
|
||||
LOG("dev_id=%02x cbuf=%x vcHr11_addr=%x", dev_id, (u32)sensor_info.cbuffer, vcHr11_addr);
|
||||
return ((0x21 == dev_id || 0x29 == dev_id) && sensor_info.cbuffer) ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
|
||||
static s8 sensor_open(u16 vcHr11WorkMode, u16 odr)
|
||||
{
|
||||
vcHr11Ret_t ret = VCHR11RET_ISOK;
|
||||
vcHr11_t *pVcHr11 = &vcHr11;
|
||||
|
||||
LOG("mode=%d", vcHr11WorkMode);
|
||||
|
||||
cbuf_clear(sensor_info.cbuffer);
|
||||
|
||||
ret = vcHr11SoftReset(pVcHr11);
|
||||
ret = vcHr11StopSample(pVcHr11);
|
||||
|
||||
if (VCWORK_MODE_POWER_OFF != vcHr11WorkMode) {
|
||||
|
||||
pVcHr11->vcSampleRate = odr;
|
||||
pVcHr11->mcuOscValue = mcuOscData;
|
||||
pVcHr11->mcuSclRate = mcuI2cClock;
|
||||
pVcHr11->workMode = vcHr11WorkMode;
|
||||
|
||||
ret = vcHr11StartSample(pVcHr11);
|
||||
}
|
||||
return ret == VCHR11RET_ISOK ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
static s8 sensor_close(void)
|
||||
{
|
||||
vcHr11Ret_t ret = VCHR11RET_ISOK;
|
||||
vcHr11_t *pVcHr11 = &vcHr11;
|
||||
|
||||
ret = vcHr11SoftReset(pVcHr11);
|
||||
ret = vcHr11StopSample(pVcHr11);
|
||||
return ret == VCHR11RET_ISOK ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static s8 sensor_process(void *arg, u16 *len)
|
||||
{
|
||||
u16 buf_len = 0;
|
||||
u8 ppgLength = 0;
|
||||
|
||||
vcHr11GetSampleValues(&vcHr11, &ppgLength);
|
||||
LOG("oscFlg=%d ppgLength=%d readFlg=%d wearStatus=%d", vcHr11.oscCheckFinishFlag, ppgLength, vcHr11.vcFifoReadFlag, vcHr11.wearStatus);
|
||||
|
||||
if (vcHr11.vcFifoReadFlag && vcHr11.wearStatus) {
|
||||
vcHr11.vcFifoReadFlag = 0;
|
||||
if (ppgLength > 0) {
|
||||
cbuf_write(sensor_info.cbuffer, vcHr11.sampleData.ppgValue, ppgLength * sizeof(u16));
|
||||
}
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
REGISTER_SENSOR(sensor_hr) = {
|
||||
.info = &sensor_info,
|
||||
.online = sensor_check,
|
||||
.open = sensor_open,
|
||||
.close = sensor_close,
|
||||
.run = sensor_process,
|
||||
};
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,291 @@
|
||||
|
||||
#ifndef LIB_vcHr11_HCI_vcHr11HCI_H_
|
||||
#define LIB_vcHr11_HCI_vcHr11HCI_H_
|
||||
|
||||
#include "stdint.h"
|
||||
#include "sdk_config.h"
|
||||
#include "includes.h"
|
||||
|
||||
|
||||
#define Drive_Version V_1_9_4
|
||||
|
||||
#define HW_HALVE_POWER_CAP 1 //sample config param halve & oversample double
|
||||
|
||||
/* HW_LC09A_PROJ(1), single green led
|
||||
* HW_LC09A_PROJ(0), 10A/11S project
|
||||
*/
|
||||
#define HW_LC09A_PROJ 1
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Register Address Declaration
|
||||
*
|
||||
******************************************************************************/
|
||||
/* Read Only */
|
||||
#define VCREG0 (0x00)
|
||||
#define VCREG0_SIZE (1)
|
||||
#define VCREG1 (0x01)
|
||||
#define VCREG1_SIZE (1)
|
||||
#define VCREG2 (0x02)
|
||||
#define VCREG2_SIZE (1)
|
||||
#define VCREG3 (0x03)
|
||||
#define VCREG3_SIZE (1)
|
||||
#define VCREG4 (0x04)
|
||||
#define VCREG4_SIZE (1)
|
||||
#define VCREG5 (0x05)
|
||||
#define VCREG5_SIZE (1)
|
||||
#define VCREG6 (0x06)
|
||||
#define VCREG6_SIZE (1)
|
||||
#define VCREG7 (0x07)
|
||||
#define VCREG7_SIZE (2)
|
||||
#define VCREG8 (0x09)
|
||||
#define VCREG8_SIZE (2)
|
||||
#define VCREG9 (0x80)
|
||||
#define VCREG9_SIZE (128)
|
||||
|
||||
/* Write Only */
|
||||
#define VCREG10 (0x3B)
|
||||
#define VCREG10_SIZE (1)
|
||||
|
||||
/* Read or Write */
|
||||
#define VCREG11 (0x10)
|
||||
#define VCREG11_SIZE (1)
|
||||
#define VCREG12 (0x11)
|
||||
#define VCREG12_SIZE (1)
|
||||
#define VCREG13 (0x12)
|
||||
#define VCREG13_SIZE (1)
|
||||
#define VCREG14 (0x13)
|
||||
#define VCREG14_SIZE (1)
|
||||
#define VCREG15 (0x14)
|
||||
#define VCREG15_SIZE (2)
|
||||
#define VCREG16 (0x16)
|
||||
#define VCREG16_SIZE (1)
|
||||
#define VCREG17 (0x17)
|
||||
#define VCREG17_SIZE (1)
|
||||
#define VCREG18 (0x18)
|
||||
#define VCREG18_SIZE (1)
|
||||
#define VCREG19 (0x19)
|
||||
#define VCREG19_SIZE (1)
|
||||
#define VCREG20 (0x1A)
|
||||
#define VCREG20_SIZE (1)
|
||||
#define VCREG21 (0x1B)
|
||||
#define VCREG21_SIZE (1)
|
||||
#define VCREG22 (0x1C)
|
||||
#define VCREG22_SIZE (1)
|
||||
#define VCREG23 (0x1D)
|
||||
#define VCREG23_SIZE (1)
|
||||
#define VCREG24 (0x1E)
|
||||
#define VCREG24_SIZE (1)
|
||||
#define VCREG25 (0x1F)
|
||||
#define VCREG25_SIZE (1)
|
||||
#define VCREG26 (0x20)
|
||||
#define VCREG26_SIZE (1)
|
||||
#define VCREG27 (0x21)
|
||||
#define VCREG27_SIZE (1)
|
||||
#define VCREG28 (0x22)
|
||||
#define VCREG28_SIZE (1)
|
||||
|
||||
|
||||
/* Bit fields for VCREG1s */
|
||||
#define VCREG1_CONFLICT (0x01 << 4)
|
||||
#define VCREG1_INSAMPLE (0x01 << 3)
|
||||
#define VCREG1_INTPS (0x01 << 4)
|
||||
#define VCREG1_INTOV (0x01 << 3)
|
||||
#define VCREG1_INTFIFO (0x01 << 2)
|
||||
#define VCREG1_INTENV (0x01 << 1)
|
||||
#define VCREG1_INTPPG (0x01 << 0)
|
||||
|
||||
/* Threshold Settings */
|
||||
#define VCENV_TH 8 //Causes of ENV interruption
|
||||
#define VCPPG_TH 10 //Causes of PPG interruption PPG_TH = 300
|
||||
#define VCPS_TH 4
|
||||
#define VCADJUST_INCREASE 22 // 1.4 << 4 = 22.4//1.4f
|
||||
#define VCADJUST_DECREASE 11 // 0.7 << 4 = 11.2//0.7f
|
||||
#define VCADJUST_STEP_MAX 32
|
||||
#define VCADJUST_STEP_MIN 1
|
||||
|
||||
#define VCUNWEAR_CNT 3
|
||||
#define VCISWEAR_CNT 1
|
||||
|
||||
#define SLOTCHNU 3
|
||||
|
||||
#define VCWEAR_STATUS_DETECTION_OFF 0
|
||||
#define VCWEAR_STATUS_DETECTION_ON 1
|
||||
#define VCWEAR_STATUS_DETECTION_MODE VCWEAR_STATUS_DETECTION_ON
|
||||
|
||||
#define VCWEAR_READ_FIFO_BY_TIME (0)
|
||||
#define VCWEAR_READ_FIFO_BY_INT (1)
|
||||
#if TCFG_HR_SENSOR_READ_BY_INT
|
||||
#define VCWEAR_READ_FIFO_MODE VCWEAR_READ_FIFO_BY_INT
|
||||
#else
|
||||
#define VCWEAR_READ_FIFO_MODE VCWEAR_READ_FIFO_BY_TIME
|
||||
#endif
|
||||
|
||||
#define SportMotionEn 0
|
||||
#define BiometricEn 0
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Data Type Declaration
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
VCWORK_MODE_HRWORK = 0,
|
||||
VCWORK_MODE_CROSSTALKTEST = 1,
|
||||
VCWORK_MODE_SPO2WORK = 2,
|
||||
VCWORK_MODE_GSENSORWORK = 3,
|
||||
VCWORK_MODE_TEMPWORK = 4,
|
||||
VCWORK_MODE_NOISEWORK = 5,
|
||||
VCWORK_MODE_LPDETECTION = 6,
|
||||
VCWORK_MODE_POWER_OFF = 255,
|
||||
} vcHr11Mode_t;
|
||||
|
||||
typedef enum {
|
||||
VCHR11ADJUSTDIRECTION_NULL = 0,
|
||||
VCHR11ADJUSTDIRECTION_UP = 1,
|
||||
VCHR11ADJUSTDIRECTION_DOWN = 2,
|
||||
} vcHr11AdjustDirection;
|
||||
|
||||
typedef enum {
|
||||
VERSION_A = 0,
|
||||
VERSION_B = 1,
|
||||
} vcHr11Version_t;
|
||||
|
||||
typedef struct {
|
||||
vcHr11AdjustDirection direction;
|
||||
vcHr11AdjustDirection directionLast;
|
||||
uint16_t step;
|
||||
} vcHr11AdjustInfo_t;
|
||||
|
||||
typedef enum {
|
||||
VCHR11WEARST_UNWEAR = 0,
|
||||
VCHR11WEARST_ISWEAR = 1,
|
||||
} vcHr11WearStatus_e;
|
||||
|
||||
typedef enum {
|
||||
VCHR11RET_ISOK = 0,
|
||||
VCHR11RET_ISWEARTOUNWEAR = 1,
|
||||
VCHR11RET_UNWEARTOISWEAR = 2,
|
||||
VCHR11RET_ISERR = 4,
|
||||
VCHR11RET_ISCONFLICT = 8,
|
||||
VCHR11RET_ISINSAMPLE = 16,
|
||||
VCHR11RET_SOLTISOVERLOAD = 32,
|
||||
VCHR11RET_PSISOVERLOAD = 64,
|
||||
VCHR11RET_ENVCURRENTISLARGE = 128,
|
||||
VCHR11RET_PSENVCURRENTISLARGE = 256,
|
||||
VCHR11RET_PPGCANNOTADJUSTABLE = 512,
|
||||
VCHR11RET_FIFOISOVERFLOW = 1024,
|
||||
VCHR11RET_PDRESISMAX = 2048,
|
||||
VCHR11RET_PDRESCANNOTRELEASE = 4096,
|
||||
} vcHr11Ret_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t maxLedCur;
|
||||
uint8_t pdResValue[3];
|
||||
uint8_t currentValue[3];
|
||||
uint8_t psValue; //PS Sample value.
|
||||
uint8_t preValue[2]; //Environment Sample value.
|
||||
uint8_t envValue[3]; //Environment Sample value.
|
||||
uint16_t ppgValue[128]; //PPG sample value.
|
||||
} vcHr11SampleData_t;
|
||||
|
||||
typedef struct {
|
||||
bool isRunning;
|
||||
bool vcFifoReadFlag;
|
||||
bool vcPsFlag;
|
||||
bool oscCheckFinishFlag;
|
||||
|
||||
uint8_t regConfig[17];
|
||||
uint8_t unWearCnt;
|
||||
uint8_t isWearCnt;
|
||||
uint8_t vcHr11Status;
|
||||
uint8_t intReason;
|
||||
uint8_t devId;
|
||||
vcHr11Mode_t workMode;
|
||||
vcHr11Version_t version;
|
||||
vcHr11WearStatus_e wearStatus;
|
||||
|
||||
uint16_t vcSampleRate;
|
||||
uint16_t mcuOscValue;
|
||||
uint16_t mcuSclRate;
|
||||
vcHr11AdjustInfo_t adjustInfo[2];
|
||||
vcHr11SampleData_t sampleData;
|
||||
|
||||
} vcHr11_t;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Function Declaration
|
||||
******************************************************************************/
|
||||
/*
|
||||
* @brief
|
||||
* Get sample datas from vcHr11.
|
||||
*
|
||||
**/
|
||||
vcHr11Ret_t vcHr11GetSampleValues(vcHr11_t *pvcHr11, uint8_t *DataLen);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Manual start sample of vcHr11.
|
||||
*
|
||||
**/
|
||||
vcHr11Ret_t vcHr11StartSample(vcHr11_t *pvcHr11);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Manual stop sample of vcHr11.
|
||||
*
|
||||
**/
|
||||
vcHr11Ret_t vcHr11StopSample(vcHr11_t *pvcHr11);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Manual SoftReset the vcHr11
|
||||
*
|
||||
**/
|
||||
vcHr11Ret_t vcHr11SoftReset(vcHr11_t *pvcHr11);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* init the vcHr11
|
||||
*
|
||||
**/
|
||||
extern void vcHr11Init(vcHr11_t *pVcHr11, vcHr11Mode_t vcHr11WorkMode);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*
|
||||
**/
|
||||
extern vcHr11Ret_t vcHr11ReadRegisters(uint8_t startAddress, uint8_t *pRegisters, uint8_t len);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*
|
||||
*
|
||||
**/
|
||||
extern vcHr11Ret_t vcHr11WriteRegisters(uint8_t startAddress, uint8_t *pRegisters, uint8_t len);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Write Registers to vcHr11. This function needs to be implemented
|
||||
* according to the MCU.
|
||||
**/
|
||||
extern uint32_t vcHr11GetRtcCountFromMCU(void);
|
||||
|
||||
/*
|
||||
* @brief
|
||||
*
|
||||
*
|
||||
**/
|
||||
extern void green_led_off_state_gsensor_abs_sum_diff_func(int32_t x_axis_value, int32_t y_axis_value, int32_t z_axis_value);
|
||||
|
||||
typedef vcHr11Ret_t (* vcHr11_read_cb)(uint8_t startAddress, uint8_t *pRegisters, uint8_t len);
|
||||
typedef vcHr11Ret_t (* vcHr11_write_cb)(uint8_t startAddress, uint8_t *pRegisters, uint8_t len);
|
||||
|
||||
|
||||
#define DEBUG_LOG(fmt,...) //printf("[vchr] %s " fmt "\n",__func__, ##__VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,179 @@
|
||||
#include "sensor_driver.h"
|
||||
#include "includes.h"
|
||||
#include "uart.h"
|
||||
#include "debug.h"
|
||||
#include "gpio.h"
|
||||
#include "bank_switch.h"
|
||||
#include "usr_timer.h"
|
||||
#include "iic_api.h"
|
||||
|
||||
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE
|
||||
|
||||
#define LOG(fmt,...) printf("[driver] %s " fmt "\n",__func__, ##__VA_ARGS__)
|
||||
|
||||
static u8 sensor_timer_msec = 200;
|
||||
|
||||
|
||||
u8 sensor_write(u8 iic_dev_addr, u8 register_address, u8 *buf, u8 data_len)
|
||||
{
|
||||
int ret = hw_i2c_master_write_nbytes_to_device_reg(HW_IIC_0, iic_dev_addr, ®ister_address, 1, buf, data_len);
|
||||
return ret == data_len ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
u8 sensor_read(u8 iic_dev_addr, u8 register_address, u8 *buf, u8 data_len, u8 ignore_len)
|
||||
{
|
||||
int ret = hw_i2c_master_read_nbytes_from_device_reg(HW_IIC_0, iic_dev_addr, ®ister_address, 1, buf, data_len);
|
||||
return ret == data_len ? RET_OK : RET_ERR;
|
||||
}
|
||||
|
||||
SENSOR_INTERFACE *sensor_driver_find(sensor_type_t type)
|
||||
{
|
||||
SENSOR_INTERFACE *sensor_driver = NULL;
|
||||
list_for_each_sensor(sensor_driver) {
|
||||
if (sensor_driver->info->type == type) {
|
||||
return sensor_driver;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void sensor_info_printf(void)
|
||||
{
|
||||
#if CONFIG_UART_DEBUG_ENABLE
|
||||
printf("\n\n******** sensor info ********\n");
|
||||
SENSOR_INTERFACE *driver = NULL;
|
||||
|
||||
list_for_each_sensor(driver) {
|
||||
printf("\nname : %s\n", driver->info->name);
|
||||
printf("type : %d\n", driver->info->type);
|
||||
printf("state : %d\n", driver->info->state);
|
||||
printf("range : +-%d +-%d +-%d +-%d\n", driver->info->range[0], driver->info->range[1], driver->info->range[2], driver->info->range[3]);
|
||||
printf("odr : %d %d %d %d\n", driver->info->odr[0], driver->info->odr[1], driver->info->odr[2], driver->info->odr[3]);
|
||||
}
|
||||
printf("\n****** sensor info end ******\n\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void sensor_driver_check(void)
|
||||
{
|
||||
SENSOR_INTERFACE *sensor_driver = NULL;
|
||||
list_for_each_sensor(sensor_driver) {
|
||||
if ((sensor_driver->online != NULL) && (sensor_driver->online() == RET_OK)) {
|
||||
sensor_driver->info->state = SENSOR_STATE_ONLINE;
|
||||
} else {
|
||||
sensor_driver->info->state = SENSOR_STATE_OFFLINE;
|
||||
}
|
||||
}
|
||||
|
||||
//发送sensor_drvier_info给大核
|
||||
int msg[3];
|
||||
msg[0] = MSG_P11_SENSOR_INFO;
|
||||
msg[1] = (int)&sensor_dev_begin;
|
||||
msg[2] = (int)&sensor_dev_end;
|
||||
int ret = p2m_post_msg(MSG_APP, 0, (u8 *)msg, sizeof(msg));
|
||||
LOG("begin=%x end=%x ret=%d", (u32)sensor_dev_begin, (u32)sensor_dev_end, ret);
|
||||
sensor_info_printf();
|
||||
}
|
||||
|
||||
static void sensor_timer_irq_handle(void *priv)
|
||||
{
|
||||
task_post_msg(NULL, 1, MSG_P11_SYS_KICK);
|
||||
}
|
||||
|
||||
|
||||
void sensor_timer_enable(u8 enable)
|
||||
{
|
||||
static u16 timer_handle = 0;
|
||||
|
||||
if (enable && timer_handle == 0) {
|
||||
timer_handle = usr_timer_add(NULL, sensor_timer_irq_handle, sensor_timer_msec, 1);
|
||||
LOG("handle=%d msec=%d", timer_handle, sensor_timer_msec);
|
||||
} else if ((!enable) && (timer_handle > 0)) {
|
||||
usr_timer_del(timer_handle);
|
||||
timer_handle = 0;
|
||||
LOG("handle=%d", timer_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sensor_timer_modify(u32 msec)
|
||||
{
|
||||
sensor_timer_msec = msec;
|
||||
sensor_timer_enable(0);
|
||||
sensor_timer_enable(1);
|
||||
}
|
||||
|
||||
void sensor_driver_sleep(u8 type, u8 enable)
|
||||
{
|
||||
SENSOR_INTERFACE *sensor_driver = sensor_driver_find(type);
|
||||
if (sensor_driver->sleep) {
|
||||
LOG("type=%d enable=%d", type, enable);
|
||||
sensor_driver->sleep();
|
||||
sensor_timer_enable(!enable);
|
||||
}
|
||||
}
|
||||
|
||||
void sensor_driver_irq_handle(void)
|
||||
{
|
||||
__attribute__((weak)) s8 driver_sc7a20_is_wake(void);
|
||||
if (driver_sc7a20_is_wake) {
|
||||
if (driver_sc7a20_is_wake() == RET_OK) {
|
||||
sensor_timer_enable(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sensor_driver_init(u8 type, u8 enable, u16 range, u8 odr)
|
||||
{
|
||||
SENSOR_INTERFACE *sensor_driver = sensor_driver_find(type);
|
||||
LOG("type=%d enable=%d range=%d odr=%d driver=%x", type, enable, range, odr, (u32)sensor_driver);
|
||||
|
||||
if ((sensor_driver != NULL) && (sensor_driver->open != NULL)) {
|
||||
if (enable) {
|
||||
if (sensor_driver->open(range, odr) == RET_OK) {
|
||||
sensor_driver->info->state = SENSOR_STATE_OPEN;
|
||||
sensor_timer_enable(1);
|
||||
LOG("type %d sucess!", type);
|
||||
} else {
|
||||
LOG("type %d failed!", type);
|
||||
}
|
||||
} else {
|
||||
if (sensor_driver->close() == RET_OK) {
|
||||
sensor_driver->info->state = SENSOR_STATE_CLOSE;
|
||||
LOG("type %d sucess!", type);
|
||||
} else {
|
||||
LOG("type %d failed!", type);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG("no driver for sensor %d", type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void sensor_driver_run(void)
|
||||
{
|
||||
u16 data[30 * 3];
|
||||
u16 size = sizeof(data);
|
||||
|
||||
SENSOR_INTERFACE *sensor_driver = NULL;
|
||||
SENSOR_INTERFACE *acceler_algorithm = NULL;
|
||||
|
||||
acceler_algorithm = sensor_driver_find(SENSOR_ALGO_WRIST_TILT);
|
||||
list_for_each_sensor(sensor_driver) {
|
||||
if ((sensor_driver->info->type < SENSOR_DRV_MAX_NUM) &&
|
||||
(sensor_driver->info->state == SENSOR_STATE_OPEN) && (sensor_driver->run)) {
|
||||
sensor_driver->run(data, &size);
|
||||
|
||||
if ((sensor_driver->info->type == SENSOR_DRV_ACCELER) &&
|
||||
(acceler_algorithm != NULL) && (acceler_algorithm->run)) {
|
||||
acceler_algorithm->run(data, &size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include "includes.h"
|
||||
#include "circular_buf.h"
|
||||
#include "main.h"
|
||||
|
||||
#define RET_OK (1)
|
||||
#define RET_ERR (0)
|
||||
|
||||
typedef enum {
|
||||
|
||||
SENSOR_DRV_ACCELER = 0x00,
|
||||
SENSOR_DRV_GYRO,
|
||||
SENSOR_DRV_MAGNETIC,
|
||||
SENSOR_DRV_HR,
|
||||
SENSOR_DRV_SPO2,
|
||||
SENSOR_DRV_HR_SPO2,
|
||||
SENSOR_DRV_WEAR_DETECTION,
|
||||
SENSOR_DRV_TEMP,
|
||||
SENSOR_DRV_MAX_NUM,
|
||||
|
||||
SENSOR_ALGO_WRIST_TILT = 0x20,
|
||||
SENSOR_ALGO_HR,
|
||||
SENSOR_ALGO_SPO2,
|
||||
SENSOR_ALGO_STEP_COUNTER,
|
||||
} sensor_type_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SENSOR_STATE_OFFLINE = 0,
|
||||
SENSOR_STATE_ONLINE = 1,
|
||||
SENSOR_STATE_CLOSE = 1,
|
||||
SENSOR_STATE_OPEN = 2,
|
||||
} sensor_state_t;
|
||||
|
||||
typedef struct {
|
||||
u8 addr;
|
||||
u8 value;
|
||||
} sensor_regs_t;
|
||||
|
||||
typedef struct {
|
||||
u8 type;
|
||||
u8 state;
|
||||
u8 name[20];
|
||||
u8 odr[4];
|
||||
u16 range[4];
|
||||
cbuffer_t *cbuffer;
|
||||
} sensor_info_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
u8 type;
|
||||
u8 enable;
|
||||
u8 odr;
|
||||
u16 range;
|
||||
} p11_sensor_t;
|
||||
|
||||
typedef struct {
|
||||
sensor_info_t *info;
|
||||
s8(*open)(u16 range, u16 odr);
|
||||
s8(*close)(void);
|
||||
s8(*run)(void *arg, u16 *len);
|
||||
s8(*online)(void);
|
||||
s8(*sleep)(void);
|
||||
} SENSOR_INTERFACE;
|
||||
|
||||
extern SENSOR_INTERFACE sensor_dev_begin[];
|
||||
extern SENSOR_INTERFACE sensor_dev_end[];
|
||||
|
||||
#define REGISTER_SENSOR(Sensor) \
|
||||
static const SENSOR_INTERFACE Sensor SEC_USED(.sensor_dev)
|
||||
|
||||
#define list_for_each_sensor(c) \
|
||||
for (c=sensor_dev_begin; c<sensor_dev_end; c++)
|
||||
|
||||
|
||||
typedef struct {
|
||||
short x;
|
||||
short y;
|
||||
short z;
|
||||
} axis_data_t;
|
||||
|
||||
u8 sensor_write(u8 w_chip_id, u8 register_address, u8 *buf, u8 data_len);
|
||||
u8 sensor_read(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len, u8 ignore_len);
|
||||
|
||||
void sensor_timer_modify(u32 msec);
|
||||
|
||||
void sensor_driver_check(void);
|
||||
void sensor_driver_init(u8 type, u8 enable, u16 range, u8 odr);
|
||||
void sensor_driver_run(void);
|
||||
void sensor_driver_sleep(u8 type, u8 enable);
|
||||
void sensor_driver_irq_handle(void);
|
||||
@@ -0,0 +1,88 @@
|
||||
#include "sdk_config.h"
|
||||
#include "sensor_driver.h"
|
||||
#include "includes.h"
|
||||
#include "sensor_service_wrist_tilt.h"
|
||||
|
||||
|
||||
#if CONFIG_SENSOR_DRIVER_ENABLE
|
||||
|
||||
#define LOG(fmt,...) printf("[algo] %s() " fmt "\n",__func__, ##__VA_ARGS__)
|
||||
|
||||
enum {
|
||||
MSYS_STATE_NORMAL = 0,
|
||||
MSYS_STATE_PWR_DOWN,
|
||||
MSYS_STATE_PWR_OFF,
|
||||
MSYS_STATE_SOFT_PWR_OFF,
|
||||
MSYS_STATE_SOFT_PWR_OFF_KEEP_NVRAM,
|
||||
MSYS_STATE_LIGHT_PWR_DOWN,
|
||||
};
|
||||
|
||||
#define MSYS_STATE_GET() (P11_SYSTEM->P11_SYS_CON0 & 0xf)
|
||||
|
||||
|
||||
static sensor_info_t sensor_info = {
|
||||
.type = SENSOR_ALGO_WRIST_TILT,
|
||||
.name = "JL GESTURE V1.0",
|
||||
};
|
||||
|
||||
static s8 wrist_tilt_online(void)
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static void wrist_tilt_event_response(u8 event)
|
||||
{
|
||||
static u8 p11_algo_event;
|
||||
|
||||
p11_algo_event = event;
|
||||
u8 low_power_mode = MSYS_STATE_GET() != MSYS_STATE_NORMAL;
|
||||
|
||||
if (p11_algo_event == ALGO_WRIST_DOWN && low_power_mode) {
|
||||
return;
|
||||
}
|
||||
LOG(" %d", event);
|
||||
|
||||
//发送 算法事件 给大核
|
||||
int msg[2];
|
||||
msg[0] = MSG_P11_ALGORITHM_EVENT;
|
||||
msg[1] = p11_algo_event;
|
||||
p2m_post_msg(MSG_APP, 0, (u8 *)msg, sizeof(msg));
|
||||
}
|
||||
|
||||
s8 wrist_tilt_run(void *arg, u16 *len)
|
||||
{
|
||||
axis_data_t *accel_data = arg;
|
||||
u8 accel_point = *len / sizeof(axis_data_t);
|
||||
|
||||
jl_gesture_event_t gesture_event = ALGO_NOTHING;
|
||||
|
||||
for (u8 i = 0; i < accel_point; i++) {
|
||||
gesture_event = sensor_jl_gesture_run(accel_data[i].x, accel_data[i].y, accel_data[i].z);
|
||||
if (sensor_info.state == SENSOR_STATE_OPEN && gesture_event != ALGO_NOTHING) {
|
||||
wrist_tilt_event_response(gesture_event);
|
||||
}
|
||||
// LOG("gesture=%d,xyz:%d,%d,%d",gesture_event,accel_data[i].x,accel_data[i].y,accel_data[i].z);
|
||||
}
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static s8 wrist_tilt_open(u16 range, u16 odr)
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static s8 wrist_tilt_close(void)
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
|
||||
REGISTER_SENSOR(wrist_tilt) = {
|
||||
.info = &sensor_info,
|
||||
.online = wrist_tilt_online,
|
||||
.open = wrist_tilt_open,
|
||||
.close = wrist_tilt_close,
|
||||
.run = wrist_tilt_run,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
typedef enum {
|
||||
ALGO_NOTHING, //没有相关动作
|
||||
ALGO_WRIST_UP, //抬腕动作
|
||||
ALGO_WRIST_DOWN, //落腕动作
|
||||
ALGO_DOUBLE_CLICK, //双击屏幕
|
||||
ALGO_HITTING, //击球动作
|
||||
ALGO_ON_DESK, //放置桌面
|
||||
} jl_gesture_event_t;
|
||||
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/*
|
||||
* @brief 杰理手势算法 获取版本号
|
||||
*
|
||||
* @param [out] 10~255
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
unsigned char sensor_jl_gesture_ver(void);
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/*
|
||||
* @brief 杰理手势算法 开启debug模式
|
||||
*
|
||||
* @param [in] enable 0:关闭log打印 1:开启log打印
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
void sensor_jl_gesture_debug(char enable);
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/*
|
||||
* @brief 杰理手势算法 设置抬腕算法的角度
|
||||
*
|
||||
* @param [in] angle [0]:翻腕角度,默认5 [1]:手腕与水平面的角度,默认<45
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
void sensor_jl_gesture_set_wrist_angle(char angle[2]);
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/*
|
||||
* @brief 杰理手势算法 运行接口
|
||||
*
|
||||
* @param [in] x accelerate x轴数据
|
||||
* @param [in] y accelerate y轴数据
|
||||
* @param [in] z accelerate z轴数据
|
||||
* @param [out] 算法输出,见 jl_gesture_event_t 定义
|
||||
*
|
||||
*--------------------------------------------------------------------------*/
|
||||
jl_gesture_event_t sensor_jl_gesture_run(short x, short y, short z);
|
||||
Reference in New Issue
Block a user