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. 以太网控制芯片DM9000在2440裸机上终于能正确接收数据了(源代码工程已经上传)...
  2. 你还在 select * 吗?
  3. 视学AI,这群大学生做了个牛逼的项目!
  4. 模型的可解释性:部分依赖图PDP和个体条件期望图ICE
  5. 确定msm8937+android7.1采用的dtb文件
  6. 石头扫地机器人离线了怎么办_关于激光头故障,石头扫地机器人无限次复活记!...
  7. python seaborn 热图 值对应颜色_基于行值的seaborn热图配色方案
  8. linux中apache服务器的搭建与配置
  9. torch的model加载完怎么看_看完这篇后,别再说你不懂JVM类加载机制了~
  10. 4 相机切换_价格屠夫、训练伴侣——海鸟4K运动相机简评
  11. hdu4576(概率DP)
  12. 抖音品质建设 - iOS启动优化《原理篇》
  13. 如何将通讯录批量转换为vcf格式导入手机,苹果手机如何批量删除通讯录?
  14. 勿让“天地图”成绿坝第二
  15. 魔兽争霸3冰封王座,打不开,提示“此版本之魔兽争霸3需要特定语言版本之windows“
  16. 30-40W/年,某银行招聘架构设计岗(地点:上海)
  17. 从excel表格读取日期利用python简单实现农历转阳历功能(1901-2099年之间)
  18. 如何使用html、css制作一个期末作业网站【羽毛球体育运动主题html网页设计】
  19. C#如何获取本机网络ip地址
  20. svn分支开发与主干合并(branch merge)

热门文章

  1. [转] 提问的智慧 快速学习必备
  2. IT运维人员必看!超全信息化建设之运维资料
  3. 细分市场需求:上海千胜发布针对不同量级电商用户云ERP
  4. c语言大小排序算法,七种常见的数组排序算法整理(C语言版本)
  5. Python写个小游戏:蛇棋(上)
  6. Nginx——Nginx优化方案设计
  7. 自考专科历练计算机实践考试,自考等于历练
  8. HTML学习——最终实现小米商城第三天
  9. Java面试题2021【美团】真题:
  10. Windows 7 家庭普通版升级