【已解决】IO中断问题

蓝牙 BLE设备、蓝牙 MESH设备、蓝牙 Beacon设备、Sub-G设备等


Post Reply
wt呃呃
Posts: 124

请问一下,我使用tuya-ble-sdk-demo-project-tlsr8253 这份SDK,有IO中断的例程吗?我现在遇到的问题是io中断没有进入中断函数(irq_handler)

jinyuan
Posts: 55

Re: IO中断问题

telink的中断只有一个入口 ,这个入口在main.c中的 void irq_handler(void)函数中。IO口配置为中断后,当中断触发时,首先进入这个函数,然后通过判断标志位来确定是否有GPIO IO中断: if (reg_irq_src & FLD_IRQ_GPIO_EN) , 由于无法区分是哪个GPIO 触发的中断, 在中断处理中还需要读一下IO的电平状态来确定是否是目标GPIO IO触发中断。
例子:
1、通过vscode 的wind ide 插件拉下涂鸦OS版本的telink ble sdk, 里面的按键组件同时用到了中断和唤醒。可供参考
2、这里简单用伪码描述下

Code: Select all

_attribute_ram_code_ void irq_handler(void)
{
	// ble 协议栈的处理函数必须在中断的最上层
	irq_blt_sdk_handler ();

    if (reg_irq_src & FLD_IRQ_GPIO_EN)
    {
        reg_irq_src |= FLD_IRQ_GPIO_EN;
        // irq handler
    }
}

void ty_gpio_input_irq_init(void)
{
	gpio_set_func(GPIO_PC0, AS_GPIO);
	gpio_set_output_en(GPIO_PC0, 0);
	gpio_set_input_en(GPIO_PC0, 1);
#ifdef  HIGH_ACTIVE
        gpio_setup_up_down_resistor(GPIO_PC0, PM_PIN_PULLDOWN_100K);
        gpio_set_interrupt_pol(GPIO_PC0, POL_RISING);
        gpio_en_interrupt(GPIO_PC0, 0); //disable the pin's irq
        cpu_set_gpio_wakeup(GPIO_PC0, Level_High, 1);//wakeup enable
#else
        gpio_setup_up_down_resistor(GPIO_PC0, PM_PIN_PULLUP_10K);
        gpio_set_interrupt_pol(GPIO_PC0, POL_FALLING);
        gpio_en_interrupt(GPIO_PC0, 0);
        cpu_set_gpio_wakeup(GPIO_PC0, Level_Low, 1);
#endif
        
reg_gpio_wakeup_irq |= FLD_GPIO_CORE_INTERRUPT_EN; irq_clr_src(); //清除所有中断标志位 reg_irq_mask |= FLD_IRQ_GPIO_EN; // 使能中断 gpio_en_interrupt(GPIO_PC0, 1); }

注意 ,当时设备进入深度休眠后 ,每次唤醒都需要将IO再次初始化

wt呃呃
Posts: 124

Re: IO中断问题

安装给的例程,我添加上去了,不行,io是低电平有效,哪里还需要修改的吗?

Code: Select all

_attribute_ram_code_ void irq_handler(void)
{
	// ble 协议栈的处理函数必须在中断的最上层
	irq_blt_sdk_handler ();

#if (HCI_ACCESS==HCI_USE_UART)
	unsigned char irqS = dma_chn_irq_status_get();
    if(irqS & FLD_DMA_CHN_UART_RX)	//rx
    {
    	dma_chn_irq_status_clr(FLD_DMA_CHN_UART_RX);

	u8* w = spp_rx_fifo.p + (spp_rx_fifo.wptr & (spp_rx_fifo.num-1)) * spp_rx_fifo.size;
	if(w[0]!=0)
	{
		my_fifo_next(&spp_rx_fifo);
		u8* p = spp_rx_fifo.p + (spp_rx_fifo.wptr & (spp_rx_fifo.num-1)) * spp_rx_fifo.size;
		reg_dma_uart_rx_addr = (u16)((u32)p);  //switch uart RX dma address
	}
}

if(irqS & FLD_DMA_CHN_UART_TX)	//tx
{
	dma_chn_irq_status_clr(FLD_DMA_CHN_UART_TX);
}
#endif

if (reg_irq_src & FLD_IRQ_GPIO_EN)
{
    reg_irq_src |= FLD_IRQ_GPIO_EN;
    // irq handler
    user_key_irq_handler();
}

static void ty_gpio_input_irq_init(void)
{

gpio_set_func(KEY_PIN, AS_GPIO);
gpio_set_output_en(KEY_PIN, 0);
gpio_set_input_en(KEY_PIN, 1);
#ifdef  HIGH_ACTIVE
        gpio_setup_up_down_resistor(KEY_PIN, PM_PIN_PULLDOWN_100K);
        gpio_set_interrupt_pol(KEY_PIN, POL_RISING);
        gpio_en_interrupt(KEY_PIN, 0); //disable the pin's irq
        cpu_set_gpio_wakeup(KEY_PIN, Level_High, 1);//wakeup enable
#else
        gpio_setup_up_down_resistor(KEY_PIN, PM_PIN_PULLUP_10K);
        gpio_set_interrupt_pol(KEY_PIN, POL_FALLING);
        gpio_en_interrupt(KEY_PIN, 0);
        cpu_set_gpio_wakeup(KEY_PIN, Level_Low, 1);
#endif
        
reg_gpio_wakeup_irq |= FLD_GPIO_CORE_INTERRUPT_EN; irq_clr_src(); //清除所有中断标志位 reg_irq_mask |= FLD_IRQ_GPIO_EN; // 使能中断 gpio_en_interrupt(KEY_PIN, 1); } } void user_key_init(void) { /* key gpio init */ //ty_pin_init(KEY_PIN, TY_PIN_MODE_IN_PU); ty_gpio_input_irq_init(); } void user_key_irq_handler(void) { //TUYA_APP_LOG_DEBUG("======>key irq."); user_key_start_timer(); }
wt呃呃
Posts: 124

Re: IO中断问题

ty_system_enter_suspend();调用了这个进入sleep,有影响吗?

jinyuan
Posts: 55

Re: IO中断问题

首先 ,不调用 ty_system_enter_suspend ,即让芯片保持唤醒状态, 看看中断有无效果。
如果确定中断有效,那你需要在芯片每次唤醒的时候都初始化一下GPIO。唤醒后芯片会跑到 user_init_deepRetn 这个函数 , 在这个函数的最下面添加 user_key_init();

wt呃呃
Posts: 124

Re: IO中断问题

可以了。再请教一下另外一个问题,调用了ty_system_enter_suspend,唤醒之后要调用这个函数 ty_system_exit_suspend 吗?

jinyuan
Posts: 55

Re: IO中断问题

不需要。
这两个函数其实就是对休眠标志位的置1和清0,底层通过判断这个标志位来确定是否允许进入休眠。
ty_system_enter_suspend 执行之后并打开蓝牙广播/蓝牙连接,底层就会以蓝牙广播/蓝牙连接的interval来确定休眠唤醒周期。如果有定时器 ,就会综合定时器timeout时间和蓝牙广播/蓝牙连接interval时间来确定休眠唤醒周期。

wt呃呃
Posts: 124

Re: IO中断问题

通过验证,创建一个1000ms的定时器, 进入睡眠,会一直进入 user_init_deepRetn 这个函数,那一直初始化,会不会出现其他问题?

Code: Select all

_attribute_ram_code_ void user_init_deepRetn(void)
{
	blc_ll_initBasicMCU();   //mandatory
	ty_ble_set_tx_power(RF_POWER_P3p01dBm);

blc_ll_recoverDeepRetention();

extern  int sdk_mainLoop_run_flag;
sdk_mainLoop_run_flag = 0;
extern  u8 blt_dma_tx_rptr;
blt_dma_tx_rptr = 0;

irq_enable();

////////////////// SPP initialization ///////////////////////////////////
//note: dma addr must be set first before any other uart initialization!
ty_uart_init();

ty_pin_init(0,0);

blt_soft_timer_init();

extern void user_dev_exit_sleep(void);
user_dev_exit_sleep();
}

void user_dev_exit_sleep(void)
{
	//ty_system_exit_suspend();
	//TUYA_APP_LOG_DEBUG("======>exit sleep");
	//user_set_enter_sleep_t(2);
	user_key_init();
	user_led_init();
}
jinyuan
Posts: 55

Re: IO中断问题

wt呃呃 2023年 Mar 21日 16:07

通过验证,创建一个1000ms的定时器, 进入睡眠,会一直进入 user_init_deepRetn 这个函数,那一直初始化,会不会出现其他问题?

Code: Select all

_attribute_ram_code_ void user_init_deepRetn(void)
{
	blc_ll_initBasicMCU();   //mandatory
	ty_ble_set_tx_power(RF_POWER_P3p01dBm);

blc_ll_recoverDeepRetention();

extern  int sdk_mainLoop_run_flag;
sdk_mainLoop_run_flag = 0;
extern  u8 blt_dma_tx_rptr;
blt_dma_tx_rptr = 0;

irq_enable();

////////////////// SPP initialization ///////////////////////////////////
//note: dma addr must be set first before any other uart initialization!
ty_uart_init();

ty_pin_init(0,0);

blt_soft_timer_init();

extern void user_dev_exit_sleep(void);
user_dev_exit_sleep();
}

void user_dev_exit_sleep(void)
{
	//ty_system_exit_suspend();
	//TUYA_APP_LOG_DEBUG("======>exit sleep");
	//user_set_enter_sleep_t(2);
	user_key_init();
	user_led_init();
}

这里的初始化有两个地方需要注意:
1、芯片执行了这个函数,说明是从deepsleep状态唤醒。当芯片进入deepsleep后,所有芯片内部外设都会掉电(包括uart iic spi gpio等)所以唤醒后 ,这部分的初始化需要再执行一遍。
2、芯片休眠后,虽然芯片内部外设掉电, 但是sram都还保持着,所以纯软件的东西不需要再初始化(包括软件定时器的创建,各种变量参数等)

Post Reply