Linux 移植流水账

首先,要看芯片的核Linux是否支持,如果不支持,那么工作量极其大,放弃吧。
如果cpu核linux支持的话,移植linux,主要是根据SOC所集成的外围模块,将驱动完成。
下面以一款ARM926ejs的芯片为例,在linux 26.22.5上的移植 。
假设芯片叫 MYCHIP
第一步 环境的建立 :
1 在config文件中添加你的芯片支持
  a)  mkdir arch/arm/mach_mychip, 添加Kconfig和Makefile文件
修改arch/arm/Kconfig :
menu "System Type"
choice
    prompt "ARM system type"
    default ARCH_MYCHIP
config ARCH_MYCHIP
    bool "my chip "
    select ARM_AMBA
    help
      This enables support for mychip
-------
source "arch/arm/mach-mychip/Kconfig"
这样 make menuconfig ARCH=arm 就出现了你的芯片 。
b) 在arch/arm/mm/Kconfig 中
# ARM926T
config CPU_ARM926T
depends on ---| |   ARCH_MYCHIP
deafult if ............. | |   ARCH_MYCHIP
这样就申明你的芯片属于 arm 926
c) 在 include/asm-arm/下创建一个目录 mach-mychip
然后修改arch/arm/Makefile 加上 :
machine-$(CONFIG_ARCH_MYCHIP)       := mychip
这样当选择上你的芯片时,编译的时候 会将 include/asm-arm/.arch 链接到
include/asm-arm/arch-mychip
2 加上cpu的配置
a) 在arch/arm/tools中,mach_types加上芯片ID
b) 配置cpu的起始物理地址 和时钟频率
编译
将提示asm/arch/memory.h,asm/arch/timex.h这两个文件没有。
创建include/asm-arm/arch-mychip/memory.h
#define PHYS_OFFSET     UL(0x60000000)
这个是根据芯片SDRAM的 地址空间,比如我现在所用的芯片它的SDRAM地址空间为:6000 0000 – 67FF FFFF 128M
#define __virt_to_bus(x)        __virt_to_phys(x)
#define __bus_to_virt(x)        __phys_to_virt(x)
这两个是:Virtual view <-> DMA view memory address translations
创建include/asm-arm/arch-mychip/timex.h
#define CLOCK_TICK_RATE         (50000000 / 16)
linux用宏 CLOCK_TICK_RATE来表示输入时钟脉冲的频率.
在linux中,1秒中时钟中断的次数 以HZ表示,对于arm #define HZ 100 也就是10ms来一次时钟中断,
Linux用宏LATCH来定义要写到计数器中的值,隔多少个时钟周期产生一次时钟中断。显然LATCH应该由下列公式计算:
LATCH=(1秒之内的时钟周期个数)÷(1秒之内的时钟中断次数)=(CLOCK_TICK_RATE)÷(HZ)
c) 配置vmalloc 虚拟地址分配
编译
提示 缺少 asm/arch/vmalloc.h:
创建include/asm-arm/arch-mychip/vmalloc.h
#define VMALLOC_END             (PAGE_OFFSET + 0x18000000)
PAGE_OFFSET 启始的虚拟地址的分配, linux分为内核空间和用户空间,内核空间为3G-4G,所以PAGE_OFFSET定义为 0xC0000000
VMALLOC_END:
(转http://www.lslnet.com/linux/f/docs1/i34/big5260475.htm)
vmalloc(見mm/vmalloc.c文件)的目的是供內核分配在虛擬空間必須是連續的大塊內存(物理地址不要求連續),其所佔用的地址範圍是特定於平台的常數VMALLOC_START和VMALLOC_END定義的
(转http://idcnews.net/html/edu/20080101/281406.html)
Linux用vm_struct结构来表示vmalloc使用的线性地址.vmalloc所使用的线性地址区间为: VMALLOC_START VMALLOC_END.借用>中的一副插图,如下示:

d) 配置中断,IO ,DMA
编译 inux移植流水帐
将提示缺少 :asm/arch/irqs.h,asm/arch/dma.h,asm/arch/io.h这三个文件
创建irqs.h,在这个文件中 主要是定义NR_IRQS ,以及定义中断的宏,比如定义
#define I2C_INT                     39
标记I2C中断为39号 ,以后在程序里 好用
request_irq( I2C_INT......)
创建 include/asm-arm/arch-dw/io.h,这个文件主要定义IO地址到内存地址的转换
创建 include/asm-arm/arch-dw/dma.h,这个文件主要DMA方面的一些定义
e) 查询中断号的宏实现
这个和特定的CPU有关,就是通过查询中断状态器,得知现在是那个中断
编译
提示缺少include/asm-arm/arch-mychip/entry-macro.S
这个文件主要是low level IRQ helper 宏 get_irqnr_and_base,该宏获取irq中断号,存储到r0寄存器中,作为参数传递给asm_do_IRQ
加上下面两个宏:
.macro  get_irqnr_preamble, base, tmp
                .endm
       .macro  arch_ret_to_user, tmp1, tmp2
                .endm
f)hardware.h
编译
提示缺少include/asm-arm/arch-mychip/hardware.h
g) 设置系统idle ,reset函数
编译 提示缺少asm/arch/system.h:
这个文件主要实现 arch_idle 和arch_reset 2个函数
arch_reset 根据芯片,按次序设置一些寄存器 ,让系统重启
3
  a)上面的步骤做好后,将驱动全部去掉,编译,将提示 arch/arm/arch-mychip/built_in.o找不到,
在arch/arm/arch-mychip中随便添加一个mychip.c文件 ,修改makefile
obj-y                   := mychip.c
b) 编译工具检查
编译 出现
   no machine record defined
原来在arch/arm/kernel/vmlinux.lds末尾 :
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
这表明我们的编译工具太老了,一看,编译工具是arm-2006q3, 2006第3季度的 ,确实太老了。
升级到arm-2008q3,编译还是出现这个问题。
我们编译出错,因为没有arch.info.init这个区,那么这个区在哪里定义的呢? 在linux/include/asm-arm/mach/arch.h 中发现MACHINE_START宏定义:
#define MACHINE_START(_type,_name)                      /
static const struct machine_desc __mach_desc_##_type    /
__used                                                 /
__attribute__((__section__(".arch.info.init"))) = {    /
        .nr             = MACH_TYPE_##_type,            /
        .name           = _name,
#define MACHINE_END                             /
};
因此 在mychip.c中 加上 __enable_mmu
   MACHINE_START(XXXX, "ARM-DW")
        /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
MACHINE_END
XXXX根据arch/arm/tools/mach-types
第二步 :启动kernel
1  将uImage 启动后,
在打印
   Start Kernel ....
后出现
undefined instruction
   Start Kernel .... 是在uboot /lib_arm/armlinux.c 的    do_bootm_linux函数中 ,开始启动kernel时打印的
那后面呢???
2 在uboot中对 SDRAM和串口已经初始化了,但在Linux中也有串口的驱动,串口驱动初始化后,就可以用printk打印东西了,在之前,怎么打印呢?需要实现putc函数 .
在include/asm-arm/arch-mychip中,添加uncompress.h,实现putc,flush函数 。
3 原来是缺少 Makefile.boot文件
在arch/arm/boot/Makefile中,会include $(srctree)/$(MACHINE)/Makefile.boot
创建arch/arm/mach-mychip/Makefile.boot
该文件主要定义
zreladdr-y  0x60008000 内核解压缩后的执行地址 (0x60000000 SDRAM基地址+0x00008000)
params_phys-y 0x60000100 内核参数物理地址  (0x60000000 SDRAM基地址 +0x00000100)
initrd_phys-y  initrd物理地址
4 还是不行 ,用一个可以启动的uImage 进行对比
好的:
## Booting image at 62000000 ...
   Image Name:   Kernel Image
   Created:      2009-03-18   6:23:44 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1452480 Bytes =  1.4 MB
   Load Address: 60008000
   Entry Point:  60008000
出现undefined instrution 的 uImage:
## Booting image at 62000000 ...
   Image Name:   Kernel Image
   Created:      2009-03-20   9:42:06 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2217548 Bytes =  2.1 MB
   Load Address: 30008000
   Entry Point:  30008000
两者的load Address ,entry point不一样,
这是在uboot 的 common/cmd_bootm.c 的 do_bootm函数中 ,调用
print_image_hdr ((image_header_t *)addr);
uImage的 头为 一个image_hear_t结构 。
Load Address 应该在Makefile.boot中定义为zreladdr-y  60008000啊 怎么变成 30008000了呢 ?而且大小也不对阿,怎么2.1 M
后来终于发现,我用的是./uImage 而不是arch/arm/boot/uImage ,而./uImage为非压缩内核,在./Makefile中,用的是 :
        $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
        mkimage -A $(ARCH) -O linux -T kernel -C none -a 30008000 -e 30008000 -n "Kernel Image Giant" -d linux.bin uImage
,需要修改成:
$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
mkimage -A $(ARCH) -O linux -T kernel -C none -a 60008000 -e60008000 -n "Kernel Image Giant" -d linux.bin uImage,
换成arch/arm/boot/uImag后
## Booting image at 62000000 ...
   Image Name:   Linux-2.6.22.5
   Created:      2009-03-20  10:13:20 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)  //mkimage 没有再压缩zImage
   Data Size:    1108164 Bytes =  1.1 MB
   Load Address: 60008000
   Entry Point:  60008000
OK
Start Kernel ....
怎么后面没有了呢 ??

怎么自动就生成了uncompressed uImage呢?

一开始怎么也不理解,应该是compressed uImage啊? 默认的应该是生成compressed uImage .
原来,在include/asm-arm/mach-mychip/uncompress.h中 ,用的是串口1,而我们接的是串口2,修改这个文件,让串口2输出。
在Start Kernel .... 后出现
Uncompressing Linux....................................................................... done, booting the kernel.
说明kernel是压缩的,并正确解压了。
如果用非压缩内核 ,则改为./uImage ,下载后:
## Booting image at 62000000 ...
   Image Name:   Kernel Image Giant
   Created:      2009-03-23   5:42:39 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2217548 Bytes =  2.1 MB
   Load Address: 60008000
   Entry Point:  60008000
OK
5 解压完内核后,或者下载非压缩内核后,
由于在start_kernel一开始就调用printk, 但其实并不是立即就输出,而是放在一个buffer中,__log_buf

直到register_console调用后,register_console注册完后调用release_console_sem(),release_console_sem-->call_console_drivers打印缓冲区里的东西.

也就是说在调用register_console之前的printk,并不打印,而是放在buffer中,在注册console时,把之前打印的立即发送出去.

register_console之后的printk可以立即打印数据.

那么在哪里会调用register_console呢?

uart_add_one_port ->register_console
因此在uart驱动没完成之前,在misc.c中,有一个函数putstr,他直接调用putc ,然后调用flush .

要么在start_kernel中,也这样来试试,看看问题出在哪里 ?
在start_kernel的一开始,用putc('c');flush();  没输出,那说明在调用start_kernel之前就出错了.
在/init/main.c中 加入:
#include
asmlinkage void __init lawrence_debug(void)
{
  putc('a');
  putc('b');
  putc('/n');
   flush();
}
用这个函数来看到底在哪里出问题了(asmlinkage一定要,否则在汇编中调用不了)。
然后在./arch/arm/kernel/head.S中,加入 bl lawrence_debug , 看程序跑到哪里。
发现,原来是 在 __lookup_machine_type后死机了,进入了__error_a,也就是没找到machine_type ,
在head-Common.S中,__lookup_machine_type函数的输入参数是r1 (machine architecture number),而这个参数是 uboot中传入的。

为了更好的看到底问题出在哪里,可以打开CONFIG_DEBUG_LL宏来看.
http://blog.csdn.net/aaronychen/archive/2008/08/27/2838341.aspx
好像__lookup_machine_type的r1不对,修改为:
  __lookup_machine_type:
       mov r1 ,#0x32
       orr r1 ,r1,#0x400
就可以找到machine  了,怎么uboot就没传过来呢??
6  打开CONFIG_DEBUG_LL宏,提示缺少debug-macro.S,
这个文件主要是为了 printascii等函数用 ,它定义了4个宏
addruart : 得到UART的地址,看芯片UARAT1或者2 的地址,这里有个问题,MMU如果没打开,那地址好办,
                      MMU打开了呢?则需要提供虚拟地址,IO的虚拟地址通过下面的方法:
在 MACHINE_START中定义了.map_io = mychip_map_io
                       mychip_map_io -> iotable_init (map_desc ...) ,map_desc结构中定义了IO地址和虚拟地址的对应 关系 ,
在/init/main.c的start_kernel -->startup_arch( arch/arm/kernel/setup.c) -->paging_init(在arch/arm/mm/init.c 中)-->devicemaps_init -->map_io
senduart  :发送内容
waituart   : 等待
busyuart   : 判断是否busy , busy 的话循环
测试这个文件很简单,在head.S中 bl __error_a 看看有没有打印出来
7  发现 :
   ldr        r13, __switch_data                @ address to jump to after
                                                @ mmu has been enabled     
         adr        lr, __enable_mmu                @ return (PIC) address    
------走到此处
         add        pc, r10, #PROCINFO_INITFUNC
r10 为 procinfo的基地址, 因此  add pc ,r10 ...  将执行 __cpu_flush 也就是 __arm926_setup(arch/arm/mm/proc_arm926.S) , 该函数最后  mov pc ,lr 将调用  __enable_mmu
__enable_mmu --> __turn_mmu_on -> mov pc ,r13 将 调用  __switch_data
而在 __map_switched 下面调用 bl __error_a 没反应
在__turn_mmu_on函数中 ,
__turn_mmu_on:
        mov     r0, r0
此处用   bl __error_a 有打印
        mcr     p15, 0, r0, c1, c0, 0           @ write control reg
        mrc     p15, 0, r3, c0, c0, 0           @ read id reg
        mov     r3, r3
        mov     r3, r3
此处用        bl __error_a 没有打印
        mov     pc, r13
这说明 ,在 MMU起效后 , addruart将用虚拟地址 ,而此时IO的虚拟地址是多少呢 ??
这个要根据
      .phys_io       =        0x05C00000,              // UART2 phy addr
      .io_pg_offst    = ((0xf0000000) >> 18) & 0xfffc,  //UART2 virt addr
将5c00000 映射到 0xf0000000
修改 debug-macro.S
  .macro  addruart,rx
                mrc     p15, 0, /rx, c1, c0
                tst     /rx, #1                 @ MMU enabled?
                moveq   /rx, #0x05C00000        @ physical
                movne   /rx, #0xf0000000        @ virtual
                .endm
这样就可以打印出来了 。
8 在main.c start_kernel前定义 :
#define UART2_TX_FIFO_LEVELV (*(volatile unsigned char *)0xf0000020)
#define UART2_TX_DATAV       (*(volatile unsigned char *)0xf0000028)
static inline void putcv(int c)
{
        //wait until there is space in TX FIFO
        while(UART2_TX_FIFO_LEVELV == 0x80)
                barrier();
        UART2_TX_DATAV = c;
}
static inline void flushv(void)
{
        while(UART2_TX_FIFO_LEVELV)
                barrier();
}
asmlinkage void __init lawrence_debug(void)
{
  putcv('a');
  putcv('b');
  putcv('/n');
   flushv();
}
asmlinkage void __init start_kernel(void)
{
        char * command_line;
        extern struct kernel_param __start___param[], __stop___param[];
        lawrence_debug();
     .....
发现打印出来了 。
至此  start_kernel终于运行了。

第三步:系统初始化
1 系统启动流程大致为:
start_kernel :
  setup_arch ....
  init_IRQ -->init_arch_irq
  ...
  timer_init   -->system_timer ...
  ... rest_init -->将调用init call
在 MACHINE_START里面有 :
        .map_io         = mychip_map_io,
        .init_irq       = mychip_init_irq,
        .timer          = &mychip_timer,
        .init_machine   = mychip_init, 
在/init/main.c的start_kernel -->setup_arch( arch/arm/kernel/setup.c) -->paging_init(在arch/arm/mm/init.c 中)-->devicemaps_init -->map_io,     mychip_map_io -> iotable_init (map_desc ...) ,map_desc结构中定义了IO地址和虚拟地址的对应 关系 ,
我们用一个宏 IO_ADDRESS (include/asm/arch/hardware.h)
:#define IO_ADDRESS(x)              (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
将 x  ---> 0xfx ( x 在0x00000000 ~ 0x0f000000 )
    x  ---> 0xf(x+1~f) ( x 在0x10000000 ~ 0xf0000000 )
我们芯片的IO地址都在0x00000000 ~ 0x0f00000000 之间 ,所以物理地址变成虚拟地址只是加上了0xf0000000,变成高位地址 。
最终 映射关系为 :
其他的IO  --> 0xF0000000 (包括 NAND Flash controller ,TDM ....)
   SRAM         --->0xD0000000
  SDRAM       ---> 0xC0000000
  NOR Flash没有映射 ,只能通过 mtdblock0 ,mtdblock1来访问 ?????
修改
     .phys_io       =        0x05C00000,              // UART2 phy addr
      .io_pg_offst    = ((IO_ADDRESS(0x5C00000)) >> 18) & 0xfffc,  //UART2 virt addr
将5c00000 映射到 0xf5C00000
修改 debug-macro.S
    .macro  addruart,rx
                mrc     p15, 0, /rx, c1, c0
                tst     /rx, #1                 @ MMU enabled?
                moveq   /rx, #0x00000000        @ physical
                movne   /rx, #0xf0000000        @ virtual
                orr     /rx, /rx, #0x05C00000   @ UART2 offset
                .endm
这样就对应起来 。 可以在任何时候都用lawrence_debug看系统跑到哪里了。
在main.c start_kernel前定义 :
#define UART2_TX_FIFO_LEVELV (*(volatile unsigned char *)0xf5C00020)
#define UART2_TX_DATAV       (*(volatile unsigned char *)0xf5C00028)
setup_arch的末尾将:
      init_arch_irq = mdesc->init_irq;
        system_timer = mdesc->timer;
        init_machine = mdesc->init_machine;
在arch/arm/kernel/setup.c中
customize_machine  --> init_machine
arch_initcall(customize_machine);
对于 init_irq ,主要是结构体 static struct irq_chip , 并将set_irq_handler(i, handle_level_irq);
并且 注意 在低版本的SA_INTERRUPT 替换成 IRQF_DISABLED
                                       SA_TIMER        替换成 IRQF_TIMER
                                      set_irq_chipdata 替换成 set_irq_chip_data
而 timer 主要是提供系统时钟(tick),这样,每到一个tick,发生任务切换。

第四步: 添加console驱动
console驱动就是输出printk的信息 。 这是第一步,这样在程序中可以用printk来打印,看执行到哪里。
对于 驱动的添加,利用platform driver model , 现在 arch init 中,用amba_device_register加入device ,
然后在module_init中 用 amba_driver_register注册驱动,在注册驱动的过程中,会根据amba_driver中的idtable (包括id和mask)来和device中的periphid 比较 ,看能否match ,能的话就调用probe函数 。
对于 嵌入式设备,console是用输出到uart ,所以只要在uart的驱动中定义struct console mychip_console
然后在struct uart_driver mychip_reg中的.cons = &mychip_console ,这样在probe函数中加上
uart_add_one_port(&mychip_reg,....) 就会把console注册上了。
添加好后,启动kernel
打印:
Starting kernel ...
  Linux version 2.6.22.5 (lawrencekang@lawrencekang) (gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72) ) #48 Wed Apr 8 17:40:52 CST 2009
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
Machine: ARM-MYCHIP
Memory policy: ECC disabled, Data cache writeback
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists.  Total pages: 16256
Kernel command line: root=/dev/mtdblock2 rootfstype=yaffs2 console=ttymychip0 mem=64M mtdparts=dwnand:3m(kernel),3m(splash),-(rootfs)
2
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 62616KB available (1992K code, 155K data, 60K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NTFS driver 2.1.28 [Flags: R/W].
io scheduler noop registered (default)
Serial: MYCHIP UART driver
mychipb:1: ttyMYCHIP0 at MMIO 0x5c00000 (irq = 7) is a MYCHIP_UART
Advanced Linux Sound Architecture Driver Version 1.0.14 (Thu May 31 09:03:25 2007 UTC).
ALSA device list:
  No soundcards found.
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
VFS: Cannot open root device "mtdblock2" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
第五步: 添加网卡驱动,以支持NFS
从上面的输出信息可以看到,我们的下一步需要挂文件系统了。
在开发阶段,最好用NFS,这需要添加网卡驱动。
需要注意的是sk_buffer ,在老的版本中(比如2.6.17) 有mac,h,nh,而在新的版本中变成了 mac_header ,network_header等。
加好网卡驱动,并在文件系统中选择上NFS支持(以及NFS  根文件系统),编译后 :
.......
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
IP-Config: Unable to set interface netmask (-22).
Looking up port of RPC 100003/2 on 172.22.1.35
Looking up port of RPC 100005/1 on 172.22.1.35
VFS: Mounted root (nfs filesystem).
Freeing init memory: 76K
Warning: unable to open an initial console.
Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
第六步: 根文件系统的制作
利用busybox 等制作好rootfs,修改启动脚本,也就是在/etc/init.d/rcS中, 加入 echo "hello" ,其他什么也不作, 在/etc/inittab中,加上:ttyMYCHIP0::respawn:-/bin/sh ,其中ttyMYCHIP 在uart的驱动中定义了。
进入后,就可以 用 ls , cp , ifconfig等命令了 。
第七步: SOC驱动的添加,
1) I2C 驱动

2) SPI 驱动

3)LCD 驱动

4) audio 驱动 ,这个在低的版本中没有 asoc , 在2.6.22中有asoc

5) Flash驱动 以及 Local File System (Yaffs2 移植 )
6)

3)

在linux kernel的文件夹中

/arch 加了一个mach_XXX
/block  unchanged
/Documentation  不用理会
/driver 将 mmc_spi方式移植过来了
驱动中
dwipc
wifi驱动
USB
I2C
SPI
UART
ALSA
NAND
LCD
中断???

/fs 文件系统:添加了squashFS
/init : do_mounts_rd.c因为加了squashFS做了相应修改
/ipc : unchanged
/kernel : sched.c 添加了 DPM
/lib : add crc7.c crc-itu-t.c这些都是因为驱动中加了 mmc_spi
/mm  unchanged
/net 很奇怪,这里也有5个文件修改了
/scripts :unchanged   
/security unchanged   
/sound      添加了2个设备的驱动
/usr   unchanged

Makefile 修改了编译器等

其他都没变

Linux 移植流水账相关推荐

  1. Linux移植之auto.conf、autoconf.h、Mach-types.h的生成过程简析

    在Linux移植之make uImage编译过程分析中分析了uImage文件产生的过程,在uImage产生的过程中,顺带还产生了其它的一些中间文件.这里主要介绍几个比较关键的文件 1.linux-2. ...

  2. ARM的嵌入式Linux移植体验之操作系统

    转自:[url]http://dev.yesky.com/153/2527653.shtml[/url] 06-08-13 08:00 作者: 宋宝华 出处: 天极开发 责任编辑:方舟 在笔者撰写的& ...

  3. Linux移植随笔 tslib

    前段时间让Tslib搞晕头了,原来一切都是版本惹的祸.本文只是一个随笔,随笔者,随意用笔写下心得而已,因此不必较真.正如我所欣赏的"乘兴而来,兴尽而返"一样.--估计当年王子猷是赏 ...

  4. Linux移植随笔:终于解决Tslib的问题了【转】

    转自:http://www.latelee.org/embedded-linux/porting-linux-tslib.html 前段时间让Tslib搞晕头了,原来一切都是版本惹的祸.本文只是一个随 ...

  5. Linux移植之内核启动过程引导阶段分析

    在Linux移植之make uImage编译过程分析中已经提到了uImage是一个压缩的包并且内含压缩程序,可以进行自解压.自解压完成之后内核代码从物理地址为0x30008000处开始运行.下面分析在 ...

  6. Linux移植随笔:对tslib库的ts_test测试程序代码的一点分析

    本文是作者对tslib库的ts_test.c文件进行分析的随笔,其实tslib的几个测试程序结构差不多,譬如ts_print.c和ts_print_raw.c等. 本文并没有涉及太多概念,也没有详细介 ...

  7. Linux移植随笔:终于解决Tslib的问题了

    前段时间让Tslib搞晕头了,原来一切都是版本惹的祸.本文只是一个随笔,随笔者,随意用笔写下心得而已,因此不必较真.正如我所欣赏的"乘兴而来,兴尽而返"一样.--估计当年王子猷是赏 ...

  8. 基于ARM的嵌入式Linux移植真实体验(3)――操作系统

    基于ARM的嵌入式Linux移植真实体验(3)――操作系统 宋宝华[email]21cnbao@21cn.com[/email] 出处:dev.yesky.com 在笔者撰写的<C语言嵌入式系统 ...

  9. pcDuino的linux移植五GPIO驱动开发

    2019独角兽企业重金招聘Python工程师标准>>> 为首的亮,灭.同时如果你GPIO4,GPIO5接个LED,也会跟着亮,灭. 开发环境: 系统:Ubuntu的 一,硬件介绍 仔 ...

最新文章

  1. 树莓派centos安装的基本配置
  2. php读取usb设备信息,急,请问如何获取USB设备的路径,非HID类型
  3. TensorFlow实现人脸检测和人脸识别
  4. leetcode —— 337. 打家劫舍 III
  5. 2011年工作简单总结
  6. 商家 APP 如何接入新版支付宝支付,老版本商家如何升级
  7. java view template_Java设计模式之模板方法模式(Template Method)
  8. php环境用什么服务器好些_PHP环境部署,Linux真的比Windows好吗?
  9. [4G5G专题-22]:架构-3GPP组织以及3GPP标准各个版本的演进路线
  10. 6.5 发散思维能力
  11. 【python基础】英文大小写函数
  12. AHRS(航姿参考系统)和IMU(惯性测量单元)的区别
  13. STM32F407VET6 / BLACK_F407VE开发板间隔0.5秒不断重启
  14. appium实现向上滑动,向下滑动,向左滑动,向右滑动
  15. stm32 设置systick中断抢先式优先级
  16. mysql中双引号和单引号有什么区别
  17. 新浪微博基于Docker的混合云架构与应用实践
  18. I2C总线原理及总线信号的实现
  19. GPRS连接阿里云物联网平台三
  20. 【数据结构】名词速查

热门文章

  1. 一年中最后一个月的最后一天说说_一年最后一个月的句子
  2. android获取图片背景色,android案例--图片取色并让图片融入背景色
  3. CSS day_13(6.28) Boot常用组件(nav、tab、分页)Sass介绍
  4. 拓嘉辰丰:拼多多月卡怎么样?要不要开通?
  5. http(请求方法,状态码,Cookie与Session)
  6. 在一句话后面加ps是表示附言的意思
  7. linux一步一脚印---stat
  8. ruoyi是怎么点击菜单跳转页面的_手把手教你设置公众号菜单栏
  9. 一些比较有用的 Chrome 快捷键
  10. xshell与vim命令合集