This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
+11
View File
@@ -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
}
+50
View File
@@ -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
+407
View File
@@ -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);
}
+390
View File
@@ -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.
+185
View File
@@ -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.
@@ -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);
}
+40
View File
@@ -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();
}
+213
View File
@@ -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
/*-----------------------------------------------------------*/
+30
View File
@@ -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) */
+221
View File
@@ -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 val1, 收到对应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);
+27
View File
@@ -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
+349
View File
@@ -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, &register_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, &register_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, &register_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, &register_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, &register_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, &reg_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, &reg_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
+179
View File
@@ -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, &register_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, &register_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
+92
View File
@@ -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);