Oct 25, 2014
TechnologySerial Port Support
Enable the Device Driver—-> Character deivces —-> Serial drivers —-> Samsung related settings, My setting is listed as following:
Then you will see serial output during kernel boot.
DM9000 Support
Add following code into the linux/arch/arm/mach-s3c2440/mach-smdk2440.c:
#include <linux/serial_core.h>
+ /* Added dm9000 support for utu2400 */
+ #include <linux/dm9000.h>
#include <linux/platform_device.h>
#include <plat/common-smdk.h>
+ /* DM9000 Base address for SMDK2440 */
+ #define MACH_SMDK2440_DM9K_BASE (S3C2410_CS3 + 0x300)
static struct map_desc smdk2440_iodesc[] __initdata = {
+ /* Added for dm9000 */
+ static struct resource smdk2440_dm9k_resource[] =
+ {
+ [0] =
+ {
+ .start = MACH_SMDK2440_DM9K_BASE,
+ .end = MACH_SMDK2440_DM9K_BASE + 3,
+ .flags = IORESOURCE_MEM
+ },
+ [1] =
+ {
+ .start = MACH_SMDK2440_DM9K_BASE + 4,
+ .end = MACH_SMDK2440_DM9K_BASE + 7,
+ .flags = IORESOURCE_MEM
+ },
+ [2] =
+ {
+ .start = IRQ_EINT9,
+ .end = IRQ_EINT9,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ }
+ };
+
+ /*
+ * The DM9000 has no eeprom, and it's MAC address is set by
+ * the bootloader before starting the kernel.
+ */
+ static struct dm9000_plat_data smdk2440_dm9k_pdata =
+ {
+ .flags = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),
+ };
+
+ static struct platform_device smdk2440_device_eth =
+ {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smdk2440_dm9k_resource),
+ .resource = smdk2440_dm9k_resource,
+ .dev = {
+ .platform_data = &smdk2440_dm9k_pdata,
+ },
+ };
static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_ohci,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
+ &smdk2440_device_eth,
};
Then select the dm9000 support from:
Device Driver—-> Network device support -> Ethernet(10 or 100Mbit) —-> DM9000 support
Now testing the kernel, you will see the kernel starts with dm9000 support, thus we could use NFS for booting the system.
Oct 25, 2014
TechnologyBuilding Filesystems
Use following script for building the basic filesystem:
$ cat mkrootfs
#!/bin/sh
echo "------Create rootfs directons start...--------"
mkdir rootfs
cd rootfs
echo "--------Create root,dev....----------"
mkdir bin boot dev etc home lib mnt proc root sbin sys tmp usr var www
mkdir etc/init.d etc/rc.d etc/sysconfig
mkdir usr/sbin usr/bin usr/lib usr/modules
echo "make node in dev/console dev/null"
mknod -m 666 dev/console c 5 1
mknod -m 666 dev/null c 1 3
mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp
mkdir var/lib var/lock var/run var/tmp
chmod 1777 tmp
chmod 1777 var/tmp
echo "-------make direction done---------"
Run it and you will get an folder which contains the newly created directory structure.
$ sudo ./mkrootfs
------Create rootfs directons start...--------
--------Create root,dev....----------
make node in dev/console dev/null
-------make direction done---------
$ ls rootfs
bin boot dev etc home lib mnt proc root sbin sys tmp usr var www
After making the filesystem, you should install all of the kernel modules into your fs:
$ make modules_install ARCH=arm INSTALL_MOD_PATH=The_PATH_TO_YOUR_ROOTFS
BusyBox
Busybox provides almost all of the tools used in system, first we should download and cross-compile it.
$ wget http://www.busybox.net/downloads/busybox-1.22.1.tar.bz2
$ tar xjvf busybox-1.22.1.tar.bz2
$ cd busybox-1.22.1
$ vim Makefile
+ CROSS_COMPILE ?= arm-linux-
# bbox: we may have CONFIG_CROSS_COMPILER_PREFIX in .config,
$ make menuconfig
Parameters:
Build Options---> Build BusyBox as a static binary(no shared libs)
Installation Options--> Busybox installation prefix(See following pictures)
Linux Module Utilities--> Default directory containing modules(/lib/modules)
Linux System Utilities --->
[*]Support /etc/mdev.conf
[*]Support command execution at device addition/removal
Init Utilities --->
"Support reading an inittab file"
"Support running commands with a controlling-tty"
Then Make and make install:
$ make && make install
Now list the rootfs you have created you could see a new file named linuxrc is located under the / directory. Also you will see lots of executable files under the /bin which links to the /bin/busybox.
Startup Configuration
Create the /etc/group file:
$ cat etc/group
root:*:0:
daemon:*:1:
bin:*:2:
sys:*:3:
adm:*:4:
tty:*:5:
disk:*:6:
lp:*:7:lp
mail:*:8:
news:*:9:
u p:*:10:
proxy:*:13:
kmem:*:15:
dialout:*:20:
fax:*:21:
voice:*:22:
cdrom:*:24:
floppy:*:25:
tape:*:26:
s o:*:27:
a io:*:29:
sshd:*:74:
ppp:x:99:
500:x:500:plg
501:x:501:fa
Edit the /etc/passwd file:
$ cat etc/passwd
root::0:0:root:/:/bin/sh
ftp::14:50:FTP User:/var/ftp:
bin:*:1:1:bin:/bin:
daemon:*:2:2:daemon:/sbin:
nobody:*:99:99:Nobody:/:
sky::502:502:Linux User,,,:/home/sky:/bin/sh
Add the hostname:
$ cat etc/sysconfig/HOSTNAME
utu2440
Edit the inittab file:
$ cat etc/inittab
#etc/inittab
::sysinit:/etc/init.d/rcS
# Start an "askfirst" shell on /dev/tty2-4
console::askfirst:-/bin/sh
tty2::askfirst:-/bin/sh
tty3::askfirst:-/bin/sh
tty4::askfirst:-/bin/sh
# /sbin/getty invocations for selected ttys
tty4::respawn:/sbin/getty 38400 tty5
tty5::respawn:/sbin/getty 38400 tty6
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a –r
$ chmod 777 etc/init.d/rcS
Edit etc/init.d/rcS, this file will be executed everytime we bootup the linux system:
$ cat etc/init.d/rcS
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
echo "----------mount all----------------"
mount -a
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s
### Added from utu2440
trap ":" INT QUIT TSTP
##################################
#/bin/mount -t tmpfs tmpfs /dev
#/bin/mount -t sysfs sysfs /sys
##################################
mkdir /dev/pts
/bin/mknod /dev/pts/0 c 136 0
/bin/mknod /dev/pts/1 c 136 1
/bin/mknod /dev/pts/2 c 136 2
/bin/mknod /dev/pts/3 c 136 3
/bin/mknod /dev/pts/4 c 136 4
/bin/mknod /dev/pts/5 c 136 5
/bin/mount -t devpts devpts /dev/pts
#/bin/mount -t proc none /proc
ln -s /dev/ts0 /dev/h3600_tsraw
/sbin/ifconfig eth0 10.0.0.15
/usr/sbin/telnetd -l /bin/login
echo "After telnetd"
/usr/bin/tty>/root/tty.txt
Create a new fstab file:
$ cat etc/fstab
#device mount-point type option dump fsck order
proc /proc proc defaults 0 0
none /tmp ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
mdev /dev ramfs defaults 0 0
Testing filesystem
Set the nfs boot options:
utu-bootloader=>>>setenv bootargs 'console=ttySAC0 init=/linuxrc root=/dev/nfs nfsroot=10.0.0.11:/media/nfs/rootfs,proto=tcp,nolock ip=10.0.0.15:10.0.0.1:10.0.0.1:255.255.255.0:www.yctek.com:eth0:off'
utu-bootloader=>>>setenv bootargs 'console=ttySAC0 init=/linuxrc root=/dev/nfs nfsroot=10.0.0.11:/media/nfs/rootfs,proto=tcp,nolock ip=10.0.0.15'
then we could boot into the nfs based filesystem.
Please press Enter to activate this console. NET: Registered protocol family 10
[root@www ~]#
[root@www ~]# uname -a
Linux www 2.6.39 #6 Mon Oct 20 16:12:43 CST 2014 armv4tl GNU/Linux
Oct 25, 2014
TechnologyRTC
Activate
RealTime Clock functionality could be easily activated via:
$ vim arch/arm/mach-s3c2440/mach-smdk2440.c
static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_ohci,
+ &s3c_device_rtc,
&s3c_device_lcd,
Configure the Kernel:
Device Drivers—-> RealTime Clock —-> Samsung S3C series Soc RTC
Save and exit, then make Image.
Test RTC
Before we have following configuration:
[root@www ~]# date
Thu Jan 1 01:07:51 UTC 1970
Now we switch to new kernel which contains RTC support:
[root@www ~]# ls -l /dev/rtc*
crw-rw---- 1 root root 254, 0 Jan 1 00:00 /dev/rtc0
[root@www ~]# date -s 201410251348
Sat Oct 25 13:48:00 UTC 2014
[root@www ~]# hwclock -w
Add following lines into /etc/init.d/rcS for automatically update systemtime from RTC:
[root@www ~]# cat /etc/init.d/rcS
echo "update time from RTC"
hwclock -s
date
Reboot to see whether RTC works or not:
# date
Sat Oct 25 13:51:34 UTC 2014
If we enable the NTPD, then this board could serve as the Network Time Protocol Server in Ethernet.
LCD
Coding
First we attached the LCD touch screen to our development board, it will displayed a blank screen, while this blank screen will turn into graphic windows after we enabled the LCD Driver.
We should carefully view yc2440-core.pdf, to find the LCD controller pin.
From the picture we could see the LCD’s backlight is controlled via CPU’s LCD_PWREN/EINT12/GPG4
.
Add the backlight.c in kernel source tree:
$ pwd
/media/y/embedded/utu2440/Kernel/linux-2.6.39/drivers/video/backlight
[Trusty@/media/y/embedded/utu2440/Kernel/linux-2.6.39/drivers/video/backlight]$ cat SMDK2440_backlight.c
Now the content should be:
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#undef DEBUG
//#define DEBUG
#ifdef DEBUG
#define DPRINTK(x...) {printk(__FUNCTION__"(%d): ",__LINE__);printk(##x);}
#else
#define DPRINTK(x...) (void)(0)
#endif
#define DEVICE_NAME "backlight"
static unsigned int bl_state;
static inline void set_bl(int state)
{
bl_state = !!state;
s3c2410_gpio_setpin(S3C2410_GPG(4), bl_state);
}
static inline unsigned int get_bl(void)
{
return bl_state;
}
static ssize_t dev_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
{
unsigned char ch;
int ret;
if (count == 0) {
return count;
}
ret = copy_from_user(&ch, buffer, sizeof ch) ? -EFAULT : 0;
if (ret) {
return ret;
}
ch &= 0x01;
set_bl(ch);
return count;
}
static ssize_t dev_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
int ret;
unsigned char str[] = {'0', '1' };
if (count == 0) {
return 0;
}
ret = copy_to_user(buffer, str + get_bl(), sizeof(unsigned char) ) ? -EFAULT : 0;
if (ret) {
return ret;
}
return sizeof(unsigned char);
}
static struct file_operations dev_fops = {
owner: THIS_MODULE,
read: dev_read,
write: dev_write,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
ret = misc_register(&misc);
printk (DEVICE_NAME"\tinitialized\n");
s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT);
set_bl(1);
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc);
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Utu2440 Inc.");
Add the Kconfig items for our newly added SMDK2440_backlight:
$ cat /media/y/embedded/utu2440/Kernel/linux-2.6.39/drivers/video/backlight/Kconfig
config BACKLIGHT_SMDK2440
tristate "Backlight Driver for utu2440"
depends on BACKLIGHT_LCD_SUPPORT && FB_S3C2410
help
Backlight driver for utu2440
Enable the Makefile Item:
$ cat /media/y/embedded/utu2440/Kernel/linux-2.6.39/drivers/video/backlight/Makefile
obj-$(CONFIG_BACKLIGHT_SMDK2440) += SMDK2440_backlight.o
Now configure the Kernel like following image:
Compile and generate the uImage:
$ make
$ cp arch/arm/boot/zImage ./ && mkimage -A arm -O linux -n $(date --iso-8601=seconds) -C NONE -a 0x30008000 -e 0x30008000 -d zImage uImage
Verification
Replace the newly built kernel on utu2440, first your screen remains turned on.
Change the backlight on utu2440:
[root@www ~]# echo 0>/dev/backlight
[root@www ~]# echo 1>/dev/backlight
[root@www ~]# ls /dev/backlight
/dev/backlight
But this command is not stable, we could only turn off the backlight, then won’t call it alive again.
Change back to 2.6.32
The ioctl function changes in 2.6.39, thus we have to use .unlocked_ioctl, so we won’t actually control the backlight, switch the kernel version to 2.6.32, do following changes:
Change again the code:
$ vim SMDK2440_backlight.c
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
//定义背光驱动的名称为 backligh,将会出现在/dev/backlight
#define DEVICE_NAME "backlight"
#define DEVICE_MINOR 5 //次设备号,这里我们将设备注册为misc设备,这种设备的主设备号都为10
extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
static int smdk2440_backlight_ioctl(struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg)
{
printk("We received cmd %d\n", cmd);
switch(cmd)
{
case 0:
//当接收的命令为0时,就将GPG4引脚设为低电平,关闭背光
s3c2410_gpio_setpin(S3C2410_GPG(4), 0);
printk(DEVICE_NAME " turn off!\n");
return 0;
case 1:
//当接收的命令为1时,就将GPG4引脚设为高电平,开启背光
s3c2410_gpio_setpin(S3C2410_GPG(4), 1);
printk(DEVICE_NAME " turn on!\n");
return 0;
default:
return -EINVAL;
}
}
//设备操作集
static struct file_operations dev_fops =
{
.owner = THIS_MODULE,
//.unlocked_ioctl = smdk2440_backlight_ioctl,
.ioctl = smdk2440_backlight_ioctl,
};
static struct miscdevice misc =
{
.minor = DEVICE_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int __init dev_init(void)
{
int ret;
ret = misc_register(&misc); //注册成misc设备
if(ret < 0)
{
printk("Register misc device fiald!");
return ret;
}
//将GPG4口配置成输出口
s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT);
s3c2410_gpio_setpin(S3C2410_GPG(4), 1); //启动内核时打开背光
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc); //注销该misc设备
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("DreamCatcher");
MODULE_DESCRIPTION("Backlight control for mini2440");
Then define a test_lcd.c like:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
unsigned int turn;
int fd;
//检测命令后面带的参数
if(argc == 1 || argc > 2)
{
printf("Usage: backlight_test on|off!\n");
exit(1);
}
//打开背光设备
fd = open("/dev/backlight", O_RDWR);
if(fd < 0)
{
printf("Open Backlight Device Faild!\n");
exit(1);
}
//判断输入的参数
if(strcmp(argv[1], "on") == 0)
{
printf("Yes, you input on!\n");
turn = 1;
ioctl(fd, 1);
}
else if(strcmp(argv[1], "off") == 0)
{
printf("Yes, you input off!\n");
turn = 0;
ioctl(fd, 0);
}
else
{
printf("Usage: backlight_test on|off!\n");
exit(1);
}
printf("turn is %d\n", turn);
//进行IO控制
//long ret=ioctl(fd, turn);
//关闭背光设备
close(fd);
return 0;
}
Compile the lcd_test via:
$ arm-linux-gcc -o lcd_test lcd_test.c
$ cp lcd_test.c /media/nfs/rootfs/root/
Test the lcd backlight setting functionality via:
[root@www root]# ./lcd_test on
Yes, you input on!
turn is 1
[root@www root]# ./lcd_test off
Yes, you input off!
turn is 0
So until now, you have mastered the LCD backlight, you could freely turn on/off it.
Oct 24, 2014
TechnologyUse Popen for running ls
We could use following python scripts for running the bash command ls -l
:
>>> from subprocess import *
>>> from subprocess import call
>>> from subprocess import Popen
>>> import subprocess
>>> ls_child = Popen(['ls', '-l'], stdout=subprocess.PIPE, stderr = subprocess.PIPE)
>>> ls_result = ls_child.communicate()
>>> print ls_result
.......
The command I want to call is:
sed -n 1~2p File_Name
This command will get the half of the file contents.
Popen Wrapping
The commands for canling sed is:
>>> sed_child = Popen(['sed', '-n', '1~2p', '/home/Trusty/code/mybash/rtp02_2014_10_23_03_23_36.txt'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> sed_content = sed_child.communicate()
Judge the parameters:
>>> command_line=raw_input()
sed -n 1~2p /home/Trusty/code/mybash/rtp02_2014_10_23_03_23_36.txt
>>> args=shlex.split(command_line)
>>> print args
Write the result into the file(half size as the origin input file), notice we remove the first 16 characters:
>>> f_half = open("./half_result.txt", "w+")
>>> for line in sed_content:
>>> f_half.write(line.replace(line[:16],''))
>>> f_half.close()
Then the file contains all of the content.
If we want to write into sorted result, then do following:
>>> lines=[]
>>> for line in sed_content:
>>> lines.append(line.replace(line[:16], ''))
>>> lines.sort()
>>> f_half = open("./half_result.txt", "w+")
>>> for line in lines:
>>> f_half.write(line)
>>> f_half.close()
Oct 23, 2014
Technologysshd replacement
Since busybox enabled the telnetd by default, we could just use telnet for accessing the board.
[root@www ~]# ps -ef | grep telnet
861 root 0:00 /usr/sbin/telnetd -l /bin/login
893 root 0:00 grep telnet