Page 1 of 1

注意:inline关键字被优化导致此类函数被布局在flash内

Posted: Thu Jun 10, 2021 4:07 am
by QQ26750452
在编写同时使用uart和ota的程序中,发现进入串口中断后导致panic,提示如下:
Guru Meditation Error: Core 0 panic'ed (Cache disabled but cached memory region accessed).

Core 0 register dump:
PC : 0x4010b324 PS : 0x00060034 A0 : 0x40082611 A1 : 0x3ffb0660
A2 : 0x3ffc6904 A3 : 0x3ffb18a8 A4 : 0x3ffb18a4 A5 : 0x00000001
A6 : 0x00000001 A7 : 0x00004000 A8 : 0x80085b19 A9 : 0x00000008
A10 : 0x3ff50000 A11 : 0x00000000 A12 : 0x00000000 A13 : 0x3ffb0650
A14 : 0x3ffb2358 A15 : 0x00000008 SAR : 0x00000020 EXCCAUSE: 0x00000007
EXCVADDR: 0x00000000 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff

Backtrace:0x4010b321:0x3ffb0660 0x4008260e:0x3ffb06c0 0x0004001e:0x00000000 |<-CORRUPTED
经过一顿凶猛的排错分析,是因为uart的中断函数uart_rx_intr_handler_default内调用uart_hal_is_tx_idle宏导致的。
uart_hal_is_tx_idle宏是uart_ll_is_tx_idle的别名,而uart_ll_is_tx_idle定义如下:

Code: Select all

static inline bool uart_ll_is_tx_idle(uart_dev_t *hw)
{
    typeof(hw->status) status = hw->status;
    return ((status.txfifo_cnt == 0) && (status.st_utx_out == 0));
}
由于uart.c多处调用这个函数,所以编译器自作聪明地把它编译成了非内联函数(意图是减少代码占用?),且elf能找到uart_ll_is_tx_idle标号。uart_ll_is_tx_idle函数被安排在默认的flash地址,最终导致了运行时panic。
我的临时解决方法是,在uart.c文件里加入如下声明:

Code: Select all

static inline bool uart_ll_is_tx_idle(uart_dev_t *hw) __attribute((always_inline));
如此以来uart_ll_is_tx_idle不会被编译为非内联函数,经测试问题解决。
但是,希望乐鑫官方把idf内源码中的inline关键词都替换为__attribute((always_inline)),因为inline关键字不可靠!
期待下次idf版本更新能解决此bug,自己修改idf源码真的是权宜之计、临时之策。
2021-06-10_120449.png
elf标号
2021-06-10_120449.png (88.87 KiB) Viewed 172 times
2021-06-10_120047.png
异常截图
2021-06-10_120047.png (31.97 KiB) Viewed 172 times
2021-06-10_120301.png
相关文件
2021-06-10_120301.png (77.56 KiB) Viewed 172 times

Re: 注意:inline关键字被优化导致此类函数被布局在flash内

Posted: Thu Jun 10, 2021 2:35 pm
by ESP_Sprite
Moving this to the Chinese forum.