smdkv210 uboot增加GPIO按键和开机logo的制作

来源:互联网 发布:红警3网络对战 编辑:程序博客网 时间:2024/06/05 08:10

华天正的smdkv210开发板,有五个按键接在外部中断0,1,3,4,5引脚上,最初打算用中断方式

实现按键,修改cpu/s5pc11x/interrupts.c:

int interrupt_init(void)
{

S5PC11X_TIMERS *const timers = S5PC11X_GetBase_TIMERS();


/*use PWM Timer 4 because it has no output */
/* prescaler for Timer 4 is 16 */
timers->TCFG0 = 0x0f00;
if (timer_load_val == 0) {
/*
* for 10 ms clock period @ PCLK with 4 bit divider = 1/2
* (default) and prescaler = 16. Should be 10390
* @33.25MHz and  @ 66 MHz
*/
timer_load_val = get_PCLK() / (16 * 100);
}

/* load value for 10 ms timeout */
lastdec = timers->TCNTB4 = timer_load_val;
/* auto load, manual update of Timer 4 */
timers->TCON = (timers->TCON & ~0x00700000) | TCON_4_AUTO | TCON_4_UPDATE;
/* auto load, start Timer 4 */
timers->TCON = (timers->TCON & ~0x00700000) | TCON_4_AUTO | COUNT_4_ON;
timestamp = 0;  

/*  EINT initial INT0,1,3,4,5   */
printf("\nEint_init\n");
ulong reg;
reg = readl(GPH0CON);
writel(reg | 0x00fff0ff, GPH0CON);  //GPH0CON EXT_INT[0,1,3,4,5]
reg = readl(EXT_INT_0_CON);
writel(reg | 0x222022, EXT_INT_0_CON);  //EXT_INT_0_CON[0,1,3,4,5] Falling edge triggered
reg = readl(EXT_INT_0_MASK);
writel(reg & 0x4, EXT_INT_0_MASK);  //EXT_INT_0_MASK[0,1,3,4,5]  Enables Interrupt 
reg = readl(VIC0INTENABLE);
writel(reg | 0x3b, VIC0INTENABLE);  //VIC0INTENABLE[0,1,3,4,5]  Enables Interrupt 

return (0);
}

void do_irq(struct pt_regs *pt_regs)
{
ulong reg;
reg = readl(VIC0INTENCLEAR);
writel(reg | 0x3b, VIC0INTENCLEAR);  //VIC0INTENCLEAR[0,1,3,4,5]  disables Interrupts 
reg = readl(EXT_INT_0_PEND);
writel(reg & 0x4, EXT_INT_0_PEND);  //EXT_INT_0_PEND[0,1,3,4,5]  clear Interrupts
printf("interrupt request\n");
show_regs(pt_regs);
bad_mode();
}

修改之后按下按键,uboot不断重启,没有执行中断处理函数do_irq,尝试了一些方法

没有效果,不知道问题在哪,如果有哪位高手知道请留言。

转而使用查询方式实现按键,新建/drivers/input/gpio_key.c:

#include <common.h>
#include <regs.h>
#include <asm/io.h>
#include <gpio_key.h>

#ifdef CONFIG_GPIOKEY
#include <devices.h>
//#include <keyboard.h>

#define KBG_DEBUG

#ifdef KBG_DEBUG
#define PRINTF(fmt,args...)printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif

#define DEVNAME"gpiokey"
#define KBD_BUFFER_LEN0x20  /* size of the keyboardbuffer */

static volatile char kbd_buffer[KBD_BUFFER_LEN];
static volatile int in_pointer = 0;
static volatile int out_pointer = 0;

/******************************************************************
 * Queue handling
 ******************************************************************/
/* puts character in the queue and sets up the in and out pointer */
static void kbd_put_queue(char data)
{
if((in_pointer+1)==KBD_BUFFER_LEN) {
if(out_pointer==0) {
return; 
} else{
in_pointer=0;
}
} else {
if((in_pointer+1)==out_pointer)
return; /
in_pointer++;
}
kbd_buffer[in_pointer]=data;
return;
}

static char kbd_read_data(void)
{
char val;
val = ((~readl(GPH0DAT)) & 0x0000003b);
return val;
}
static char kbd_wait_for_input(void)
{
char val;
// val=kbd_read_data();
while(1) {
val=kbd_read_data();
if(val==0) continue;
udelay(100000);   //延时去抖动 100ms
if(val==kbd_read_data()){    
// kbd_put_queue(val);
/* switch(val){
case KEY_MENU:
PRINTF(" key MENU pressed!\n");
break;
case KEY_HOME:
PRINTF(" key HOME pressed!\n");
break;
case KEY_CALL:
PRINTF(" key CALL pressed!\n");
break;
case KEY_ENDCALL:
PRINTF(" key ENDCALL pressed!\n");
break;
case KEY_BACK:
PRINTF(" key BACK pressed!\n");
}
PRINTF("key: %X\n",val);  */
return val;
}
}

}
/* test if a character is in the queue */
static int kbd_testc(void)
{
/*
if(in_pointer==out_pointer)
return(0);
else
return(1);
*/
char val;
val=kbd_read_data();
if(val==0) 
return(0);
udelay(100000);   //延时去抖动 100ms
if(val==kbd_read_data()){    
return(1);
}
return(0);
}

/* gets the character from the queue */
static char kbd_getc(void)
{
/* char c;
if(in_pointer==out_pointer) {
kbd_wait_for_input();
}
if((out_pointer+1)==KBD_BUFFER_LEN)
out_pointer=0;
else
out_pointer++;
c=kbd_buffer[out_pointer];
PRINTF("key: %X\n",c);
return c;
*/
return kbd_wait_for_input();
}

/******************************************************************
 * Init
 ******************************************************************/
#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
extern int overwrite_console (void);
#define OVERWRITE_CONSOLE overwrite_console ()
#else
#define OVERWRITE_CONSOLE 0
#endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */

int gpio_key_init(void)
{
ulong reg;
reg = readl(GPH0CON);
writel(reg & 0xff000f00, GPH0CON);  //GPH0CON input[0,1,3,4,5]
reg = readl(GPH0PUD);
writel(reg & 0xf030, GPH0PUD);  //GPH0PUD [0,1,3,4,5] Pull-up/down disabled
reg = readl(GPH0DRV);
writel(reg & 0xf030, GPH0DRV);  //GPH0DRV [0,1,3,4,5]  1x 
int error;
struct device_t kbddev ;
char *stdinname  = getenv ("stdin");
memset (&kbddev, 0, sizeof(kbddev));
strcpy(kbddev.name, DEVNAME);
kbddev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
kbddev.putc = NULL ;
kbddev.puts = NULL ;
kbddev.getc = kbd_getc ;
kbddev.tstc = kbd_testc ;
error = device_register (&kbddev);
if(error==0) {
/* check if this is the standard input device */
if(strcmp(stdinname,DEVNAME)==0) {
/* reassign the console */
if(OVERWRITE_CONSOLE) {
return 1;
}
error=console_assign(stdin,DEVNAME);
if(error==0)
return 1;
else
return error;
}
return 1;
}
return error;
}

#endif /* CONFIG_GPIOKEY */


开机logo的制作,参考文章U-boot开机logo的制作方法

http://blog.chinaunix.net/uid-20543672-id-94364.html

在有实现LCD显示和LCD命令行终端的U-boot中,在左上角都有显示一个logo,如果是atmel的芯片,就会有atmel的logo,三星的则是denx的logo。

有的网友发邮件说想改成自己公司的Logo,而且如果是自己玩的话,改成自己喜欢的logo也爽阿。所以今天我做好了实验,将简单的修改方法总结如下:


一、图片的放置路径

所有的开机logo都放在了 /tools/logos 之下,你只需要将你的班子作对应的logo替换就好了。

对于S3C2440,你只需要将denx.bmp替换成你想要的logo就好了。

对于ATMEL的芯片,据说会显示ATMEL的logo,所以替换那个logo即可。

但是你所替换的logo必须和原来的大小、格式一模一样否则会出现u-boot使用过程中宕机重启的后果


二、图片的大小标准

不同的logo对应不同的大小,这里S3C2440所对应的是160*96分辨率的BMP图片。


三、图片的转换脚本

在制作图片前,请您现确认您的Linux主机上安装了Netpbm 工具包。如果是ubuntu,你可以直接用新立得安装;如果是别的发行版,可以在 Netpbm主页 下载源代码编译。

   将你想要的图片裁减成160*96的JPG图片,然后用以下的脚本处理一下就好了:


#!/bin/sh
#install Netpbm first
    jpegtopnm $1 | ppmquant 31 | ppmtobmp -bpp 8 > $2


使用方法: (脚本名) ( 待处理的JPG图片名) (输出文件名)