【MIPS】MT7620DA问题汇总

更啊更,新啊新,不止不熄...


目录

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_devicehw_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的性质。

  2hw_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");

验证:

  

 

 

 

 

 

 结果:与猜想一样,已解决;

 

 

 

 

---------------------------------------

 问题1c程序执行一个空指针,会发生什么?例如:

struct font_desc  *font;

unsigned char *pdata = (unsigned char *)font->data;

答:程序直接挂在此处了。

问题2

Const unsigned ch = 32;

unsigned char char = ch - 32; //编译错误!只读变量?

答:因为char和宏或者字符类型char冲突了!

---------------------------------------

posted @ 2019-12-09 10:32  大秦长剑  阅读(1563)  评论(0编辑  收藏  举报