Category: 嵌入式

拍照紀念

By ganquan, 2010年04月21日 23:28

經過整個團隊20天努力,項目預期效果實現,一切OK。從學長,老師,同學身上都學習到了不少知識,收穫很多。後續我繼續玩這個板子的機會可能不多了,拍照紀念一下。9.7寸的電子紙,比市面上很多電子紙閱讀器都要大40%左右,看起來很舒服。

這個sketcher程序是板子的demo。


移植2.6.32内核到mini2440开发板

By ganquan, 2009年12月13日 16:02

转载请注明出处:http://ganquan.org,谢谢。本文链接是http://ganquan.org/blog/2009/12/2-6-32-port-to-mini2440/

过程非常简单,麻烦的是如果出问题,就要要一遍又一遍的编译。

先上图:

友善官方的Qtopia系统我早就看烦了,直接启动进入字符界面

img_3676

下面是移植步骤,

1.www.kernel.org下载内核代码,修改构架和编译器

2.修改时钟频率,mini2440开发板用的是12M晶振,修改arch/arm/mach-s3c2440/mach-smdk2440.c

把下面代码中的16934400改为12000000,如果不改串口会出现乱码

static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}

3.修改mini2440的lcd配置,有两个地方要修改,第一是修改LCD屏幕的参数,第二是修改fbi

修改LCD屏幕参数,mini2440使用的是3.5寸的屏幕,在arch/arm/mach-s3c2440/mach-smdk2440.c中,写入

  • 3.1修改LCD参数结构。

#define LCD_WIDTH 240
#define LCD_HEIGHT 320
#define LCD_PIXCLOCK 170000

#define LCD_RIGHT_MARGIN 25
#define LCD_LEFT_MARGIN 0
#define LCD_HSYNC_LEN 4

#define LCD_UPPER_MARGIN 1
#define LCD_LOWER_MARGIN 4
#define LCD_VSYNC_LEN 1

修改lcd参数结构为:

static struct s3c2410fb_display mini2440_lcd_cfg __initdata = {

#if !defined (LCD_CON5)
.lcdcon5    = S3C2410_LCDCON5_FRM565 |
S3C2410_LCDCON5_INVVLINE |
S3C2410_LCDCON5_INVVFRAME |
S3C2410_LCDCON5_PWREN |
S3C2410_LCDCON5_HWSWP,
#else
.lcdcon5    = LCD_CON5,
#endif

.type        = S3C2410_LCDCON1_TFT,

.width        = LCD_WIDTH,
.height        = LCD_HEIGHT,

.pixclock    = LCD_PIXCLOCK,
.xres        = LCD_WIDTH,
.yres        = LCD_HEIGHT,
.bpp        = 16,
.left_margin    = LCD_LEFT_MARGIN + 1,
.right_margin    = LCD_RIGHT_MARGIN + 1,
.hsync_len    = LCD_HSYNC_LEN + 1,
.upper_margin    = LCD_UPPER_MARGIN + 1,
.lower_margin    = LCD_LOWER_MARGIN + 1,
.vsync_len    = LCD_VSYNC_LEN + 1,
};

  • 3.2修改fbi

static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
.displays    = &smdk2440_lcd_cfg,
.num_displays    = 1,
.default_display = 0,

.gpccon =       0xaa955699,
.gpccon_mask =  0xffc003cc,
.gpcup =        0x0000ffff,
.gpcup_mask =   0xffffffff,

.gpdcon =       0xaa95aaa1,
.gpdcon_mask =  0xffc0fff0,
.gpdup =        0x0000faff,
.gpdup_mask =   0xffffffff,

.lpcsel        = 0xf82,
};

4.修改nand分区表,修改arch/arm/plat-s3c24xx/common-smdk.c,这个根据自己的情况来写,照抄是没用滴。

static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name    = “bootloader”,
.size    = 0×00060000,
.offset    = 0,
},
[1] = {
.name    = “kernel”,
.offset = 0×00060000,
.size    = 0×00200000,
},
[2] = {
.name    = “root”,
.offset = 0×00260000,
.size    = 0x3fd80000,
}
};

5.修改machine ID,修改arch/arm/tools/mach-types,填写自己的machine ID

s3c2440            ARCH_S3C2440        S3C2440            1999

6.给内核打yaffs文件系统的补丁。去http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/下载GNU tarball,解压后进入yaffs2目录,给内核打补丁

./patch-ker.sh c ~/kernel/linux-2.6.32

补丁打好后,在内核代码目录下的fs目录新增了yaffs2目录和相关配置文件

7.因为2410和2440很多地方是一样的,可以用2410的配置文件为基础来配置内核。在内核代码主目录下执行:

make s3c2410_defconfig

这个命令其实就是把arch/arm/configs/s3c2410_defconfig文件拷贝过来命名为.config,所以也可以自己cp。其实在2.6.31版内核中就已经加入了对mini2440开发板的支持,但是我没有选。

配置内核这里没有什么好说的,按照自己的需求来配置。

注意两个问题:

(1)编译后的镜像大小不要超过分区配额

(2)不要裁剪太狠了,把一些基本支持都去掉了,这样一些设备就用不了啦

开始编译。我的机器配置是Core 2 T5500 1.66G,2.5G 内存,运行Debian Lenny 5.0.3,编译10分钟左右就OK了。

网卡驱动我一直没有移植成功。后面弄好了再写上来。

EOF

mini2440 button驱动分析

By ganquan, 2009年08月25日 01:34

基本上读懂了,有些几个地方还不明白。

由于wp-syntax插件显示代码实在让我看着眼睛难受,我决定换一种方式贴代码。点击下面的链接试试:

mini2440 button驱动注释

mini2440 leds驱动注释

volatile关键字

By ganquan, 2009年08月23日 11:47

用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。在嵌入式系统中,用来作为硬件动作的结果。

例如,通过一个串口接收到一个字符,结果串口状态寄存器更新,这完全在程序流程之外发生。最好就把该寄存器声明为volatile,编译器不会试图优化一个volatile寄存器,而是每次重载它。所以在嵌入式设备的程序中,将所有外设寄存器声明为volatile是一个好习惯。

mini2440 LED驱动详解

By ganquan, 2009年08月21日 21:22

从最简单的LED驱动入手,彻底细致的分析一遍mini2440的LED驱动。

官方手册上写,mini2440的四个LED与CPU的GPIO相连,LED1, LED2, LED3, LED4分别对应的
是GPB5, GPB6, GPB7, GPB8。那什么是GPIO呢?

GPIO是通用输入输出口的简称,只需要设置相应的CPU寄存器,就可以改变引脚的用途。
控制硬件,其实就是控制对应的寄存器。

四个LED的采用GPBCON寄存器上的4组2bit位来配置对应引脚的状态。4组2bit位的功能都
一样:00表示输入,01表示输出,10为特殊功能,11是保留的。
LED1对应的是GPB5, GPB5使用[11:10]位
LED2对应的是GPB6, GPB6使用[12:13]位
LED3对应的是GPB7, GPB7使用[14:15]位
LED4对应的是GPB8, GPB8使用[16:17]位
驱动需要先设置LED为输出状态,也就是要把对应的GPBX设置为01。

四个LED采用CPBDAT寄存器来对应4个LED的数值状态,GPBDAT5就对应GPB5,GPBDAT6就对
应GPB6,以此类推。手册上写低电平有效,就是说当GPBDAT寄存器位置为0时,LED就发光。

在三星官方的手册S3C2440.pdf中描述的寄存器状态如下:
GPB8 [17:16] 00 = Input 01 = Output
10 = nXDREQ1 11 = Reserved
GPB7 [15:14] 00 = Input 01 = Output
10 = nXDACK1 11 = Reserved
GPB6 [13:12] 00 = Input 01 = Output
10 = nXBREQ 11 = reserved
GPB5 [11:10] 00 = Input 01 = Output
10 = nXBACK 11 = reserved

GPBDAT Bit Description
GPB[10:0] [10:0] When the port is configured as input port, the corresponding
bit is the pin state. When the port is configured as output port, the pin state is the same
as the corresponding bit. When the port is configured as functional pin, the
undefined value will be read.

贴出添加注释后的代码,非常简单的驱动。

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
 
#define DEVICE_NAME "leds" /* /dev目录下的设备名 */
 
/* GPBX */
static unsigned long led_table [] = {
	S3C2410_GPB5,
	S3C2410_GPB6,
	S3C2410_GPB7,
	S3C2410_GPB8,
};
/* GPBX的输出状态 */
static unsigned int led_cfg_table [] = {
	S3C2410_GPB5_OUTP,
	S3C2410_GPB6_OUTP,
	S3C2410_GPB7_OUTP,
	S3C2410_GPB8_OUTP,
};
 
/* 驱动接口函数
* ioctl的内核空间版本和用户控件的版本不同
* 内核版为:
* int (*ioctl)( struct inode *inode, struct file *file, unsigned int
* cmd, unsigned long arg);
* */
static int sbc2440_leds_ioctl(
	struct inode *inode,
	struct file *file,
	unsigned int cmd,
	unsigned long arg)
{
	switch(cmd) {
	case 0:
	case 1:
		if (arg &gt; 4) {
			return -EINVAL; /* Invalid argument,非法参数 */
		}
       /* 设置数据寄存器GPBDAT
		* 低电平有效,用户程序传来的cmd取反
		* */
		s3c2410_gpio_setpin(led_table[arg], !cmd);
		return 0;
	default:
		return -EINVAL;
	}
}
 
/* 接口对象 */
static struct file_operations dev_fops = {
	.owner	=	THIS_MODULE,
	.ioctl	=	sbc2440_leds_ioctl,
};
 
/* 设备对象 */
static struct miscdevice misc = {
	.minor = MISC_DYNAMIC_MINOR, /* 动态设备号 */
	.name = DEVICE_NAME, /* 将在/dev目录生成led设备 */
	.fops = &amp;dev_fops, /* 驱动接口 */
};
 
static int __init dev_init(void)
{
	int ret;
 
	int i;
 
	for (i = 0; i &lt; 4; i++) {
		/*设置GPIO对应的配置寄存器GPIOCON为输出状态*/
		s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
 
		/*设置GPIO对应的数据寄存器GPIODAT为低电平
		 *在模块加载结束后,四个LED应该是全部都是发光状态*/
		s3c2410_gpio_setpin(led_table[i], 0);
	}
 
	ret = misc_register(&amp;misc); /* 注册设备 */
 
	printk (DEVICE_NAME"\tinitialized\n"); /* dmesg */
 
	return ret;
}
 
static void __exit dev_exit(void)
{
	misc_deregister(&amp;misc);                     /* 注销设备 */
}
 
module_init(dev_init); /* 声明加载模块初始化函数 */
module_exit(dev_exit); /* 声明卸载模块清除函数 */
MODULE_LICENSE("GPL"); /* 许可证声明 */
MODULE_AUTHOR("FriendlyARM Inc."); /* 作者信息 */

NFS开发环境建立

By ganquan, 2009年08月19日 23:55

晚上在学校里转了好几个卖电脑配件的地方,都没有卖usb转串口线的,继续找,最后在老综合楼复印店找到了,只剩最后一个,35元。既然是最后一个,就肯定讲不了价,我和店家商量如果系统不能识别就退货,他同意了,咬牙拿下。

回到宿舍赶紧接上开发板,然后火速装上minicom,立即测试,太爽了,一切OK。这下就可以NFS开发了。

基本步骤如下,比较容易,后面有时间再细致的补一下笔记。

1.debian上安装nfs-kernel-server,配置好nfs-server

2.按照手册上的方法把环境配出来

3.配置好minicom,用minicom进入板子的shell

4.在板子上挂载笔记本上的开发目录

5.运行程序不用下载到板子了,在minicom中./myapp就可以了

对Linux很亲热,所以很顺手。感慨一下,Linux这个东西真的太猛了,这么多方便的方式给我选择:

a.可以在笔记本上开发,编译链接得到elf之后用U盘拷贝到板子

b.用串口下载到板子

c.用ftp上传到板子

d.用NFS方式,都不用下载到板子了,这样相当于把板子的FLASH扩大了,因为是用笔记本的硬盘当FLASH,这个是最佳方式。

上述3个方式中,windows不装linux虚拟机的情况下可以使用前三个。还是原生使用linux爽啊,以后就用最佳方式NFS了。

misc设备

By ganquan, 2009年08月19日 19:28

手册上说LED是misc设备,我在开发板上看/dev/leds,给出的是字符设备,这就奇怪了。我以前只知道有字符设备,块设备,对misc没有一点概念。赶紧google一下:

杂项设备(misc device)
杂项设备也是在嵌入式系统中用得比较多的一种设备驱动。在 Linux 内核的include\linux目录下有Miscdevice.h文件,要把自己定义的misc device从设备定义在这里。其实是因为这些字符设备不符合预先确定的字符设备范畴,所有这些设备采用主编号10,一起归于misc device,其实misc_register就是用主标号10调用register_chrdev()的。

也就是说,misc设备其实也就是特殊的字符设备。

在mini2440上的helloworld

By ganquan, 2009年08月18日 22:07

搭建开发环境很容易,跟着手册做,官方是在fedora上搭建的,我在debian上也非常顺利。第一个程序,拍照纪念。

img_2986

Panorama Theme by Themocracy