面对自己设计的新板子,基于freesclae的I.MX51 SOC,如果采购仿真器的话,据说连软件带硬件要7000美金,这实在是一笔不小的开销。但是,板子总是需要使用软件方法来测试的,特别是IO的基本功能。那么在u-boot下写一些有关的测试程序是很有必要的。虽然这个方法无法和仿真器相比,但是只要板子boot起来,那么使用底层的IO函数,进行适当的“裸奔”,对设计者来说,总算是有点“招”了。
本文编写了一个gpio_ctrl程序,在u-boot启动后的命令行运行,直接对SOC的GPIO端口进行高低电平测试。实际就是对u-boot 的命令进行一次自己需要性的扩展。具体做的方法如下:
1、添加命令标志CONFIG_CMD_GPIOCTRL
打开u-boot/include/config_cmd_default.h
添加:
#define CONFIG_CMD_GPIOCTRL
2、编写代码
在u-boot/commom目录下,建立一个gpio_ctrl.c空文件,并编写代码:
#include
#include
#include
#include
#include
#include
struct gpio_out_list {
char strPinName[20];
int nGroup;
int bit;
unsigned int PIN;
};
static struct gpio_out_list gpio_list[] = {
{"EIM_D17",2,1,MX51_PIN_EIM_D17},
{"EIM_D18",2,2,MX51_PIN_EIM_D18},
{"EIM_D22",2,6,MX51_PIN_EIM_D22},
{"EIM_A16",2,10,MX51_PIN_EIM_A16},
{"EIM_A18",2,12,MX51_PIN_EIM_A18},
{"EIM_A20",2,14,MX51_PIN_EIM_A20},
{"EIM_A21",2,15,MX51_PIN_EIM_A21},
{"EIM_A22",2,16,MX51_PIN_EIM_A22},
{"EIM_A23",2,17,MX51_PIN_EIM_A23},
{"EIM_A24",2,18,MX51_PIN_EIM_A24},
{"EIM_A25",2,19,MX51_PIN_EIM_A25},
{"EIM_A26",2,20,MX51_PIN_EIM_A26},
{"EIM_A27",2,21,MX51_PIN_EIM_A27},
{"EIM_CS1",2,26,MX51_PIN_EIM_CS1},
{"EIM_OE",2,24,MX51_PIN_EIM_OE},
{"EIM_DTACK",2,31,MX51_PIN_EIM_DTACK},
{"NANDF_RB1",3,9,MX51_PIN_NANDF_RB1},
{"NANDF_CS0",3,16,MX51_PIN_NANDF_CS0},
{"NANDF_CS1",3,17,MX51_PIN_NANDF_CS1},
{"NANDF_D0",4,8,MX51_PIN_NANDF_D0},
{"NANDF_D1",4,7,MX51_PIN_NANDF_D1},
{"NANDF_D3",4,5,MX51_PIN_NANDF_D3},
{"NANDF_D4",4,4,MX51_PIN_NANDF_D4},
{"NANDF_D5",4,3,MX51_PIN_NANDF_D5},
{"NANDF_D6",4,2,MX51_PIN_NANDF_D6},
{"NANDF_D14",3,26,MX51_PIN_NANDF_D14},
{"NANDF_D15",3,25,MX51_PIN_NANDF_D15},
{"CSI1_D9",3,13,MX51_PIN_CSI1_D9},
{"CSI2_D12",4,9,MX51_PIN_CSI2_D12},
{"CSI2_D13",4,10,MX51_PIN_CSI2_D13},
{"CSI2_D18",4,11,MX51_PIN_CSI2_D18},
{"CSI2_D19",4,12,MX51_PIN_CSI2_D19},
{"CSI2_VSYNC",4,13,MX51_PIN_CSI2_VSYNC},
{"CSI2_HSYNC",4,14,MX51_PIN_CSI2_HSYNC},
{"CSI2_PIXCLK",4,15,MX51_PIN_CSI2_PIXCLK},
{"DISP2_DAT6",1,19,MX51_PIN_DISP2_DAT6},
{"DISP2_DAT7",1,29,MX51_PIN_DISP2_DAT7},
{"DISP2_DAT9",1,31,MX51_PIN_DISP2_DAT9},
{"DISP2_DAT11",1,10,MX51_PIN_DISP2_DAT11},
{"DISPB2_SER_RS",3,8,MX51_PIN_DISPB2_SER_RS},
{"DISPB2_SER_CLK",3,7,MX51_PIN_DISPB2_SER_CLK},
{"DISPB2_SER_DIN",3,5,MX51_PIN_DISPB2_SER_DIN},
{"DI1_D1_CS",3,4,MX51_PIN_DI1_D1_CS},
{"DI1_D0_CS",3,3,MX51_PIN_DI1_D0_CS},
{"DI1_PIN13",3,2,MX51_PIN_DI1_PIN13},
{"DI1_PIN12",3,1,MX51_PIN_DI1_PIN12},
{"DI1_PIN11",3,0,MX51_PIN_DI1_PIN11},
{"0",-1,-1,0}
};
int _atoi(char );
int _listlen(struct gpio_out_list *);
int _listlen(struct gpio_out_list *pList)
{
int nlen = 0;
while(pList[nlen].PIN !=0)
{
nlen++;
}
return nlen;
}
int _atoi(char strInt)
{
int nInteger = strInt - 0x30;
return nInteger;
}
int do_gpio_out(cmd_tbl_t *cmdtp,int flag,int argc,char *argv[])
{
printf("argc = %d\n",argc);
printf("argv[0] = %s\n",argv[0]);
printf("argv[1] = %s\n",argv[1]);
printf("argv[2] = %s\n",argv[2]);
int nLevel = _atoi(argv[2][0]);
printf("nLevel is -\n",nLevel);
int i=0;
int cmp = -1;
int bFound = 0;
int nPosInList=-1;
int nLen = _listlen(gpio_list);
printf("list length is = -\n",nLen);
for(i=0;i
{
cmp = strcmp(argv[1],gpio_list[i].strPinName);
if(cmp == 0)
{
bFound = 1;
nPosInList = i;
break;
}
}
if(bFound==0)
{
printf("Can't find pin name!\n");
return -1;
}
unsigned int GPIO_BASE_ADDR;
if(gpio_list[nPosInList].nGroup == 1)
{
GPIO_BASE_ADDR = GPIO1_BASE_ADDR;
}
else if(gpio_list[nPosInList].nGroup == 2)
{
GPIO_BASE_ADDR = GPIO2_BASE_ADDR;
}
else if(gpio_list[nPosInList].nGroup == 3)
{
GPIO_BASE_ADDR = GPIO3_BASE_ADDR;
}
else if(gpio_list[nPosInList].nGroup == 4)
{
GPIO_BASE_ADDR = GPIO4_BASE_ADDR;
}
else
return -1;
unsigned int uTempReg = 1 << gpio_list[nPosInList].bit;
int result = mxc_request_iomux(gpio_list[nPosInList].PIN, IOMUX_CONFIG_GPIO);
if(result!=0)
{
printf("request iomux failed\n");
return -1;
}
unsigned int reg = readl(GPIO_BASE_ADDR + 0x0);
switch(nLevel)
{
case 1:
{
reg |=uTempReg;
writel(reg, GPIO_BASE_ADDR + 0x0);
printf("Set EIM_D22 PIN to High\n");
reg = readl(GPIO_BASE_ADDR + 0x4);
reg |= uTempReg;
writel(reg, GPIO_BASE_ADDR + 0x4);
}
break;
case 0:
{
reg &=~uTempReg;
writel(reg, GPIO_BASE_ADDR + 0x0);
printf("Set EIM_D22 PIN to Low\n");
reg = readl(GPIO_BASE_ADDR + 0x4);
reg |= uTempReg;
writel(reg, GPIO_BASE_ADDR + 0x4);
}
break;
default:
break;
}
mxc_free_iomux(gpio_list[nPosInList].PIN,IOMUX_CONFIG_GPIO);
return 0;
}
U_BOOT_CMD(gpio_out,3,1,do_gpio_out,"usage: gpio_out PIN_NAME 1 or 0\n","This is a command to test gpio pins for I.MX51 SOC\n");
上面代码比较简单,熟悉C语言,一看就懂。该程序的用法就是:> gpio_out EIM_D22 1 表示对EIM_D22引脚进行输出高电平操作;如果是:> gpio_out EIM_D22 0,就是进行低电平操作。如果控制其他引脚,把EIM_D22换成其他PIN的名字。
3、修改一下u-boot/commom/Makefile文件
#this is added by wigros
ifdef CONFIG_CMD_GPIOCTRL
COBJS-$(CONFIG_CMD_GPIOCTRL) += gpio_ctrl.o
endif
4、回到u-boot顶层目录
> make cft8851_config # 调入自己板子配置
> make # 完成make后,就得到u-boot.bin文件
5、把得到的u-boot.bin文件烧入板子NOR FLASH,启动板子进入u-boot命令行,输入help,就能看到gpio_ctrl命令被列出来。
说明:本程序可以进行对SOC的所有GPIO输出端口进行测试。