近期用maplab開發sam9x60,結果例程能點亮屏幕,新建工程無論如何都不行,模塊圖形化配置做的稀爛,mhc還卡的不行,待機久了甚至出現過10g內存佔用。但還好還是功能齊全的ide(雖然我還不知道類似keil那些功能在哪裏打開)。
通過調試模式發現程序卡在LCDC_WaitForSyncInProgress內部的死循環裏。
打斷點發現第一個LCDC_WaitForSyncInProgress並沒有卡住,而是卡在第二個。一開始以為是硬件圖層的時鐘配置,但我發現所有的LCDC_SetLayerClockGatingDisable都註釋之後還是卡在那。所以懷疑目光終於落在了lcd的pwm時鐘上。
直接讓ai讀代碼,給出功能解釋,在代碼量小的情況下ai還是沒問題的。
/* LCDC initialization */
//1. Configure the LCD timing parameters
LCDC_WaitForSyncInProgress();
LCDC_SetPWMClockSourceSelection(LCDC_PWM_CLOCK_SOURCE);
LCDC_SetClockDivider(PIXEL_CLOCK_DIV);
//Disable all layers for now
LCDC_SetLayerClockGatingDisable(LCDC_LAYER_BASE, false);
LCDC_SetLayerClockGatingDisable(LCDC_LAYER_OVR1, false);
LCDC_SetLayerClockGatingDisable(LCDC_LAYER_OVR2, false);
LCDC_SetLayerClockGatingDisable(LCDC_LAYER_HEO, false);
LCDC_SetLayerClockGatingDisable(LCDC_LAYER_PP, false);
LCDC_WaitForSyncInProgress();//就是卡在這。
1. LCDC_WaitForSyncInProgress()
這個函數用於等待LCD控制器的同步過程完成。在配置LCD控制器寄存器之前,需要確保沒有正在進行的同步操作,以避免配置衝突。
函數實現:
- 檢查LCDC_LCDSR寄存器中的SIPSTS位(同步正在進行狀態位)
- 當該位為0時,表示同步已完成,函數返回
- 如果同步正在進行,則等待直到完成
2. LCDC_SetPWMClockSourceSelection(LCDC_PWM_CLOCK_SOURCE)
設置LCD控制器PWM信號的時鐘源。LCDC_PWM_SOURCE_SYSTEM,表示使用系統時鐘作為PWM時鐘源
函數實現:
- 修改LCDC_LCDCFG0寄存器中的CLKPWMSEL位
- 根據參數設置選擇系統時鐘或慢速時鐘作為PWM時鐘源
3. LCDC_SetClockDivider(PIXEL_CLOCK_DIV)
設置像素時鐘分頻器,用於生成LCD面板所需的像素時鐘。
參數: PIXEL_CLOCK_DIV:在項目中定義為7
函數實現:
- 修改LCDC_LCDCFG0寄存器中的CLKDIV位
- 像素時鐘頻率 = 系統時鐘頻率 / (CLKDIV + 2)
- 因此,當PIXEL_CLOCK_DIV為7時,實際分頻值為9(7+2)
像素時鐘是LCD控制器生成的時鐘信號,用於同步像素數據的傳輸。
所以這裏的邏輯是:
- 等待LCD控制器當前的同步操作完成,確保可以安全地修改寄存器
- 設置PWM時鐘源為系統時鐘,這將用於背光控制
- 設置像素時鐘分頻器,確定LCD面板的像素時鐘頻率
這些配置是LCD正常顯示的基礎,必須在啓用LCD控制器其他功能之前正確設置。
以上都是ai分析結果,知道啥意思就好辦了,直接查這兩個函數的傳參對不對得上硬件規格。興奮得對比了例程的配置(我的硬件跟例程是一樣的),發現時鐘源/頻率/分頻全都一模一樣,一頭冷水。但好在,在對比過程中發現,例程設置的時鐘配置跟我的自建工程不一樣,你這ide,都不能自動配置好自家開發板的lcd驅動初始化的嗎??
人在生氣的時候真的會笑出來(因為已經被ide在emac初始化,工程configuration丟失,圖形化模塊編輯鏈接關係丟失,用着用着卡死發現內存泄露ide佔用10g導致爆內存。還有更多我不太記得的讓人無語的小細節諸如模塊版本更新導致例程無法打開mhc,想看例程具體配置就在mcc降低模塊版本結果兼容性崩潰被迫重裝一切,裝低版本ide結果這個例程可以打開了那個例程又不兼容,我絕望的想得到如果我想通過例程瞭解模塊配置參數那我每天都在卸載和重裝中度過。當然我很快想通ide的配置也得有個文件存儲參數,所以還是找到了。那麼可以放棄mhc了,只用ide構建,用vsc來編輯,手動添加模塊庫,結果因為只有庫沒有對應的時鐘和中斷等可以參考,我還得看手冊,不害意思不會看也沒必要如此古法開發。還是得折騰mhc直到摸清如何選對驅動參數。跟同學吐槽,同學一句話點醒我,感謝這些印度人的不靠譜,讓ai無法正確處理嵌入式開發。所以我們工作機會大大滴多啊(○| ̄|_)
這是例程的時鐘配置,注意到
{ ID_LCDC, 1, 1, 0x3, 0}了嗎?在我的自建工程裏面,他是
{ ID_LCDC, 1, 0, 0, 0}。vsc通過clang,鼠標懸停顯示了具體的參數含義,第一個1設備時鐘是否使能,後面三個0具體就是gclk是否開啓,時鐘源選第幾個,分頻係數多少。
static void initPeriphClk(void)
{
const uint8_t EOL_MARKER = ((uint8_t)ID_PERIPH_MAX + 1U);
struct {
uint8_t id;
uint8_t clken;
uint8_t gclken;
uint8_t css;
uint8_t divv;
} periphList[] =
{
{ ID_PIOA, 1, 0, 0, 0},
{ ID_PIOB, 1, 0, 0, 0},
{ ID_PIOC, 1, 0, 0, 0},
{ ID_FLEXCOM0, 1, 0, 0, 0},
{ ID_TC0, 1, 0, 0, 0},
{ ID_EMAC0, 1, 0, 0, 0},
{ ID_LCDC, 1, 1, 0x3, 0},
{ ID_GFX2D, 1, 0, 0, 0},
{ ID_PIOD, 1, 0, 0, 0},
{ ID_DBGU, 1, 0, 0, 0},
{ EOL_MARKER, 0, 0, 0, 0}//end of list marker
};
好了,配置完這個總算點亮屏幕了吧。還不行,不過經驗有了,就知道去驅動庫找配置不一樣的地方了。是的,這個ide的代碼架構是把許多初始化配置直接寫在驅動庫裏,改參數直接在lib裏面各個文件去改。
最後因為lvgl本身不支持24位色深,而添加模塊時候會因為PDA-TM5000 可以超頻到24位而自動填寫,這裏跟點亮與否無關,實測只是會顯示異常。同理還有顏色模式雖然支持rgba8888,但是lvgl不支持24位的rgba8888,所以也得改成rgb565.接下來還有重頭戲,mhc支持rtos模塊化添加(雖然是加到一個third_party文件夾裏),但是實測直接添加rtos會導致中斷異常。很容易跑進架構自帶的中斷異常死循環裏。
檢查發現,在FreeRTOS的移植代碼portASM.S中,定義了處理SWI指令的函數:
.type FreeRTOS_SWI_Handler, %function
FreeRTOS_SWI_Handler:
FreeRTOS的portmacro.h文件中定義了portYIELD()宏
#define portYIELD() __asm volatile ( "SWI 0" ); 在系統啓動彙編代碼cstartup.S中,異常向量表定義了軟件中斷處理函數,這是默認配置。
/* Software Interrupt */
ldr pc, =software_interrupt_irq_handler
/* Interrupt */
ldr pc, =IRQ_Handler
需要改成
/* Software Interrupt */
ldr pc, =FreeRTOS_SWI_Handler
/* Interrupt */
ldr pc, =FreeRTOS_IRQ_Handler
改完調試仍然跳轉到未定義中斷循環。ε=( o`ω′)ノ
再檢查一下,呼。別怕,這是因為調試器自動把cstartup.S裏的中斷配置又改默認了。
重新改好直接構建下載就能點亮屏幕觸摸正常。
也就是説用了freertos就沒法調試了,除非我改在freertos讓它可以使用默認中斷,但是微芯廠商在添加rtos到mhc的時候怎麼不做好適配。。他們自己是沒有用過調試功能嗎?(印度加爾各答的開發人員,估計真沒調試)
也就是説以後用了rtos還想要調試,我還得自己修改rtos?有這精力,我為什麼不把這個開發板的rtt studio硬件支持包做出來,用rtt來跑業務。。至少rtt的lvgl和tcp等都有了,不需要再費勁巴拉的適配。(事實上我已經買了 RA6M4-HMI開發板了,rtt 與瑞薩的聯合產品,到手半小時點亮例程,讓qwen隨手改改ui就是新東西。就是瑞薩的框架沒那麼精簡,但人家的硬件配置也高,不用這麼扣扣嗖嗖)