AT91SAM9260开发板驱动编写

来源:互联网 发布:淘宝和易趣的共同点 编辑:程序博客网 时间:2024/05/02 06:09

一、 编写目的 2

二、 驱动移植 2

1. RTC驱动(PCF8563) 2

2. Led驱动 3

3. 按键驱动 4

4. NAND FLASH驱动 6

5. LCD1602驱动 8

三、 总结 11

 


一、编写目的

        根据“1.AT91SAM9260建立开发环境.doc”搭建好开发环境后,接下来就是进行各个硬件驱动的调试了。本文档用于记录硬件驱动的调试过程,方便日后快速参考设计相关驱动。

二、驱动移植

1. RTC驱动(PCF8563)

        本核心板上使用的RTC芯片型号为PCF8563。LINUX内核对其驱动已经有完整的支持,因此只需要进行相关配置即可。

a) 修改内核中的RTC配置

         Device Drivers  ---> Real Time Clock  ---> 

        < >   AT91SAM9x/AT91CAP9 RTT as RTC  //取消内部RTC设置

        <*>   Philips PCF8563/Epson RTC8564    //打开外部IIC RTC配置

b) 修改板级配置文件

        # gedit ./arch/arm/mach-at91/board-sam9260ek.c

static struct i2c_board_info __initdata ek_i2c_devices[] = {

{

I2C_BOARD_INFO("pcf8563", 0x51),   //add

/* delete

I2C_BOARD_INFO("24c512", 0x50),

.platform_data = &at24c512,

*/

},

/* more devices can be added using expansion connectors */

};

 

c) 设置 系统时钟并写到RTC上(设置为2014年7月8日 02:43:00)

        # date -s "2014-07-08 02:43:00"

        # hwclock -w

2. Led驱动

        LINUX内核对于LED有完善的架构支持,可以在内核配置时打开相关配置项。

a) 修改内核中的配置

        Device Drivers  ---> [*] LED Support  --->

                [*]   LED Class Support

                <*>   LED Support for GPIO connected LEDs

                [*]     Platform device bindings for GPIO LEDs

                [*]   LED Trigger support

                <*>   LED Timer Trigger

                <*>   LED Heartbeat Trigger 

                <*>   LED backlight Trigger 

                <*>   LED GPIO Trigger

                <*>   LED Default ON Trigger

b) 修改板级配置文件

        # gedit ./arch/arm/mach-at91/board-sam9260ek.c

/*

 * LEDs

 */

static struct gpio_led ek_leds[] = {

{

.name = "ds1",

.gpio = AT91_PIN_PC6,

.active_low = 1,

.default_trigger = "timer",

},

{

.name = "ds2",

.gpio = AT91_PIN_PC7,

.active_low = 1,

.default_trigger = "timer",

},

{

.name = "ds3",

.gpio = AT91_PIN_PC9,

.default_trigger = "heartbeat",

}

};

 

c) 测试驱动

        由于使用了LINUX的LED子系统作为LED驱动架构,如下图所示,设备文件的路径在/sys/class/leds/dsx目录下。

 

使用以下命令可以控制LED的亮、灭:

        # echo 1 > /sys/class/leds/ds1/brightness   //亮

        # echo 0 > /sys/class/leds/ds1/brightness   //灭

3. 按键驱动

a) 修改内核中的配置

        Device Drivers  ---> Input device support  --->

                <*>   Event interface

        Device Drivers  ---> Input device support  ---> [*]   Keyboards  --->

                <*>   GPIO Buttons 

b) 修改板级配置文件

        # gedit ./arch/arm/mach-at91/board-sam9260ek.c

/*

 * GPIO Buttons

 */

#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)

static struct gpio_keys_button ek_buttons[] = {

{

.gpio = AT91_PIN_PC10,

.code = BTN_1,

.desc = "Button 1",

.active_low = 1,

.wakeup = 1,

.debounce_interval = 20,   /* 去抖动间隔,单位微毫秒*/  

},

{

.gpio = AT91_PIN_PC11,

.code = BTN_2,

.desc = "Button 2",

.active_low = 1,

.wakeup = 1,

.debounce_interval = 20,   

},

{

.gpio = AT91_PIN_PC13,

.code = BTN_3,

.desc = "Button 3",

.active_low = 1,

.wakeup = 1,

.debounce_interval = 20,   

},

{

.gpio = AT91_PIN_PB30,

.code = BTN_4,

.desc = "Button 4",

.active_low = 1,

.wakeup = 1,

.debounce_interval = 20,  

},

};

static struct gpio_keys_platform_data ek_button_data = {

.buttons = ek_buttons,

.nbuttons = ARRAY_SIZE(ek_buttons),

};

 

static struct platform_device ek_button_device = {

.name = "gpio-keys",

.id = -1,

.num_resources = 0,

.dev = {

.platform_data = &ek_button_data,

}

};

 

static void __init ek_add_device_buttons(void)

{

at91_set_gpio_input(AT91_PIN_PC10, 1); /* btn1 */

at91_set_deglitch(AT91_PIN_PC10, 1);

at91_set_gpio_input(AT91_PIN_PC11, 1); /* btn2 */

at91_set_deglitch(AT91_PIN_PC11, 1);

at91_set_gpio_input(AT91_PIN_PC13, 1); /* btn3 */

at91_set_deglitch(AT91_PIN_PC13, 1);

at91_set_gpio_input(AT91_PIN_PB30, 1); /* btn4 */

at91_set_deglitch(AT91_PIN_PB30, 1);

 

platform_device_register(&ek_button_device);

}

#else

static void __init ek_add_device_buttons(void) {}

#endif

c) 测试驱动

        该按键驱动使用了LINUX输入子系统框架,在打开了事件接口配置后,在/dev/input/event0设备文件中可读取按键的事件值。在控制台上测试可以使用以下命令。

                # hexdump /dev/input/event0

        此时按下按键,将会有数据输出,如下图所示。其中每一次按键动作输出两行数据,从图中分析可知K1~K4的键值分别为101~104。

 

4. NAND FLASH驱动

a) 修改内核中的配置

        Device Drivers  --->  <*> Memory Technology Device (MTD) support  

                [*]   MTD partitioning support

                <*>   Direct char device access to MTD devices

                -*-   Common interface to block layer for MTD 'translation layers

                <*>   Caching block device access to MTD devices

        Device Drivers  --->  <*> Memory Technology Device (MTD) support  ---> <*>   NAND Device Support 

                <*> Support for NAND Flash / SmartMedia on AT91 and AVR32

                ECC management for NAND Flash / SmartMedia on AT91 / AVR32 (Software ECC)  --->

                        (X) Software ECC

b) 测试nand驱动

        从启动信息中可以看出已经成功识别了改NAND FLASH了,如下图所示。

 

        使用flash_eraseall、 nanddump、nandwrite 这三个工具对NAND进行操作(mtd-utils工具/http://pan.baidu.com/s/1mgG8dbq)。以下测试方法是在Linux下将uImage镜像烧写至nand中,通过是否能正常启动Linux来检验Nand驱动是否正确。

        目前开发板的NAND中已经烧写了Bootstrap和u-boot,使用nanddump指令可以读取这两个分区的数据,并与BIN文件进行对比,对比结果正确。

                # nanddump /dev/mtd0  -s 0x00000000 -l 0x00000200 -p  //bootstrap的分区

                # nanddump /dev/mtd1  -s 0x00000000 -l 0x00000200 -p  //u-boot的分区

 

        使用nandwrite烧写uImage到NAND中,修改U-BOOT启动命令后,让其从NAND读取内核,经验证可以正常启动LINUX内核,说明NAND驱动可以使用。

                # flash_eraseall /dev/mtd4

                # nandwrite -a -p  /dev/mtd4 /uImage

                # setenv bootcmd 'nand read 0x22000000 0xA0000 0x200000; bootm'

5. LCD1602驱动

        LCD1602属于一个简单的字符设备,因此这里不对其驱动代码进行详细说明。这部分文字主要说明在LINUX内核中加入新设备驱动的操作,驱动以模块化的方式进行加载。

a) 复制驱动源码至LINUX内核源码目录(使用以前开发过的驱动)

        # cp at91_lcd.c ./drivers/char

b) 修改./drivers/char目录下的Kconfig文件,增加LCD1602相关配置菜单

        # gedit ./drivers/char/Kconfig

config MSM_SMD_PKT

bool "Enable device interface for some SMD packet ports"

default n

depends on MSM_SMD

help

  Enables userspace clients to read and write to some packet SMD

  ports via device interface for MSM chipset.

 

config AT91_LCD

        tristate  "LCD12232 interface"

        default y

        help

          ------------ No help! ----------------------------

 

endmenu

c) 修改./drivers/char目录下的Makefile文件,增加编译选项

        # gedit ./drivers/char/Makefile

        obj-$(CONFIG_AT91_LCD)          += at91_lcd.o

d) 进入menuconfig配置菜单,进行驱动配置

         Device Drivers  ---> Character devices  --->

                 <M> LCD12232 interface (NEW)

e) 编译内核模块

        # make ARCH=arm CROSS_COMPILE=arm-linux- modules

        编译成功后,将./drivers/char目录下的at91_lcd.ko文件复制到目标板的文件系统中,并在目录板的控制台上使用insmod指令加载驱动模块,使用lsmod指令可以查看已经加载的模块,使用rmmod命令删除模块。注意,模块文件必须放在/lib/modules/2.6.39目录下,否则不能正常卸载。

        # cp drivers/char/at91_lcd.ko /opt/AT91SAM9260EK/4.FS/NFS/lib/modules/2.6.39/

        # insmod /lib/modules/2.6.39/at91_lcd.ko

        # lsmod

        # rmmod at91_lcd

 

f) 生成设备文件

        # mknod /dev/at91_lcd c 217 0

 

        加载驱动模块与生成设备文件的命令可以放到/etc/init.d/rcS文件中,让其开机自动执行。

g) 测试程序

#include <stdint.h>       //标准输入输出定义

#include <stdio.h>        //Unix标准函数定义

#include <string.h>       //字符串处理函数定义

#include <fcntl.h>        //文件控制定

 

#define DEV_LCD "/dev/at91_lcd"

 

int clearLCD(int fd);

 

int fd_lcd;

 

int main(void)

{

char bufLcd[124]; 

 

fd_lcd = open(DEV_LCD, O_RDWR);

 

if (fd_lcd < 0)

{

printf("Open \"%s\" fail!\n", DEV_LCD);

}

 

clearLCD(fd_lcd);

 

bufLcd[0] = 0; // 列

bufLcd[1] = 0; //行

strcpy(&bufLcd[2], "----Welcome!----");

write(fd_lcd, bufLcd, strlen(&bufLcd[2]) + 2);

bufLcd[0] = 0; // 列

bufLcd[1] = 1; //行

strcpy(&bufLcd[2], "---LSHICEMAN!---");

write(fd_lcd, bufLcd, strlen(&bufLcd[2]) + 2);

 

while(1);

 

return 0;

}

 

 

int clearLCD(int fd)

{

int i;

char bufLCD[124];

 

if (fd < 0) return -1;

 

memset(bufLCD, 20, 124);

 

for (i = 0; i < 2; i++)

{

bufLCD[0] = 0;

bufLCD[1] = i;

write(fd, bufLCD, 124);

}

 

return 0;

}

 

三、总结

        AT91SAM9260核心板的各个驱动已经基本完成。像继电器、LCD背光这类GPIO控制类的驱动还没有进行编写,可以参考LED驱动的方式进行编写/设置。将本文档中的LINUX系统打包为201407091104_at91sam9260ek_linux.2.6.39.tar.bz2,可通过以下地址下载。

        # tar -jcvf 201407091104_at91sam9260ek_linux.2.6.39.tar.bz2 ./linux-at91-linux-2.6.39-at91/

                 http://pan.baidu.com/s/1o6LTNRW 

0 0