更啊更,新啊新,不止不熄...
目錄
1.問題:編譯錯誤parse error before '=' token
2.問題:MT7620A無線芯片——普通GPIO操作
3.問題:MT7620A無線芯片——復用功能引腳轉GPIO操作
4.APP/RESCUE校驗的困惑
5.矩陣按鍵短路測試字體顯示遮蓋問題
6. xx10設備單板二次測試LCD字符串顯示擠到一行問題
7、問題:FIP10字符串打印,當字符串超過16個字符時,其尾巴會覆蓋該行的首端。為什么?
8、問題:getnev()得到的hw_device設備號在產測過程中有幾率被不相干的代碼修改,為什么?LCD顯示亂序之徹底解決
1.問題:編譯錯誤parse error before '=' token
nand_lcd_notdma.c:
1071: error: parse error before '=' token
1072: error: parse error before "char"
錯誤源碼:
unsigned char char = ch;
查網上:
一個*.c文件中,在一行中定義:
int data[5];
編譯報錯:
parse error before '[' token;
data是非常平常的一個變量,為什么會報錯呢?
如果改為data_, data1, data2.... 就沒有問題。
編譯器錯誤???當然不是,還是程序本身的問題
在一個包含的頭文件中定義了一行:
#define data
這就是錯誤的關鍵,花了一天時間才發現這個問題。。。。
2.問題:MT7620A無線芯片——普通GPIO操作
I.基礎操作
2.1設置引腳為輸出模式:
*(volatile u32 *)(RALINK_REG_PIO7140DIR) |= (0x3F << 20); /* set GPIO 65 -- 60 to output; 1=output, 0=input */
2.2設置引腳為輸入模式:
*(volatile u32 *)(RALINK_REG_PIO7140DIR) &= ~(0x3F << 20); /* set GPIO 65 -- 60 to input; 1=output, 0=input */
2.3讀數據(主要用作輸入引腳時使用,輸出引腳也可使用)
u32_var = *(volatile u32 *)(RALINK_REG_PIO7140DATA);
2.4寫數據(用作輸出引腳)
1>輸出引腳寫入數據1,輸出高電平:
*(volatile u32 *)(RALINK_REG_PIO7140SET) |= (1<< (20 + i)); /* 把行GPIO(60 + i)輸出引腳拉高(即置1)*/
2>輸出引腳寫入數據0,輸出低電平:
*(volatile u32 *)(RALINK_REG_PIO7140RESET) |= (0x3F << 20); /* GPIO 65 -- 60 清零 */
------------------------------------------------
----------------------------------------------
II.項目使用
問題:矩陣按鍵行(實際工作用作輸出引腳,矩陣6行6列)短路/開路測試,從ROW0-5依次配置測試行引腳為輸出引腳,其他行引腳為輸入引腳,然后正常測試 / 短路測試,檢測其他行的電平狀況。 理論結果:其他行電平在正常測試時為低電平,短路測試時為高電平。 實際結果:其他行電平在正常測試時依然有高電平/低電平,且每次讀並不總是一樣。短路測試時為高電平,正常。
問題分析與解決:
*(volatile u32 *)(RALINK_REG_PIO7140DIR) |= (0x3F << 20); /*a.清零所有列數據寄存器*/
*(volatile u32 *)(RALINK_REG_PIO7140RESET) |= (0x3F << 20);
*(volatile u32 *)(RALINK_REG_PIO7140DIR) &= ~(0x3F << 20); /*b.set GPIO 65 -- 60 to input; 1=output, 0=input */
*(volatile u32 *)(RALINK_REG_PIO7140DIR) |= (1<< (20 + i)); /*c.測試GPIO(60 + i)輸出*/
*(volatile u32 *)(RALINK_REG_PIO7140SET) |= (1<< (20 + i)); /*d.把測試列GPIO(60 + i)輸出引腳拉高*/
udelay(10000); //打印亂了,好幾個引腳顯示高電平,且每次讀DATA寄存器,值都不一樣;
//udelay(0); //屏蔽延時,與測試行短接的行引腳,但是DATA寄存器輸入引腳的相應位,檢測不到高電平;
udelay(200); //該時間可以讀取到正常的數據,也可以檢測到短路;
u32_var = (*(volatile u32 *)(RALINK_REG_PIO7140DATA)) >> 20; /*e.讀GPIO65-60 列其他輸入引腳數據 */
u32_var &= 0x3f;
printf("KEY_ROWS TEST3: u32_var = 0x%x\n", u32_var);
說明:
1.根據數據手冊,操作時需要進行“位寫”操作的寄存器:
RALINK_REG_GPIO_xx_DIR //set GPIO_xx to: 1=output, 0=input */
2.不需要進行“位寫”操作的寄存器:
RALINK_REG_GPIO_xx_SET //0=無影響; 1=把輸出引腳GPIODATA寄存器對應位拉高;
RALINK_REG_GPIO_xx_RESET //0=無影響; 1=把輸出引腳GPIODATA對應位清零;
RALINK_REG_GPIO_xx_TOG //0=無影響; 1=反轉輸出引腳GPIODATA對應位;
這類寄存器,應使用直接賦值操作。
3.不需要寫操作,只需要“讀”操作的寄存器:
RALINK_REG_GPIO_xx_DATA
現象:
KEY_ROWS TEST3: u32_var = 0x19 = 0b011001;
分析:手動短路鍵盤引腳,理論只應該出現兩個高電平引腳,即測試拉高引腳和與測試引腳手動短路的引腳。但現象並不是如此。
操作:短接行4-5(共有行0-5)。
猜測1:應該是RALINK_REG_GPIO_xx_SET寄存器使用位操作時,之前操作的位仍保留了高電平。
但是RALINK_REG_PIO7140SET修改前
源碼:
*(volatile u32 *)(RALINK_REG_PIO7140SET) |= (1<< (26 + i)); /*d.把測試行GPIO(66 + i)輸出引腳拉高*/
udelay(10000);
u32_var = *(volatile u32 *)(RALINK_REG_PIO7140SET);
//==================================
printf("KEY_ROWS TEST3: RALINK_REG_PIO7140SET = 0x%x\n", u32_var); //u32_var = 0x19 = 0b011001;
//==================================
u32_var = (*(volatile u32 *)(RALINK_REG_PIO7140DATA) >> 26); /*e.讀GPIO71-66 行其他輸入引腳數據 */
u32_var &= 0x3f;
//==================================
printf("KEY_ROWS TEST3: RALINK_REG_PIO7140DATA = 0x%x\n", u32_var);
//==================================
打印:
KEY_ROWS TEST3: RALINK_REG_PIO7140SET = 0x0
KEY_ROWS TEST3: RALINK_REG_PIO7140DATA = 0x31=0b0011 0001;
修改后源碼:
*(volatile u32 *)(RALINK_REG_PIO7140SET) = (1<< (26 + i)); /*d.把測試行GPIO(66 + i)輸出引腳拉高*/
udelay(10000);
u32_var = *(volatile u32 *)(RALINK_REG_PIO7140SET);
//==================================
printf("KEY_ROWS TEST3: RALINK_REG_PIO7140SET = 0x%x\n", u32_var); //u32_var = 0x19 = 0b011001;
//==================================
打印:
KEY_ROWS TEST3: RALINK_REG_PIO7140SET = 0x0
KEY_ROWS TEST3: RALINK_REG_PIO7140DATA = 0x31=0b0011 0001;
答:RALINK_REG_GPIO_xx_SET並無保存之前的值,是因為其在作用完RALINK_REG_GPIO_XX_DATA后就自動歸回默認值0x0了嗎?不知,但是其並未影響程序。
猜測2:手動短路時,手接觸鑷子,手上帶有電。
答:手不接觸鑷子時,短路,測試必報短路,萬用表測電平:
ROW_4/5 與其他引腳電平一樣,都是0.8V左右;
手接觸鑷子時,短路,測試必報短路,萬用表測電平:
ROW_4/5 與其他引腳電平不一樣,是1.5V左右;其他引腳仍然0.8V左右;
測試3:把所有行后設置為輸入引腳,短接ROW4-5,查看RALINK_REG_GPIO_XX_DATA寄存器的打印結果
答:
//*(volatile u32 *)(RALINK_REG_PIO7140DIR) |= (1<< (26 + i));
KEY_ROWS TEST1: RALINK_REG_PIO7140DATA = 0x0
KEY_ROWS TEST2: RALINK_REG_PIO7140DATA = 0x0
KEY_ROWS TEST3: RALINK_REG_PIO7140SET = 0x0
KEY_ROWS TEST3: RALINK_REG_PIO7140DATA = 0x30 //0b0011 0000;
Keypad Test: row: 0-4
//*(volatile u32 *)(RALINK_REG_PIO7140SET) = (1<< (26 + i)); /*d.把測試行GPIO(66 + i)輸出引腳拉高*/
....
KEY_ROWS TEST3: RALINK_REG_PIO7140SET = 0x0
KEY_ROWS TEST3: RALINK_REG_PIO7140DATA = 0x30 //0b0011 0000;
Keypad Test: row: 2-4
猜測4:專業用於輸入引腳的列引腳接下拉電阻到地,為什么?這個是造成行全配置為輸入引腳時會讀到高電平的原因所在嗎?
總結:因為行引腳未接上拉/下拉電阻到電源/地,引腳懸空。因此,需要在寄存器配置之后,立刻讀DATA寄存器的值,如此可得到正確的值。
但又因為RALINK_REG_PIO7140SET寄存器置1后稍微一段時間后,才能在RALINK_REG_PIO7140DATA寄存器讀到該位的相應數據位置1,因此應該在
RALINK_REG_PIO7140SET寄存器置1后添加延時delay(200)或(100)。
說明:當一個數字芯片的輸入引腳處於懸空狀態時,是輸入高電平還是低電平。我認為這個問題答案不確定。這個要看引腳內部結構。有些引腳內部有上拉電阻,
懸空時肯定是輸入高電平。有些引腳內部有下拉電阻,懸空時肯定輸入低電平。對於那些開漏的引腳,電平應該不確定的。
3.問題:MT7620A無線芯片——復用功能引腳轉GPIO操作
---------------------------------------
4.APP/RESCUE校驗的困惑
問題1:人為改變APP校驗值app_checksum,保持rescue_checksum不變,啟動系統,串口顯示APP分區校驗"FAIL", RESCUE分區校驗“OK”。
問:系統從哪里啟動?即bootm地址?
問題2:若app_checksum,rescue_checksum環境參數都不存在,或者其一不存在,系統從哪里啟動?即bootm地址?
---------------------------------------
5.矩陣按鍵短路測試問題
問題:矩陣電話機鍵盤進行按鍵開路測試時,需要在LCD屏上列舉所有按鍵的鍵號,未檢測時初始狀態為藍色,檢測到按鍵轉為綠色。
發現問題:整機按鍵操作顯示,刷新時,后顯示的會覆蓋下一行先顯示的上半部1/3.
源碼梳理:
Nand_lcd_notdma.c (uboot_fip13\e3call\linux_drv\fvdd) 49377 2019/12/10
void lcd_set_line(u16 linex, u16 xpos)
{
cur_pos_x = xpos;
//cur_pos_y = linex * y_max_px +3; //修改前源碼; 會造成后面顯示的會覆蓋下一行前面顯示的上半部1/3;
cur_pos_y = linex * font_chosen->height + 3; //修改后源碼:已解決bug/* FIP13/14: font_12x22[]: 行高度22,字體顯示區上邊框3pixel*/;
printf("\n\nlcd_set_line: y_max_px = %d\n\n", y_max_px); //串口打印:lcd_set_line: y_max_px = 16;
}
Ftchar_dummy.c (uboot_fip13\e3call) 30773 2019/12/2
const u16 x_pixels = 24;
const u16 y_pixels = 24;
const u16 x_max_px = 26;
const u16 y_max_px = 26;
Ftchar.c (uboot_fip13\e3call) 28070 2019/12/2
const u16 x_pixels = 15;
const u16 y_pixels = 15;
const u16 x_max_px = 16;
const u16 y_max_px = 16;
e3call/Makefile:
OBJS = test.o net_e3c.o arch.o cid.o custom_test.o ftchar.o ft_utils.o font_ascii_8x16.o font_sun12x22.o fonts.o
Font_sun12x22.c (uboot_fip13\e3call) 69169 2019/12/3
每個數字的的12x22字符位圖的最上一行像素,最下6行像素都是空白; 真正點陣位圖只有15像素高度;
總結:
1.ftchar.o編譯在前,y_max_px變量取用ftchar.o文件,ft_utils.o文件無用,該文件已經沒有作用了;
2.lcd_set_line()在定位按鍵數組時,對每一行的設定寬度是y_max_px=16時,由於LCD屏的像素刷新方向是從左到右,從上到下。因此第一次刷全屏時,
第n+1行數字必將覆蓋第n行數字的最下(22-y_max_px=6)行像素,所有數字呈現到LCD屏的的位圖確實完整無損。但是,當進行無序按鍵操作時,LCD屏幕中
的數字重新刷新時,若第n行數字先於第n+1行刷新時,第n行數字必將覆蓋第n+1行數字的最上(22-y_max_px=6)行像素,因此造成其下的數字的上半部基本
被覆蓋。若第n+1行數字先於第n行刷新時,則仍不會造成顯示呈現缺損問題。
忽然發現,曾經以為的實惠可用,在同層人眼中,已經是被淘汰的對象了,呵,唉,品味啊,變吧,改換優先級吧。
---------------------------------------
6.10單板二次測試LCD字符串顯示擠到一行問題
說明:FIP10設備單板測試時用FIP11C的彩色液晶屏,整機測試時用其本身的單色屏,程序根據設備號hw_device在啟動階段初始化不同的LCD。
即切換屏時,程序會先切換設備號。
當第一次單板測試結束后,仍保留按鍵短接線,
FIP10二次單板測試時,LCD測試項顯示擠到一行了。
源碼梳理:
fip1x_test
hw_device=getenv("hw_device"); /* 1.get the device name */
#ifdef FIP10
if((!strncmp(hw_device, "FIP10", 5)) && (testmode == '1')) /* 判斷是否重復測試*/
{
setenv("hw_device", "FIP11C");
saveenv();
do_reset(NULL, 0, 0, NULL);
}
#endif
##hw_device = getenv("hw_device"); /* 2.更新hw_device,添加后測試 */
if (testmode == '1') /* FIP10/FIP11C單板測試均用彩屏 */
{
set_test_mask(); /* 2.設置MFR_MASK;*/
get_test_information(testmode);
fip1x_b_test(); /* 3.測試板塊:1=單板測試 */
save_test_information(testmode); /* 4.設置單板測試信息結果 */
#ifdef FIP10
set_hw_device_to_default("FIP10"); /* 5.設置設備系統型號hw_device=FIP10 ;*/
#endif
while (1);
}
display_test_info()等顯示函數;
分析:由於首次單板測試結束時,FIP10設備號會被set_hw_device_to_default()改回"FIP10","#ifdef FIP10"判斷成功執行setenv("hw_device", "FIP11C")
會重新更改hw_device到FIP11C以進行用彩屏單板測試。而重新進入(testmode == '1')單板測試模式時,雖然flash中的設備號hw_device已經改過來了,但
是該文件中的靜態全局變量hw_device並未在進入單板測試前從"FIP10"改回到“FIP11C”。靜態全局變量hw_device為"FIP10"或"FIP11C"在單板測試執行過程的
唯一區別在於:display_test_info()類函數。
因此,造成問題:lcd_init()正常,logo也正常顯示,但是進入單板測試時字體行排列按照FIP10執行,所有測試項將都擠到第二行。而重新啟動/復位,則
會在fip1x_test()開頭處重新更新靜態全局變量hw_device為"FIP11C",顯示正常。
---------------------------------------
7、問題:FIP10字符串打印,當字符串超過16個字符時,其尾巴會覆蓋該行的首端。為什么?
答:
---------------------------------------
8、問題:getnev()得到的hw_device設備號在產測過程中有幾率被不相干的代碼修改,為什么?LCD顯示亂序之徹底解決
現象:檢驗xx_10設備單板測試時,設備號hw_device及其在測試中作為判斷條件時,實現xx_10設備單板測試時用彩屏仍顯示正常,解決顯示擠到一行的問題。
bug定位:
save_unit_test_information
char size[16]="";
sprintf(size, "0x%08x", MFR_TEST);
//=================
printf("save_unit_test_information1.2: size = %s\n", size);
printf("save_unit_test_information1.2: MFR_TEST = %x\n", MFR_TEST);
printf("save_unit_test_information1.2: hw_device = %s\n", hw_device); //hw_device = xx_11C
//===============
setenv("MFR_TEST", size); //hw_device靜態變量在此被改變了;
//=================
printf("save_unit_test_information2: size = %s\n", size);
printf("save_unit_test_information2: MFR_TEST = %x\n", MFR_TEST);
printf("save_unit_test_information2: hw_device = %s\n", hw_device); //打印:hw_device = stdout=serial
printf("save_unit_test_information2: &hw_device = 0x%x\n", &hw_device); //打印:hw_device = stdout=serial
printf("save_unit_test_information2: &size = 0x%x\n", &size);
//=============
saveenv();
綜述:
之前的set_test_mask( )之后hw_device亂序的問題也是這個原因嗎?雖然是#ifdef FIP10前后的邏輯有疏漏,但是在該函數讀出的hw_device也是這個問題( = stdout=serial),為什么?
猜想1:是因為hw_device指針指向的字符串的所在內存空間被程序收回從新使用,從而導致數據出錯嗎?
猜想2:使用hw_device和hw_device[32]的使用場合區別?
答1:現在看是的,探討static volatile char* hw_device = NULL;改為static volatile char hw_device[32] = "";的可行性。
hw_device的所有使用情景:
- static volatile char* hw_device = NULL;
- if(!strncmp(hw_device, "FIP11C", 6) )
- hw_device=getenv("hw_device"); /* get the device name in /etc_ro/dev.conf */
- printf("fip1x_test: hw_device = %s\n", hw_device);
- setenv("hw_device", dev_name);
因此,hw_device[32]具備可替換hw_device的性質。
答2:hw_device[32]適用於所有場合,hw_device則只適用於短暫存儲字符串並立馬使用且后續不在使用的場合;
static volatile char hw_device[32] = ""; //舊方式:static volatile char *hw_device=NULL;
strcpy(hw_device, getenv("hw_device")); //hw_device=getenv("hw_device");
#ifdef FIP10
#endif
strcpy(hw_device, getenv("hw_device")); //hw_device = getenv("hw_device");
驗證:
結果:與猜想一樣,已解決;
---------------------------------------
問題1:c程序執行一個空指針,會發生什么?例如:
struct font_desc *font;
unsigned char *pdata = (unsigned char *)font->data;
答:程序直接掛在此處了。
問題2:
Const unsigned ch = 32;
unsigned char char = ch - 32; //編譯錯誤!只讀變量?
答:因為char和宏或者字符類型char沖突了!
---------------------------------------