当前位置:首页 > 移植
  • 详细讲解 移植Uboot到ARMer9开发系统上

    首先了解ARMer9开发系统硬件设计上和三星原装SMDK2410之间的区别。让uboot在ARMer9开发系统上跑起来,目前只需要关注如下的硬件区别,解决了下面这个问题,uboot就可以在ARMer9开发系统上正常地从串口输出,进入提示符。很多命令都可以使用,当然有些命令需要做修改。 SMDK2410 : nor flash 是AMD的1M的; ARMer9: 是Intel E28F128J3A, 两片并联,一共32M Bytes. 下载一个uboot-1.1.1.tar.bz2.; tar jxvf uboot-1.1.1.tar.bz2; 在uboot 目录board/smdk2410 下的flash.c需要修改。这个是Flash的驱动,如何写,需要参考E28F128J3A的Datasheet. 这里我们提供一个我们修改好的flash.c文件,您只需要将这个文件覆盖掉board/smdk2410 下的文件即可。 (注意:你要安装了交叉编译器才行哦) 修改uboot目录下的Makefile,将 ifeq ($(ARCH),arm) CROSS_COMPILE = arm-linux- endif 修改成 ifeq ($(ARCH),arm) CROSS_COMPILE = /opt/host/armv4l/bin/armv4l-unknown-linux- endif 修改processor.h中: union debug_insn { u32 arm; u16 thumb; } 修改成: union debug_insn { u32 arm_mode; u16 thumb_mode; } 然后配置板子 make smdk2410_config 然后 make 在uboot目录生成uboot.bin; 通过sjf2410w程序将uboot.bin下载到nor flash中, 地址为0的地方; 串口接在UART0上,uboot的启动信息将输出。 你将发现很多命令都可以使用了。uboot果然强大。 关于网络部分,因为ARMer9开发系统使用也是CS8900A,所以代码部分几乎不用做改动,只需要在 include/configs/smdk2410.h中看看,有没有定义CONFIG_ETHADDR,CONFIG_IPADDR, CONFIG_SERVERIP这些宏没有,如果没有,请定义好。 #define CONFIG_ETHADDR 00:00:e0:ff:cd:15 #define CONFIG_IPADDR 192.168.0.5 #define CONFIG_SERVERIP 192.168.0.100 就这样修改一下,网络部分功能就通了,哈哈。 可以使用tftpboot命令从tftp服务器下载程序到系统内存中。 #tftpboot 0x33000000 zImage #bootm 0x33000000 利用uboot引导可执行映象的通用方法 uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。 mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载内存中的哪个位置, 入口点在内存的那个位置以及映象名是什么 root@Glym:/tftpboot# ./mkimage Usage: ./mkimage -l image -l ==> list image header information ./mkimage -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image -A ==> set architecture to 'arch' -O ==> set operating system to 'os' -T ==> set image type to 'type' -C ==> set compression type 'comp' -a ==> set load address to 'addr' (hex) -e ==> set entry point to 'ep' (hex) -n ==> set image name to 'name' -d ==> use image data from 'datafile' -x ==> set XIP (execute in place) 参数说明: -A 指定CPU的体系结构: 取值 表示的体系结构 alpha Alpha arm A RM x86 Intel x86 ia64 IA64 mips MIPS mips64 MIPS 64 Bit ppc PowerPC s390 IBM S390 sh SuperH sparc SPARC sparc64 SPARC 64 Bit m68k MC68000 -O 指定操作系统类型,可以取以下值: openbsd、netbsd、freebsd、4_4bsd、linux、svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos -T 指定映象类型,可以取以下值: standalone、kernel、ramdisk、multi、firmware、script、filesystem -C 指定映象压缩方式,可以取以下值: none 不压缩 gzip 用gzip的压缩方式 bzip2 用bzip2的压缩方式 -a 指定映象在内存中的加载地址,映象下载到内存中时,要按照用mkimage制作映象时,这个参数所指定的地址值来下载 -e 指定映象运行的入口点地址,这个地址就是-a参数指定的值加上0x40(因为前面有个mkimage添加的0x40个字节的头) -n 指定映象名 -d 指定制作映象的源文件 常用U-BOOT命令介绍 1. ?或者help,得到所有命令列表; 2. help: help usb, 列出USB功能的使用说明 3. ping:注:通常只能运行uboot的系统PING别的机器 4. setenv: 设置环境变量 setenv serverip 10.36.20.49,设置TFTP Server的IP地址; setenv ipaddr 10.36.20.200,设置IP地址; setenv bootcmd ‘tftp 32000000 vmlinux; kgo 32000000’,设置启动命令(实际上就是一个脚本); 5. saveenv:在设置好环境变量以后, 保存环境变量值到flash中间; 6. tftpboot:tftpboot 0x800000 vmlinux, 将TFTP Server(IP = 环境变量中设置的serverip)中/tftpdroot目录 下的vmlinux通过TFTP协议下载到物理内存0x800000开始的地方。 7. kgo:启动没有压缩的linux内核,kgo 0x800000 8. bootm:启动通过UBOOT TOOLS—— mkimage制作的压缩LINUX内核, bootm 3200000; 9 flinfo:列出flash的信息 10. protect: 对FLASH进行写保护或取消写保护, protect on 1:0-3(就是对第一块FLASH的0-3扇区进行保护),protect off 1:0-3取消写保护 11. erase: 删除FLASH的扇区, erase 1:0-2(就是对每一块FLASH的0-2扇区进行删除) 12. cp: 将内存中数据烧写到Flash, cp 0x800000 0xc0000 0x40000(把内存中0x800000开始的0x40000字节复制到0xc0000处); 13. mw: 对RAM中的内容进行写操作, mw 32000000 ff 10000(把内存0x32000000开始的0x10000字节设为0xFF); 14. md: 显示RAM中的内容, md 0x800000; 15. loadb: 准备用 KERMIT协议接收来自kermit或超级终端传送的文件。 16. nfs: nfs 32000000 192.168.0.2:aa.txt , 把192.168.0.2(LINUX 的NFS文件系统)中的NFS文件系统中的aa.txt 读入内存0x32000000处。 17. fatls:列出DOS FAT文件系统, 如:fatls usb 0列出第一块U盘中的文件 18. fatload: 读入FAT中的一个文件,如:fatload usb 0:0 32000000 aa.txt 19. usb相关的命令: usb start: 起动usb 功能 usb info: 列出设备 usb scan: 扫描usb storage(u 盘)设备 Uboot对SMDK2410板的NAND Flash初始化部分没有写, 即lib_arm/board.c中的start_armboot函数中有这么一句: #if (CONFIG_COMMANDS & CFG_CMD_NAND) puts ("NAND:"); nand_init(); /* go init the NAND */ #endif 但是在board/smdk2410目录下任何源文件中都没有定义nand_init这个函数。 所以需要我们补充这个函数以及这个函数涉及的底层操作。 我们可以仿照VCMA9板的nand_init函数,VCMA9板是一款用S3C2410做CPU的DEMO Board,因此这部分操作和SMDK2410 Demo Board很相似。大部分代码可以照搬。 首先将board/mpl/vcma9/vcma9.c中下面代码拷贝到board/smdk2410/ smdk2410.c中来。 /* * NAND flash initialization. */ #if (CONFIG_COMMANDS & CFG_CMD_NAND) extern ulong nand_probe(ulong physadr); static inline void NF_Reset(void) { int i; NF_SetCE(NFCE_LOW); NF_Cmd(0xFF); /* reset command */ for(i = 0; i < 10; i++); /* tWB = 100ns. */ NF_WaitRB(); /* wait 200~500us; */ NF_SetCE(NFCE_HIGH); } static inline void NF_Init(void) { #if 0 /* a little bit too optimistic */ #define TACLS 0 #define TWRPH0 3 #define TWRPH1 0 #else #define TACLS 0 #define TWRPH0 4 #define TWRPH1 2 #endif NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0)); /*nand->NFCONF = (1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); */ /* 1 1 1 1, 1 xxx, r xxx, r xxx */ /* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */ NF_Reset(); } void nand_init(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); NF_Init(); #ifdef DEBUG printf("NAND flash probing at 0x%.8lXn", (ulong)nand); #endif printf ("%4lu MBn", nand_probe((ulong)nand) >> 20); } #endif 再将board/mpl/vcma9/vcma9.h中下面代码拷贝到board/smdk2410/ smdk2410.c中来。 #if (CONFIG_COMMANDS & CFG_CMD_NAND) typedef enum { NFCE_LOW, NFCE_HIGH } NFCE_STATE; static inline void NF_Conf(u16 conf) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONF = conf; } static inline void NF_Cmd(u8 cmd) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCMD = cmd; } static inline void NF_CmdW(u8 cmd) { NF_Cmd(cmd); udelay(1); } static inline void NF_Addr(u8 addr) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFADDR = addr; } static inline void NF_SetCE(NFCE_STATE s) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); switch (s) { case NFCE_LOW: nand->NFCONF &= ~(1<<11); break; case NFCE_HIGH: nand->NFCONF |= (1<<11); break; } } static inline void NF_WaitRB(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); while (!(nand->NFSTAT & (1<<0))); } static inline void NF_Write(u8 data) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFDATA = data; } static inline u8 NF_Read(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); return(nand->NFDATA); } static inline void NF_Init_ECC(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); nand->NFCONF |= (1<<12); } static inline u32 NF_Read_ECC(void) { S3C2410_NAND * const nand = S3C2410_GetBase_NAND(); return(nand->NFECC); } #endif 再将include/configs/vcma.9中下面代码拷贝到include/configs/smdk2410.h中来。 /*----------------------------------------------------------------------- * NAND flash settings */ #if (CONFIG_COMMANDS & CFG_CMD_NAND) #define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ #define SECTORSIZE 512 #define ADDR_COLUMN 1 #define ADDR_PAGE 2 #define ADDR_COLUMN_PAGE 3 #define NAND_ChipID_UNKNOWN 0x00 #define NAND_MAX_FLOORS 1 #define NAND_MAX_CHIPS 1 #define NAND_WAIT_READY(nand) NF_WaitRB() #define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH) #define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW) #define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d) #define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d) #define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d) #define WRITE_NAND(d, adr) NF_Write(d) #define READ_NAND(adr) NF_Read()

    时间:2021-04-12 关键词: 移植 Uboot ARMer9开发系统

  • 但是如何将不同的操作系统移植到Android

    我们已经看到许多用于所有Windows Mobile设备的端口,但是如何将不同的操作系统移植到Android呢?XDA成员和传奇人物mamaich为我们带来了两个适用于Android设备的模拟器,这将使Android用户可以启动Windows95。QEMU和BOSCH在知道如何使用它们的人们中广受欢迎,因为它们已在其他项目中使用。在其他设备上运行不同的Windows版本。 尽管该项目运行顺利,但仍有待改进。不幸的是,mamaich提到他将不会继续开发这些港口。但是,他分享了所有具有合适技能的人所需的全部资源和知识,以使他从上次离开的地方继续前进。在许多要求中,需要具有大量RAM和至少VGA屏幕的设备。 BOCHS太慢而无法使用,但非常稳定。 QEMU确实非常快-但有故障。SB16仿真正常,但没有MIDI音乐。FPU仿真不正确/不完整,因此可能导致某些程序无法运行或行为异常。网络无法正常工作。键盘/鼠标仿真远非完美。 如果要在QEMU中禁用32位磁盘驱动程序,则Windows 9x可以在QEMU中工作。这是Android中的错误(扩展/写入功能不起作用)。Windows 9x速度确实非常快。 此QEMU构建基于0.9.1,较新的版本具有ARM TCG中的错误,无法启动Windows或类似的操作系统。 我不会继续从事这两个项目。如果有人感兴趣,我将提供所有资源和有关构建的一些信息。需要具备C ++,ARM和x86 asm知识。

    时间:2020-09-25 关键词: Android 移植

  • lwip移植说明及心得

      lwIP是瑞士计算机科学院(Swedish InsTItute of Computer Science)的Adam Dunkels等开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈。Lwip既可以移植到操作系统上,又可以在无操作系统的情况下独立运行。   1、LwIP的特性   (1) 支持多网络接口下的IP转发   (2) 支持ICMP协议   (3) 包括实验性扩展的的UDP(用户数据报协议)   (4) 包括阻塞控制,RTT估算和快速恢复和快速转发的TCP(传输控制协议)   (5) 提供专门的内部回调接口(Raw API)用于提高应用程序性能   (6) 可选择的Berkeley接口API(多线程情况下)   (7) 在最新的版本中支持ppp   (8) 新版本中增加了的IP fragment的支持。   (9) 支持DHCP协议,动态分配ip地址。   2 Lwip在ucos上的移植。   2.1 系统初始化   sys_int必须在tcpip协议栈任务tcpip_thread创建前被调用。   #define MAX_QUEUES 20   #define MAX_QUEUE_ENTRIES 20   typedef struct {   OS_EVENT* pQ;//ucos中指向事件控制块的指针   void* pvQEntries[MAX_QUEUE_ENTRIES];//消息队列   //MAX_QUEUE_ENTRIES消息队列中最多消息数   } TQ_DESCR, *PQ_DESCR;   typedef PQ_DESCR sys_mbox_t;//可见lwip中的mbox其实是ucos的消息队列   staTIc char pcQueueMemoryPool[MAX_QUEUES * sizeof(TQ_DESCR) ];   void sys_init(void)   {   u8_t i;   s8_t ucErr;   pQueueMem = OSMemCreate( (void*)pcQueueMemoryPool, MAX_QUEUES, sizeof(TQ_DESCR), &ucErr );//为消息队列创建内存分区   //init lwip task prio offset   curr_prio_offset = 0;   //init lwip_TImeouts for every lwip task   //初始化lwip定时事件表,具体实现参考下面章节   for(i=0;i《LWIP_TASK_MAX;i++){   lwip_TImeouts[i].next = NULL;   }   }   2.2 创建一个和tcp/ip相关新进程   lwip中的进程就是ucos中的任务,创建一个新进程的代码如下:   #define LWIP_STK_SIZE 10*1024//和tcp/ip相关任务的堆栈大小。可以根据情况自   //己设置,44b0开发板上有8M的sdram,所以设大   //一点也没有关系:)   //max number of lwip tasks   #define LWIP_TASK_MAX 5 //和tcp/ip相关的任务最多数目   //first prio of lwip tasks   #define LWIP_START_PRIO 5 //和tcp/ip相关任务的起始优先级,在本例中优先级可   //以从(5-9)。注意tcpip_thread在所有tcp/ip相关进程中//应该是优先级最高的。在本例中就是优先级5   //如果用户需要创建和tcp/ip无关任务,如uart任务等,   //不要使用5-9的优先级   OS_STK LWIP_TASK_STK[LWIP_TASK_MAX][LWIP_STK_SIZE];//和tcp/ip相关进程   //的堆栈区   u8_t curr_prio_offset ;   sys_thread_t sys_thread_new(void (* function)(void *arg), void *arg,int prio)   {   if(curr_prio_offset 《 LWIP_TASK_MAX){   OSTaskCreate(function,(void*)0x1111, &LWIP_TASK_STK[curr_prio_offset][LWIP_STK_SIZE-1],   LWIP_START_PRIO+curr_prio_offset );   curr_prio_offset++;   return 1;   } else {   // PRINT(“ lwip task prio out of range ! error! ”);   }   }   从代码中可以看出tcpip_thread应该是最先创建的。

    时间:2020-08-04 关键词: lwip 移植

  • 粪便移植又有妙用 不仅减肥还能预防糖尿病

    通过移植健康捐赠者的粪便来改变肠道微生物群正在成为治疗各种疾病的一种有希望的方法。现在,科学家将这项技术作为治疗肥胖的一种方法,通过动物模型发现,该方法可以有效减少小鼠的体重和减轻2型糖尿病的进展。 该研究由丹麦哥本哈根大学的科学家进行的,与其他的粪便移植不同,该方法是先从样本中过滤出活细菌,同时提高病毒颗粒(即噬菌体)的浓度。 首先,科学家们给一组老鼠喂食了一段时间的标准低脂饮食,然后收集它们的粪便并过滤掉所有的活细菌。然后将产生的病毒颗粒移植到喂食高脂肪食物6周的小鼠体内,这些老鼠继续保持高脂饮食习惯六周,然后评估体重增加和葡萄糖耐量。 当将它们与高脂饮食但没有移植病毒的对照组进行比较时,接受病毒颗粒的小鼠的体重增加明显减少。该技术还显示出抗2型糖尿病的常见指标葡萄糖不耐症的潜力,研究小组观察到与健康对照组相比,接受治疗的小鼠对注射葡萄糖的反应方式没有差异。 研究人员表示,该研究目前是基于动物模型的,也有可能在人类身上产生类似的效果,但还需要更多的试验去验证。此外,在治疗肥胖症患者时,我们建议与饮食改变相搭配,以带来更佳的治疗效果。

    时间:2020-05-25 关键词: 糖尿病 病毒 肥胖 粪便 移植

  • 科学家培植大规模“超级珊瑚”:或可抵抗因气候变暖的白化死亡

    12月27日,据外媒报道,因气候变暖,全球已有一半以上的珊瑚因白化死亡。科学家启动了一个大规模的珊瑚礁拯救项目,在陆地上种植具有一定复原力的“超级珊瑚”,成功后再将它们移植回海里。 报道中指出,塞舌尔的科学家正在海底移植“超级珊瑚”,通过海洋粘合剂把珊瑚附着在岩石上,这有望使珊瑚礁在未来的珊瑚白化中存活下来。 珊瑚修复者克洛伊·舒特说:“我们的‘珊瑚园艺’移植方法是通过在珊瑚白化后马上到珊瑚礁进行观察,寻找存活的珊瑚群,我们有信心使它们具有一定的复原力。” 超级珊瑚生长在水下被称为“珊瑚苗圃”的绳索上,这是全球最大规模的珊瑚苗圃。 报道称,世界各地的科学家们纷纷来到这里学习珊瑚的培植技术,这种技术已经被应用在哥伦比亚和马尔代夫等国,接下来还将用于肯尼亚、坦桑尼亚和毛里求斯。 气候变化已经使全世界一半以上的珊瑚死亡,珊瑚的色彩和能量来源于生活在它们体内的藻类,在海水变暖使藻类变得有毒之前,这是一种完美的共生关系,所以珊瑚被迫驱逐了它们,这就是“珊瑚白化”。 珊瑚礁拯救项目创始人尼马尔·吉万·沙说:“我们现在已经了解到整项技术,所以下一步就是在陆地上种植珊瑚并修复它们,直到它们能够适应气候变化再移植回海里。” 专家预测,到2050年,世界上大部分珊瑚将死亡,像这样的创新可能是它们最后的生存希望。

    时间:2020-01-10 关键词: 藻类 气候变暖 珊瑚白化 珊瑚群 珊瑚礁 移植

  • 国外女工程师为方便:将特斯拉车钥匙芯片植入手臂内

    忘带钥匙?相信这样的事情大家或多或少经历过。 不过,随着指纹锁、近场感应解锁、人脸识别解锁等技术的普及,偌大的钥匙越来越不需要随身携带。 当然,还有些人想更省事,比如ID“Amie DD”为软件工程师就把爱车特斯拉Model 3的NFC芯片车钥匙植入手臂内。喜爱纹身的她对这样的身体改造毫不介意,毕竟如此带来的便利程度和极客范儿更具吸引力。 需要指出的是,芯片虽然包裹在生物质聚合材料内,但Amie的手臂依然有些肿胀,而且她必须非常靠近车辆才能完成解锁,这也许是现有技术不完美的地方。 图为Model 3车钥匙原始芯片

    时间:2019-09-06 关键词: 特斯拉 车钥匙 移植

  • u-boot-2009.08在mini2440上的移植(四)---增加DM9000驱动

    移植环境1,主机环境:VMare下CentOS 5.5 ,1G内存。2,集成开发环境:Elipse IDE3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。4,开发板:mini2440,2M nor flash,128M nand flash。5,u-boot版本:u-boot-2009.086,参考文章:http://blogold.chinaunix.net/u3/101649/showart.php?id=2105215http://blog.chinaunix.net/space.php?uid=23787856&do=blog&id=115382http://blogimg.chinaunix.net/blog/upfile2/100811115954.pdfu-boot-2009.08版本已经对CS8900、RTL8019和DM9000X等网卡有比较完善的代码支持(代码在drivers/net/目录下),而且在S3C24XX系列中默认对CS8900网卡进行配置使用。而mini2440开发板使用的则是DM9000网卡芯片,所以只需在开发板上添加对DM9000的支持即可。还有一点,以前的 U-boot 对于网络延时部分有问题,需要修改许多地方。但是现在的U-boot 网络部分已经基本不需要怎么修改了,只有在DM9000 的驱动和NFS 的TIMEOUT 参数上需要稍微修改一下。4.1,DM9000驱动代码修改【1】修改static int dm9000_init函数中部分代码,如果不修改这一部分,在使用网卡的时候会报“could not establish link”的错误。打开/drivers/net/dm9000x.c,定位到377行,修改如下:/* Activate DM9000 *//* RX enable */DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);/* Enable TX/RX interrupt mask */DM9000_iow(DM9000_IMR, IMR_PAR);#if 0 //default to link MII interfacei = 0;while (!(phy_read(1) & 0x20)) {/* autonegation complete bit */udelay(1000);i++;if (i == 1650) {//printf("could not establish linkn");//return 0;break;}}#endif【2】对于NFS,增加了延时,否则会出现“*** ERROR: Cannot mount”的错误。打开/net/nfs.c,定位到36行,修改如下:#if defined(CONFIG_CMD_NET) && defined(CONFIG_CMD_NFS)#define HASHES_PER_LINE 65/* Number of "loading" hashes per line*/#define NFS_RETRY_COUNT 30#define NFS_TIMEOUT (CONFIG_SYS_HZ/1000*2000UL) //2000UL【3】添加网卡芯片(DM9000)的初始化函数打开board/samsung/mini2440/mini2440.c,定位到194行附近,文件末尾处,修改如下:int dram_init (void){gd->bd->bi_dram[0].start = PHYS_SDRAM_1;gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;return 0;}extern int dm9000_initialize(bd_t *bis);//implicit declaration of function 'dm9000_initialize'#ifdef CONFIG_DRIVER_DM9000int board_eth_init(bd_t *bis){return dm9000_initialize(bis);}#endif【4】添加串口 Xmodem 传输协议(可不修改)对于使用串口传输数据到内存的操作,有可能会用到Xmodem协议。但是原本的kermit协议传输就挺好用的,速度也比较快,所以可添加此功能。打开/common/cmd_load.c,定位到37行,修改如下:#if defined(CONFIG_CMD_LOADB)#if defined(ENABLE_CMD_LOADB_X)static ulong load_serial_xmodem (ulong offset);#endifstatic ulong load_serial_ymodem (ulong offset);#endif然后再定位到480行附近,修改如下:if (load_baudrate != current_baudrate) {printf ("## Switch baudrate to %d bps and press ENTER ...n",load_baudrate);udelay(50000);gd->baudrate = load_baudrate;serial_setbrg ();udelay(50000);for (;;) {if (getc() == 'r')break;}}#if defined(ENABLE_CMD_LOADB_X)if (strcmp(argv[0],"loadx")==0) {printf ("## Ready for binary (xmodem) download ""to 0x%08lX at %d bps...n",offset,load_baudrate);addr = load_serial_xmodem (offset);} else if (strcmp(argv[0],"loady")==0) {#elseif (strcmp(argv[0],"loady")==0) {#endifprintf ("## Ready for binary (ymodem) download ""to 0x%08lX at %d bps...n",offset,load_baudrate);addr = load_serial_ymodem (offset);再定位到998行附近,修改如下:static int getcxmodem(void) {if (tstc())return (getc());return -1;}#if defined(ENABLE_CMD_LOADB_X)static ulong load_serial_xmodem (ulong offset){int size;char buf[32];int err;int res;connection_info_t info;char xmodemBuf[1024];ulong store_addr = ~0;ulong addr = 0;size = 0;info.mode = xyzModem_xmodem;res = xyzModem_stream_open (&info, &err);if (!res) {while ((res =xyzModem_stream_read (xmodemBuf, 1024, &err)) > 0) {store_addr = addr + offset;size += res;addr += res;#ifndef CFG_NO_FLASHif (addr2info (store_addr)) {int rc;rc = flash_write ((char *) xmodemBuf,store_addr, res);if (rc != 0) {flash_perror (rc);return (~0);}} else#endif{memcpy ((char *) (store_addr), xmodemBuf,res);}}} else {printf ("%sn", xyzModem_error (err));}xyzModem_stream_close (&err);xyzModem_stream_terminate (false, &getcxmodem);flush_cache (offset, size);printf ("## Total Size = 0x%08x = %d Bytesn", size, size);sprintf (buf, "%X", size);setenv ("filesize", buf);return offset;}#endifstatic ulong load_serial_ymodem (ulong offset)再定位到1169行,修改如下:#if defined(CONFIG_CMD_LOADB)U_BOOT_CMD(loadb, 3, 0,do_load_serial_bin,"load binary file over serial line (kermit mode)","[ off ] [ baud ]n"" - load binary file over serial line"" with offset 'off' and baudrate 'baud'");#if defined(ENABLE_CMD_LOADB_X)U_BOOT_CMD(loadx, 3, 0, do_load_serial_bin,"load binary file over serial line (xmodem mode)","[ off ] [ baud ]n"" - load binary file over serial line"" with offset 'off' and baudrate 'baud'");#endifU_BOOT_CMD(loady, 3, 0,do_load_serial_bin,"load binary file over serial line (ymodem mode)","[ off ] [ baud ]n"" - load binary file over serial line"" with offset 'off' and baudrate 'baud'");【5】修改配置文件,在mini2440.h中加入相关定义打开/include/configs/mini2440.h,定位到60行附近,修改如下:/** Hardware drivers*/#if 0#define CONFIG_DRIVER_CS89001/* we have a CS8900 on-board */#define CS8900_BASE0x19000300#define CS8900_BUS161 /* the Linux driver does accesses as shorts */#endif#define CONFIG_NET_MULTI1#define CONFIG_DRIVER_DM9000 1#define CONFIG_DM9000_BASE 0x20000300 //网卡片选地址#define DM9000_IO CONFIG_DM9000_BASE#define DM9000_DATA (CONFIG_DM9000_BASE+4) //网卡数据地址#define CONFIG_DM9000_NO_SROM1//#define CONFIG_DM9000_USE_16BIT#undef CONFIG_DM9000_DEBUG注意:u-boot-2009.08 可以自动检测DM9000网卡的位数,根据开发板原理图可知网卡的数据位为16位,并且网卡位于CPU的BANK4上,所以只需在 board/samsung/mini2440/lowlevel_init.S中设置 #define B4_BWSCON (DW16) 即可,不需要此处的 #define CONFIG_DM9000_USE_16BIT 1给u-boot加上ping命令,用来测试网络通不通/** Command line configuration.*/#include #define CONFIG_CMD_CACHE#define CONFIG_CMD_DATE#define CONFIG_CMD_ELF#define CONFIG_CMD_NAND#define CONFIG_CMD_JFFS2 /* JFFS2 Support*/#define CONFIG_CMD_PING /*ping command support*/恢复被注释掉的网卡MAC地址和修改你合适的开发板IP地址以及内核启动参数:#define CONFIG_BOOTDELAY3#define CONFIG_ETHADDR08:00:3e:26:0a:5b#define CONFIG_NETMASK 255.255.255.0#define CONFIG_IPADDR10.1.0.129#define CONFIG_SERVERIP10.1.0.128#define CONFIG_GATEWAYIP10.1.0.1#define CONFIG_OVERWRITE_ETHADDR_ONCE/*#define CONFIG_BOOTFILE"elinos-lart" */定位到139行附近,加入使能串口传输数据到内存的操作:#define ENABLE_CMD_LOADB_X1 //使能串口传输数据到内存的操作#if defined(CONFIG_CMD_KGDB)#define CONFIG_KGDB_BAUDRATE115200/* speed to run kgdb serial port *//* what's this ? it's not used anywhere */#define CONFIG_KGDB_SER_INDEX1/* which serial port to use */#endif【6】为u-boot增加命令自动补全和历史记录功能此功能如同shell里面自动补全和历史记录功能,用起来非常方便。打开/include/configs/mini2440.h,定位到109附近,加入宏定义:#define CONFIG_CMD_ASKENV#define CONFIG_CMD_CACHE#define CONFIG_CMD_DATE#define CONFIG_CMD_ELF#define CONFIG_AUTO_COMPLETE /*command auto complete*/#define CONFIG_CMDLINE_EDITING /*command history record*/#define CONFIG_CMD_NAND#define CONFIG_CMD_JFFS2 /* JFFS2 Support*/#define CONFIG_CMD_PING /*ping command support*/4.2,重新编译u-boot,下载到Nand中从Nand启动,查看启动信息和环境变量并使用ping命令测试网卡,操作如下:Enter your selection: aUSB host is connected. Waiting a download.

    时间:2019-01-16 关键词: u-boot mini2440 dm9000驱动 移植

  • u-boot-2009.08在mini2440上的移植(十)---增加I2C EEPROM功能

    移植环境1,主机环境:VMare下CentOS 5.5 ,1G内存。2,集成开发环境:Elipse IDE3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。4,开发板:mini2440,2M nor flash,128M nand flash。5,u-boot版本:u-boot-2009.086,参考文章:http://blogimg.chinaunix.net/blog/upfile2/100811115954.pdf10.1,实现u-boot的I2C EEPROM功能mini2440开发板上的AT24C08A芯片提供了8kbyte的非易失的EEPROM存储空间,而且是通过I2C协议进行读写的,U-boot提供了对I2C和EEPROM的操作支持。打开/include/configs/mini2440.h,定位到206行附近,加入宏定义:/** SD Card support* */#if 1#define CONFIG_CMD_MMC#define CONFIG_MMC1#define CONFIG_MMC_S3C1/* Enabling the MMC driver */#define CFG_MMC_BASE0xff000000#endif/*** I2C and EEPROM support*/#if 1#define CONFIG_CMD_EEPROM#define CONFIG_CMD_I2C#define CONFIG_DRIVER_S3C24X0_I2C 1 /* we use the buildin I2C controller */#define CONFIG_HARD_I2C 1 /* I2C with hardware support */#define CONFIG_SYS_I2C_SPEED 100000 /* I2C speed and slave address */#define CONFIG_SYS_I2C_SLAVE 0x7F#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 /* EEPROM at24c08 */#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address *//* mask of address bits that overflow into the "EEPROM chip address" */#define CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW 0x07#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ /* 16 byte page write mode using*/ /* last 4 bits of the address */#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */#define CONFIG_SYS_EEPROM_PAGE_WRITE_ENABLE//#define CONFIG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars *///#define CONFIG_ENV_OFFSET 0x000 /* environment starts at offset 0 *///#define CONFIG_ENV_SIZE 0x400 /* 1KB */#endif10.2,重新编译测试待编译完成后,nor档下载nand档启动,操作如下:[u-boot@MINI2440]# help i2ci2c - I2C sub-systemUsage:i2c speed [speed] - show or set I2C bus speedi2c md chip address[.0, .1, .2] [# of objects] - read from I2C devicei2c mm chip address[.0, .1, .2] - write to I2C device (auto-incrementing)i2c mw chip address[.0, .1, .2] value [count] - write to I2C device (fill)i2c nm chip address[.0, .1, .2] - write to I2C device (constant address)i2c crc32 chip address[.0, .1, .2] count - compute CRC32 checksumi2c probe - show devices on the I2C busi2c reset - re-init the I2C Controlleri2c loop chip address[.0, .1, .2] [# of objects] - looping read of device[u-boot@MINI2440]# i2c speedCurrent bus speed=100000[u-boot@MINI2440]# i2c probeValid chip addresses: 50 51 52 53[u-boot@MINI2440]# i2c在上面的mini2440.h文件中,CONFIG_ENV_IS_IN_EEPROM是注释掉的,如果想将环境变量保存的位置设置在EEPROM中,需要将nandflash的CONFIG_ENV_IS_IN_NAND的相关几行代码注释掉,将上面注释掉的几行代码恢复即可。这里先不作修改了。10.3 本次u-boot移植遗留问题【1】由于mini2440出厂配置的LCD的型号是TD035STED4,是240X320分辨率的,是竖屏,但是想进行横向输出时遇到了困难,究竟怎么实现,还有待研究。【2】开机时显示的logo信息,旁边空白的部分没有文字显示,如何实现开机是logo图片周边有文字环绕,还有待研究。【3】开机时的详细,可以通过环境变量stdout设置成vga是LCD输出,serial是串口控制台输出。看要要想两者同时输出时遇到了困难。【4】开机前LCD动画显示后在输出信息还没有实现。

    时间:2019-01-15 关键词: i2c eeprom u-boot mini2440 移植

  • S3C2440 Linux驱动移植——AT24C02(EEPROM)驱动

    开发板:TQ2440内核:Linux 2.6.32PC OS:Ubuntu 11.041.配置内核打开I2C功能:打开杂项设备,该选项打开后,EEPROM也就打开了。2. 修改代码修改文件: linux/arch/arm/mach-s3c2440/mach-smdk2440.c增加如下代码片段:#includestaticstructat24_platform_dataat24c02={.byte_len=SZ_2K/8,.page_size=8,.flags=0,};staticstructi2c_board_info__initdatasmdk_i2c_devices[]={/*moredevicescanbeaddedusingexpansionconnectors*/{I2C_BOARD_INFO("24c02",0x50),.platform_data=&at24c02,},};在smdk2440_machine_init函数中增加如下:i2c_register_board_info(0,smdk_i2c_devices,ARRAY_SIZE(smdk_i2c_devices)); 注意:上面许多参数是根据at24c02的参数来设置的,at24c02使用8位地址,内存大小2K比特位,也就是256K字节,页大小为8字节。最后,需要注意,手册中at24c02的设备地址是0b 1 0 1 0 0 0 0 R/W, 其最低位是读写标志位,但是在Linux中,I2C设备地址的最高位为0,而低七位地址就是手册中去掉R/W的剩余7位。因此,地址为0b 01010000(0x50)3. 测试代码 系统启动后,如果一切正常。会在/sys文件系统下展示出该设备,如下:[root@yj4230-0050]#pwd/sys/devices/platform/s3c2440-i2c/i2c-0/0-0050[root@yj4230-0050]#lsbus eeprom namesubsystemdriver modaliaspower uevent[root@yj4230-0050]#cat name24c02其中eeprom即为驱动导出的bin属性,通过读写eeprom即可访问设备,如下:[root@yj4230-0050]#cat eepromi2ci2c-0: master_xfer[0] W, addr=0x50, len=1i2ci2c-0: master_xfer[1] R, addr=0x50, len=128i2ci2c-0: master_xfer[0] W, addr=0x50, len=1i2ci2c-0: master_xfer[1] R, addr=0x50, len=128!"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

    时间:2019-01-14 关键词: eeprom s3c2440 at24c02 linux驱动 移植

  • 移植标准Linux到 S3C2410简介

    1引言目前 , 在嵌入式系统里基于ARM核的嵌入式处理器已经成为市场主流。随着ARM技术的广泛应用 , 建立面向ARM构架的嵌入式操作系统也就成为当前研究的热点。S3C2410是SAMSUNG公司基于ARM920T处理器内核开发的一款16/32位嵌入式处理器,运行频率高达200多M,具有MMU和高速缓存等丰富片上资源,是目前基于ARM920T内核的出货量最大的一款芯片。目前嵌入式操作系统也较多,如 Tor2nado 的VxWork、微软的 Windows CE等等。大量开发人员选择的却都是Linux,这是因为它源代码开放,可以轻松修改移植到自己的目标平台系统里使用。并且事实证明,效果令人满意。两者的结合必将在嵌入式系统的世界里打出一片天地。2 Linux操作系统的移植2.1移植的含义要使得标准Linux能在ARM嵌入式处理器上运作,势必要经过移植 (porting) 的过程。所谓移植,就是让一套软件可以在一套选定硬件平台上正常运作,也就是要将平台相依 (platform dependent) 的部分做适当的修改。内核源码arch子目录包括了所有和平台体系结构相关的核心代码,它的每一个子目录都代表所支持的一种体系结构,arm就是关于我们所选处理器体系结构的子目录。我们的移植工作主要集中于此目录下。2.2移植的具体实现如果我们已经搭建起完整的交叉编译平台,移植工作便可开始了(以当前使用最广的linux-2.4为例,放于/usr/src/ linux-2.4.18之下)。/ Makefile文件一个工程往往包含很多的文件,按照一定的规则放在多个目录中。Makefile文件用来指定编译规则,例如哪些需要编译,哪些要先编译。在此处要做的是:指定目标平台ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)设置为ARCH :=arm指定交叉编译器CROSS_COMPILE =设置为CROSS_COMPILE =arm-linux-/arch/arm/Makefile启动代码的产生要通过此一文件,由于2.4内核还没有对S3C2410的支持,自行加入如下代码ifeq ((CONFIG_ARCH_ S3C2410),y)TEXTADDR = xxxMACHINE = s3c2410EndifTEXTADDR是内核的虚拟起始地址[6],也是内核最终运行地址,通常设为PAGE_OFFSET +0x8000,须根据实际情况相结合[2]。/arch/arm/config.inconfig.in是配置文件,决定了我们在配置菜单中看到的内容。自行加入$CONFIG_ARCH_S3C2410子选项[5]。if [ "$CONFIG_ARCH_S3C2410" = "y" ]; thencomment'Archimedes/A5000 Implementations'dep_bool 'SMDK (MERI TECH BOARD) 'CONFIG _S3C2410_SMDK//$CONFIG_ARCH_S3C2410//其他fi在if [ "$CONFIG_FOOTBRIDGE_HOST" = "y" -o …… "$CONFIG_ARCH_SA1100" = "y" ]; then define_bool CONFIG_ISA yelse define_bool CONFIG_ISA nfi中依样加入"$CONFIG_ARCH_s3c2410" = "y"-o。/arch/arm/boot/MakefileZTEXTADDR 是解压前image.rom的位置,ZRELADDR是内核解压并最终执行的位置。ZRELADDR与TEXTADDR之间符合如下映射关系:__virt_to_phys(TEXTADDR) == ZRELADDR[6]。ifeq ((CONFIG_ARCH_s3c2410),y)ZTEXTADDR = xxxZRELADDR = xxxEndif/arch/arm/boot/compressed/Makefile依样加入 ifeq ("$(CONFIG_ARCH_S3C2410),y)OBJS +=head-s3c2410.oendif/arch/arm/boot/compressed/head-s3c2410.s此处需要自行加入内核解压前处理器初始化文件head-s3c2410.s,示例代码: .section ".start", "ax"__S3C2410_start: bic r2, pc, #0x1f @清除pc相关位,放于r2 add r3, r2, #0x40001: ldr r0, [r2], #32 teq r2, r3 bne 1b mcr p15, 0, r0, c7, c10, 4 @ 写回 Write Buffer mcr p15, 0, r0, c7, c7, 0 @ 刷新 I & D caches#if 0@ 禁用MMU ,caches ……#endif mov r0, #0x002000001: subs r0, r0, #1 bne 1b/arch/arm/kernel/ Makefile依样将$(CONFIG_ARCH_2400) $(CONFIG_ARCH_2410) 加入no-irq-arch :=$(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) ……$(CONFIG_ARCH_AT91RM9200并添加 obj-$(CONFIG_MIZI) += ecard.o obj-$(CONFIG_ARCH_APM) +=apm2.o/arch/arm/kernel/entry-armv.S此文件主要定义CPU初始化时中断处理部分[6],可参考处理器使用手册,按处理器使用要求设置。/arch/arm/kernel/debug-armv.S此文件用于最基本的串口调试功能[6],包括调试串口的地址初始化、发送、等待、忙状态定义等。使用此文件可以在启动过程中打印出相关信息。/arch/arm/kernel/setup.c在此文件中要根据使用的板子设置几个变量[5]。nr_banks指定了内存块的数量,bank指定了每块内存块的范围,PAGE_OFFSET是内存起始地址,MEM_SIZE是内存的大小。PAGE_OFFSET,MEM_SIZE要在/include/asm-arm/arch-s3c2410中定义。/arch/arm/mm/mm-armv.c此文件用于与硬件相关的内存管理,如初始化内存页表内存映射等。将init_maps->bufferable = 0;改为 init_maps->bufferable = 1;/arch/arm/mach-s3c2410建立相应目录并按照处理器使用要求编写irq.c,mm.c,time.c,arch.c,Makefile,分别实现中断控制器的初始化,地址的虚实映射关系,时钟中断和实时时钟处理以及有关Ramdisk使用参数等的设置。/include/asm-arm/arch-s3c2410 此目录下定义用到的头文件。至此移植工作基本完成,再进行如下编译过程,即可得到我们需要的映像文件[4]。make dep; make clean; make zImage3完整系统的构成要想让linux真正跑起来,还需要根文件系统的支持,常用的方法是Ramdisk。Ramdisk 是通过将计算机的内存(RAM)模拟作设备来创建和挂装文件系统的一种驱动器机制。一般应包括以下目录内容: /dev(设备文件目录); /proc (proc 文件系统目录);/etc(系统配置文件的目录); /sbin(系统程序的目录);/bin(基本应用程序目录);/lib(共享函数库的目录);/mnt (装载其他磁盘节点的目录);/usr(附加应用程序的目录)[3]。除此之外一个完整的嵌入式系统还要有引导代码,如vivi,u_boot等。Bootloader也需要移植与编译,在此并不详述。以上三块内容都准备好,对FLASH做好区间的划分[1]以后,便可以用 FLASH 烧写工具依次将Bootloader,内核以及根文件系统烧写到 FLASH里。然后就可以启动系统了。系统从0 地址处开始执行Bootloader。Bootloader做完相关硬件初始化工作之后从 FLASH里把压缩的内核映象复制到SDRAM内并且把根文件系统所在地址参数传递给内核[1]。内核复制到SDRAM之后进行内核解压启动。内核启动过程中根据 Bootloader传递过来的地址参数去寻找根文件系统 , 将其加载到嵌入式系统上。这样,整个Linux被引导启动起来 , 进入正常工作状态。4结束语本文作者创新点:现在采用较为普遍的2.4版本的Linux并没有包含进对S3C2410的支持,给基于此的嵌入式系统的开发带来不便。本文在了解了移植过程中普遍存在的问题和作者经验教训积累的基础上,详尽分析了如何将Linux2.4移植到ARM平台的嵌入式系统上的主要技术,使得该系统可以很好的支持目标平台,并且移植后的Linux 很好的保留了原有的工作稳定的特点。在移植过程中强调其原理与可操作性,对加深对于Linux内核的理解和开发嵌入式系统是十分重要的,对于开发其他嵌入式系统具有参考意义。参考文献 ( References)[1]刘晶晶,基于ARM-Linux嵌入式系统引导程序的设计[J],微计算机信息,2006,2-2:123-125[2]李明,ARM Linux 的移植过程及分析,电子设计应用[J],2003,7:55-57[3]徐虹等,操作系统实验指导[M],北京:清华大学出版社,2002,5[4]张杰,曹卫华,吴敏,施卫强,基于S3C2410的Linux移植[J],微机发展, 2005(15),6:142-144[5]孙天泽,袁文菊,张海峰,嵌入式设计及Linux驱动开发指南[M],北京:电子工业出版社,2005,9[6]Wookey and Tak-Shing,Porting the Linux Kernel to a New ARM Platform,SOLUTIONS JOURNAL,2002,4:52-57

    时间:2019-01-11 关键词: s3c2410 标准linux 移植

  • UC_COS移植到STM32

    1 在外设篇里面的点亮液晶屏(17)的基础上移植液晶屏1 下载GUI解压放到工程的根目录下图片12 将GUI里面的文件夹全部添加到工程文件里面。图片23 把GUI里面每个文件夹里面的文件加入到工程。 1 在添加Config的时候,因为Config里面都是头文件所以需要选择Allfile文件类型然后在选择全部文件添加。 2 字体先不添加,以后编译的时候需要那个字体在添加那个字体。 3 添加不带操作系统的延时函数文件GUI_X.c 4 添加图片文件的时候JPGE文件夹下面还有两个文件夹DOC和Image不需要添加,只需要添加JPGE下面的点C文件。 5 液晶屏驱动文件LCDDriver下面的文件先不添加,因为我们用的液晶屏驱动UC_COS不支持,需要我们自己改写。 6 现在我们先不加触摸。 7 UC_GUI是可以裁剪的,比如Widget控件没用上的我们可以去掉。 8 添加完成后的工程图像 4 设置头文件路径,设置完成后如下图。5 配置UC_GUI主要在Config文件里面 1 GUIConf.h 设置 #define GUI_OS (0) /* éè???a2?′?2ù×÷?μí3Compile with multitasking support */ #define GUI_SUPPORT_TOUCH (0) /* ′¥?t?è2??§3?Support a touch screen (req. win-manager) */ #define GUI_SUPPORT_MOUSE (0) /* °′?¥Support a mouse */ #define GUI_SUPPORT_UNICODE (0) /* ×?·?ò2?è1?±?Support mixed ASCII/UNICODE strings */全部关闭的目的是把系统最小化,一步一步来移植。#define GUI_DEFAULT_FONT &GUI_Font6x8 //UC_GUI默认一个字体现在我们把这个字体加上。#define GUI_ALLOC_SIZE 12500 /*动态内存管理 Size of dynamic memory ... For WM and memory devices*/#define GUI_WINSUPPORT 1 /* 视窗管理先保留Window manager package available */#define GUI_WINSUPPORT 1 /* 视窗管理Window manager package available */#define GUI_SUPPORT_MEMDEV 0 /* 内存管理Memory devices available */#define GUI_SUPPORT_AA 0 /* 抗锯齿Anti aliasing available */LCDConf.c文件修改#define LCD_XSIZE (240) /*设置触摸屏尺寸x轴 X-resolution of LCD, Logical coor. */#define LCD_YSIZE (320) /* 设置触摸屏尺寸Y轴 Y-resolution of LCD, Logical coor. */这里表示2.4寸和3.2寸触摸屏大小的设置方式刚好就是240和320#define LCD_BITSPERPIXEL (16) //像素是16#define LCD_CONTROLLER 9325 //驱动20分钟15秒

    时间:2019-01-04 关键词: STM32 uc_cos 移植

  • 几步实现stm32上面移植mqtt

    最近项目需要,stm32上面使用到mqtt了,百度了下,发现网上资料还是挺少的,虽然有几份相关的资料,下载下来之后,看到了mqtt的底层代码竟然还有错误,这个问题导致了我后面一直调试不通,后来,我直接从官方下载了mqtt的源码用比较器比较后找到了原因,最后果断将官方的mqtt底层代码移植上来,mqtt的发布还是比较顺利,订阅虽然可以收到消息,但是由于没有移植os,发布消息时,订阅接受有时无法收到消息,这个还在优化,我使用的是stm32f103c8t6平台+w5500.其实只要带以太网接口就行。首先我们从mqtt官方下载源码http://git.eclipse.org/c/paho/org.eclipse.paho.mqtt.embedded-c.git/refs/下载后将MQTTPacket下面的src文件都加入到自己的MDK工程中。如果采用W5500的话,最好先用官方的TCP例子将TCP调试通,而且能保证访问外网,可以借鉴下网上那个STM32F405+W5500的例子,我觉得那个还是挺好的,我也是主要借鉴了那个例子,不过我还是不太喜欢他把TCP的建立封装到mqtt里面,一开始我也是采用他那种方法,不过一直出错,后来我采用了状态机实现,先让TCP和mqtt服务器建立TCP连接在调用mqtt的连接,发布等API,这样比较好调试。调试的话,我采用的是下面那个页面调试的http://m2m.demos.ibm.com/mqttclient/#log其实真正要你实现的mqtt接口,主要是transport.c里面的几个APIint transport_sendPacketBuffer(unsigned char* buf, int buflen){return send(SOCK_MQTT,buf,buflen);}/*** @brief×èè?·?ê??óê?TCP·t???÷·¢?íμ?êy?Y* @parambuf êy?Y′?′¢ê×μ??·* @paramcount êy?Y?o3???3¤?è* @retval D?óú0±íê??óê?êy?Y꧰ü*/int transport_getdata(unsigned char* buf, int count){return recv(SOCK_MQTT,buf,count);}/*** @brief′ò?aò???socket2¢á??óμ?·t???÷* @param?T* @retval D?óú0±íê?′ò?a꧰ü*/int transport_open(void){int32_t ret;//D??¨ò???Socket2¢°ó?¨±?μ????ú5000ret = socket(SOCK_MQTT,Sn_MR_TCP,4500,Sn_MR_ND);if(ret != SOCK_OK){ printf("%d:Socket Errorrn",SOCK_MQTT);}else{ printf("%d:Openedrn",SOCK_MQTT);}//á??óTCP·t???÷ret = connect(SOCK_MQTT,domain_ip,1883);//???ú±?D??a1883if(ret != SOCK_OK){ printf("%d:Socket Connect Errorrn",SOCK_MQTT);}else{ printf("%d:Connectedrn",SOCK_MQTT);} return ret;}/*** @brief1?±?socket* @param?T* @retval D?óú0±íê?1?±?꧰ü*/int transport_close(void){close(SOCK_MQTT);return 0;}以上的其实transport_open(void)我没调用,让状态机来实现了这步。int mqtt_publish(char *pTopic,char *pMessage){int32_t len,rc;MQTTPacket_connectData data = MQTTPacket_connectData_initializer;unsigned char buf[200];MQTTString topicString = MQTTString_initializer;int msglen = strlen(pMessage);int buflen = sizeof(buf);data.clientID.cstring = "Client74925";data.keepAliveInterval = 15;data.cleansession = 1;len = MQTTSerialize_connect(buf, buflen, &data); /* 1 */topicString.cstring = pTopic;len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen); /* 2 */len += MQTTSerialize_disconnect(buf + len, buflen - len); /* 3 */rc = transport_sendPacketBuffer(buf,len); if (rc == len) printf("Successfully publishednr"); else printf("Publish failednr");return 0;}=========================================void do_tcp_client(void){ uint8 connect_State = 0; uint16 len1; switch(getSn_SR(SOCK_MQTT)) /*??è?socketμ?×′ì?*/ { case SOCK_CLOSED: /*socket′|óú1?±?×′ì?*/ socket(SOCK_MQTT,Sn_MR_TCP,local_port++,Sn_MR_ND); break; case SOCK_INIT: /*socket′|óú3?ê??ˉ×′ì?*/ connect(SOCK_MQTT,domain_ip,1883); /*socketá??ó·t???÷*/ break; case SOCK_ESTABLISHED: /*socket′|óúá??ó?¨á¢×′ì?*/ memset(buff,0,500); #if 0 connect_State=mqtt_subscrib("planets/earth",buff); if(connect_State) { printf("%s",buff); } #endif if(heartbeatflag>=TIME_5S) { heartbeatflag=0; mqtt_publish("planets/earth","firstName: Brett, lastName:McLaughlin,email:aaaa"); } break; case SOCK_CLOSE_WAIT: /*socket′|óúμè′y1?±?×′ì?*/ close(SOCK_MQTT); break; }}上面的发布我每5s发送一条消息,公司的电脑加密了,无法截图,只能copy下网页测试的数据============================================================================(06:23:57.487) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.492) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:02.810) >> [planets/earth][retained] Hello world!(06:24:02.810) Subscribed to [planets/earth][qos 0](06:24:07.501) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:12.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:17.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:22.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:27.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:32.481) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:37.490) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:42.497) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa(06:24:47.491) >> [planets/earth] firstName: Brett, lastName:McLaughlin,email:aaaa订阅消息的函数目前暂且不公布,主要是还在优化,其次我觉得有点鸡肋,以其误导大伙,还不如不公开~~~~~~~~~~~~,如果大伙觉得有意思,可以把mqtt的ping也加上去,如果实用的话,这个还需要加入很多容错机制~~~~~~~~~~~~

    时间:2019-01-04 关键词: STM32 mqtt 移植

  • ARM移植MPlayer

    奋斗了一晚上,多方查找资料,终于将MPlayer交叉编译成功了,小记经验于此。MPlayer版本:MPlayer-1.0rc2.tar.bz2;交叉编译器:cross-3.2.tar.bz21 在我的主目录中解压Mplayer2 安装交叉编译器,将cross-3.2.tar.bz2以root权限拷贝到/目录执行解压操作3 cd Mplayer目录4 修改stream.c,注释掉//#ifdef USE_DVDREAD//extern stream_info_t stream_info_dvd;//#endif//#ifdef USE_DVDREAD// &stream_info_dvd,//#endif原因见5,都是关于dvd的错误。5 ./configure --host-cc=gcc --cc=arm-linux-gcc --target=arm-armv4l-linux --enable-static --disable-win32dll --disable-dvdread --disable-dvdread-internal --disable-dvdnav --disable-libdvdcss-internal --enable-fbdev --disable-mencoder --disable-live 2>&1 | tee logfile注意:--host-cc=gcc要加,不然会出现codec-cfg无法执行的错误。 disable掉所有在configure中的关于dvd的选项,一方面我在嵌入式平台上用不着dvd,另一方面如果不去掉这些dvd的选项,会出现以下错误。/usr/include/netinet/in.h:259: error: parse error before '(' token/usr/include/netinet/in.h:259: error: parse error before "__u32"/usr/include/netinet/in.h:260: error: parse error before '(' token/usr/include/netinet/in.h:260: error: parse error before "__u16"/usr/include/netinet/in.h:262: error: parse error before '(' token/usr/include/netinet/in.h:262: error: parse error before "__u32"/usr/include/netinet/in.h:264: error: parse error before '(' token/usr/include/netinet/in.h:264: error: parse error before "__u16"6 make7 哈哈,我可爱的mplayer终于将生了!感谢下面三个链接:http://blog.chinaunix.net/u/28484/showart_324583.htmlhttp://www.eetop.cn/bbs/thread-55200-1-1.htmlhttp://readlist.com/lists/mplayerhq.hu/mplayer-users/2/11390.html

    时间:2019-01-04 关键词: ARM mplayer 移植

  • UCOS在S3C2410上的移植

    反反复复弄了一个多星期,参考了不少资料,终于让UCOS在自己的板子上跑起来了。期间遇到了不少问题,还好坚持下来,挺 了过去.....复习一下,记录下来,以当后用: 1.在ADS中建产工程,进入工程界面后,先建立两个组,一个为命名为UCOSII,另一个为S3C2410。UCOSII,下再建两个组,一个为ARM,添加移植要修改的三个文件,另一个sourc则添加与处理器无关的 UCOS源文件。S3C2410下主要存放一些与开发板初始化等有关的文件。2.移植的重点主要在三个有处理器有关的文件OS_CPU.H,Os_cpu_a.s 和Os_cpu_c.c三个文件的编写。(1)根据书上的移植说明及相关的参考文件,OS_CPU.H的编写最简单,主要是定义一些数据类型以及开关中断的 方法等;(2) Os_cpu_c.c这个文件中,有不少钩子函数,都默认为空函数即可,无需编写.只有一个很重要的函数需要动手编写,即任务堆栈初始化函数 OSTaskStkInit,它在任务创建时用来对任务堆栈的初始化工作,可以采用软中断或函数调用的方式来完成.OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt){ OS_STK *stk; opt = opt; /* 'opt' is not used, prevent warning */ stk = ptos; /* Load stack pointer */ *(stk) = (OS_STK)task; /* Entry Point */ *(--stk) = (INT32U)0; /* LR */ *(--stk) = (INT32U)0; /* R12 */ *(--stk) = (INT32U)0; /* R11 */ *(--stk) = (INT32U)0; /* R10 */ *(--stk) = (INT32U)0; /* R9 */ *(--stk) = (INT32U)0; /* R8 */ *(--stk) = (INT32U)0; /* R7 */ *(--stk) = (INT32U)0; /* R6 */ *(--stk) = (INT32U)0; /* R5 */ *(--stk) = (INT32U)0; /* R4 */ *(--stk) = (INT32U)0; /* R3 */ *(--stk) = (INT32U)0; /* R2 */ *(--stk) = (INT32U)0; /* R1 */ *(--stk) = (INT32U)p_arg; /* R0 : argument ARM的第一个参数存放在R0中 */ *(--stk) = (INT32U)0x00000013L; /* CPSR (SVC mode, Enable both IRQ and FIQ interrupts) */ return (stk);}(3).Os_cpu_a.s文件中需要编写四个汇编函数: OSStartHighRdy, OSCtxSw, OSTickISR , OSIntCtxSw;*********************************************************************************************************/IMPORT OSRunning //在本文件中要用到别的文件中定义的变量,要IMPORT导入IMPORT OSTCBCurIMPORT OSTCBHighRdyIMPORT OSPrioCurIMPORT OSPrioHighRdyIMPORT OSIntNestingIMPORT OSIntEnterIMPORT OSIntExitIMPORT OSTaskSwHookIMPORT OSTimeTickIMPORT HandleEINT0EXPORT OSStartHighRdy //在本汇编文件中定义实现的函数或变量用EXPORT导出,在别的文件中只要用时,EXPORT OSCtxSw //用extern(.c文件)或IMPORT(.S文件)声明EXPORT OSTickISREXPORT OSIntCtxSwEXPORT OSCPUSaveSREXPORT OSCPURestoreSREXPORT OS_CPU_IRQ_ISRAREA UCOS_ARM, CODE, READONLY;*********************************************************************************************************; START MULTITASKING; void OSStartHighRdy(void);; The stack frame is assumed to look as follows:;; Entry Point(Task Name) (High memory); LR(R14); R12; R11; R10; R9; R8; R7; R6; R5; R4; R3; R2; R1; R0 : argument; OSTCBHighRdy->OSTCBStkPtr --> CPSR (Low memory);; Note : OSStartHighRdy() MUST:; a) Call OSTaskSwHook() then,; b) Set OSRunning to TRUE,; c) Switch to the highest priority task.;********************************************************************************************************** */OSStartHighRdy;----------------------------------------------------------------------------------; 下面的代码功能:OSRunning = TRUE;;----------------------------------------------------------------------------------MSR CPSR_cxsf,#SVCMODE|NOINT ;Switch to SVC mode with IRQ&FIQ disableBL OSTaskSwHook ;Call user define Task switch hookLDR R0, =OSRunning ; OSRunning =TRUEMOV R1, #1STRB R1, [R0]

    时间:2019-01-03 关键词: s3c2410 ucos 移植

  • ucos ii的51单片机移植

    1. μC/OS-Ⅱ概述μC/OS-Ⅱ在特定处理器上的移植大部分工作集中在多任务切换的实现上,这部分代码主要用来保存和恢复处理器的现场。但许多操作如读/写寄存器不能用C语言而只能用汇编来实现。将μC/OS-Ⅱ移植到ARM处理器上,只需要修改与处理器相关的3个文件:OS_CPU.H,OS_CPU_C.C,OS_CPU_A.ASM。2. OS_CPU.H的移植1)数据类型的定义typedef unsigned char BOOLEAN;typedef unsigned char INT8U;typedef signed char INT8S;typedef unsigned short INT16U;typedef signed short INT16S;typedef unsigned int INT32U;typedef signed int INT32S;typedef float FP32;typedef double FP64;typedef unsigned int OS_STK;typedef unsigned int OS_CPU_SR;2) ARM处理器相关的宏定义#define OS_ENTER_CRITICAL() ARMDisableINT#define OS_EXIT_CRITICAL() ARMEnableINT3)堆栈增长方向的定义#define OS_STK_GROWTH 13. OS_CPU_C.C的移植1)任务椎栈初始化任 务椎栈初始化函数由OSTaskCreat()或OSTaskCreatEXT()调用,用来初始化任务并返回新的堆栈指针STK.初始状态的堆栈模拟发 生一次中断后的堆栈结构,在ARM体系结构下,任务堆栈空间由高到低将依次保存着PC,LR,R12…R0,CPSR,SPSR。堆栈初始化结束 后,OSTaskSTKInit()返回新的堆栈栈顶指针OSTaskCreat()或OSTaskCreatEXT()将新的指针保存的OS_TCB 中。OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt){ OS_STK *stk; opt = opt; /* 'opt' is not used, prevent warning */ stk = ptos; /* Load stack pointer */*stk = (OS_STK)task; /* Entry Point */ *--stk = 0; /* R14 (LR) */ *--stk = 0; /* R12 */ *--stk = 0; /* R11 */ *--stk = 0; /* R10 */ *--stk = 0; /* R9 */ *--stk = 0; /* R8 */ *--stk = 0; /* R7 */ *--stk = 0; /* R6 */ *--stk = 0; /* R5 */ *--stk = 0; /* R4 */ *--stk = 0; /* R3 */ *--stk = 0; /* R2 */ *--stk = 0; /* R1 */ *--stk = unsigned int pdata; /* R0 */ *--stk = USER_USING_MODE|0X00; *--stk = 0; /* OSEnterSum */ return (stk);}2)系统Hook()函数这些函数在特定的系统动作时被调用,允许执行函数中的用户代码。这些函数默认是空函数,用户根据实际情况添加相关代码。OSInitHookBegin()OSInitHookEnd()OSTaskCreateHook()OSTaskDelHook()OSTaskIdleHook()OSTaskStatHook()OSTaskStkInit()OSTaskSwHook()OSTCBInitHook()OSTimeTickHook()4. OS_CPU_A.ASM的移植1)退出临界区和进入临界区代码它们分别是退出临界区和进入临界区代码的宏实现,主要用于在进入临界区之前关闭中断,在退出临界区后恢复原来的中断状态。ARMDisableINT MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts ORR R1,R0,#NO_INT MSR CPSR_c,R1 MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags AND R1,R1,#NO_INT CMP R1,#NO_INT BNE OS_CPU_SR_Save ; Not properly disabled (try again) BX LR ; Disabled, return the original CPSR contents in R0ARMEnableINT MSR CPSR_c,R0 BX LR2)任务级任务切换任 务级任务切换函数OS_TasK_Sw()是当前任务因为被阻塞而主动请求CPU高度时被执行的,由于此时的任务切换都是在非异常模式直进行的,因此区别 于中断级别的任务切换。它的工作是先将当前任务的CPU现场保存到该任务的堆栈中,然后获得最高优先级任务的堆栈指针,从该堆栈中恢复此任务的CPU现 场,使之继续运行,从而完成任务切换。OSCtxSw; SAVE CURRENT TASK'S CONTEXTSTMFD SP!, {LR} ; Push return addressSTMFD SP!, {LR}STMFD SP!, {R0-R12} ; Push registersMRS R4, CPSR ; Push current CPSRTST LR, #1 ; See if called from Thumb modeORRNE R4, R4, #0x20 ; If yes, Set the T-bitSTMFD SP!, {R4}LDR R4, OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP;LDR R5, [R4]STR SP, [R5]LDR R0, OS_TaskSwHook ; OSTaskSwHook();MOV LR, PCBX R0LDR R4, OS_PrioCur ; OSPrioCur = OSPrioHighRdyLDR R5, OS_PrioHighRdyLDRB R6, [R5]STRB R6, [R4]LDR R4, OS_TCBCur ; OSTCBCur = OSTCBHighRdy;LDR R6, OS_TCBHighRdyLDR R6, [R6]STR R6, [R4]LDR SP, [R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;;STORE NEW TASK'S CONTEXTLDMFD SP!, {R4} ; Pop new task's CPSRMSR SPSR_cxsf, R4LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context3)中断级任务切换函数①该 函数由OSIntExit()和OSExIntExit()调用,它若在时钟中断ISR中发现有高优先级任务等特的时候信号到来,则需要在中断退出后并不 返回被中断的,的而是直接调度就绪的高高优先级任务执行.这样做的目的主要是能够尽快的让优先级高的任务得到响应,进而保证系统的实时性。OSIntCtxSwLDR R0, OS_TaskSwHook ; OSTaskSwHook();MOV LR, PCBX R0LDR R4, OS_PrioCur ; OSPrioCur = OSPrioHighRdyLDR R5, OS_PrioHighRdyLDRB R6,[R5]STRB R6,[R4]LDR R4,OS_TCBCur ; OSTCBCur = OSTCBHighRdy;LDR R6,OS_TCBHighRdyLDR R6,[R6]STR R6,[R4]LDR SP,[R6] ; SP = OSTCBHighRdy->OSTCBStkPtr;; RESTORE NEW TASK'S CONTEXTLDMFD SP!, {R4} ; Pop new task's CPSRMSR SPSR_cxsf, R4LDMFD SP!, {R0-R12,LR,PC}^ ; Pop new task's context② 两

    时间:2019-01-03 关键词: ii 51单片机 ucos 移植

  • S3C2410 LCD 驱动程序移植及GUI程序编写

    1. 为了不让大家觉枯燥,让朋友们更好的理解,我以一个实例来叙述 S3C2410 下一个驱动程序的编写(本文的初始化源码以华恒公司提供的 s3c2410fb.c 为基础)及简单的 GUI程序的编写。2. 拿到一块 LCD,首先要将 LCD的各个控制线与 S3C2410 的 LCD控制信号相接,当然,电源也一定要接入了,否则不亮可别找我。另外需要注意以下几点:1) 背光:对于大部分的彩色 LCD一定要接背光,我们才能看到屏上的内容;2) 控制信号:不同的 LCD 厂商对于控制信号有不同的叫法,S3C2410 芯片手册也给出了一个信号的多个名称(图一),这就要看你们硬件工程师的功底了,0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=0>图一 S3C2410 手册上给出的控制信号的名称及解释这里我做一个简单的介绍:VFRAME:LCD 控制器和 LCD 驱动器之间的帧同步信号。该信号告诉 LCD屏的新的一帧开始了。LCD 控制器在一个完整帧显示完成后立即插入一个VFRAME 信号,开始新一帧的显示;VLINE:LCD控制器和 LCD驱动器之间的线同步脉冲信号,该信号用于 LCD驱动器将水平线(行)移位寄存器的内容传送给 LCD 屏显示。LCD 控制器在整个水平线(整行)数据移入 LCD驱动器后,插入一个 VLINE 信号;VCLK:LCD控制器和 LCD驱动器之间的像素时钟信号,由 LCD控制器送出的数据在 VCLK的上升沿处送出,在 VCLK的下降沿处被 LCD驱动器采样;VM:LCD驱动器的 AC 信号。VM 信号被 LCD驱动器用于改变行和列的电压极性,从而控制像素点的显示或熄灭。VM 信号可以与每个帧同步,也可以与可变数量的 VLINE 信号同步。3) 数据线:也就是我们说的 RGB 信号线,S3C2410 芯片手册上都有详细的说明,由于篇幅关系,在此不一一摘录,不过需要与硬件工程是配合的是他采用了哪种接线方法,24 位 16 位或其它。对于 16 位 TFT 屏又有两种方式,在写驱动前你要清楚是 5:6:5还是 5:5:5:I,这些与驱动的编写都有关系4) 要注意一下 LCD 的电源电压,对于手持设备来说一般都为 5V 或 3.3V,或同时支持 5V和 3.3V,如果 LCD的需要的电源电压是 5V,那就要注意了,S3C2410 的逻辑输出电压只有 3.3V,此时一定要让你们的硬件工程师帮忙把 S3C2410 的逻辑输出电压提高到 5V,否则你可能能将屏点亮,但显示的图像要等到太阳从西边出来的那一天才能正常,呵呵,我可吃过苦头的哦!5) 3.3V逻辑电压转变成 5V逻辑电压电路图(此图由华恒公司提供)0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=0>6) 最后还有一个问题,有些 LCD 屏还需要一颗伴侣芯片,就是 S3C2410 手册中的那颗 LPC3600。这可能在 LCD 的手册中都有论述吧,我没有遇到过这样的屏,所以也不是很清楚。那么是不是所有的屏与 S3C2410相接都需要那个讨厌的家伙呢?这是好多人(包括我)在最开始都会有的疑问,不过现在的大部分 LCD 屏应该都不需要这个讨厌的家伙了,屏的控制信号直接与 S3C2410 的控制信号相接就可以了,至少我还没有遇到过。7) 还得提醒大家一下,S3C2410到 LCD屏的连线千万千万别超过 0.5 米,否则会给你带来麻烦,我也是吃过苦头的,LCD屏上面的部分显示任何信息都是正确的,而只有屏的底部会有时正确有时错误,折腾了好一阵,才知道是连线太长的缘故!3. 好了,在硬件工程师的帮助下,硬件接好了,那就该我们做软件的干活了,编写驱动吧1) 让我们首先看一下 RGB数据结构的定义在 s3c2410fb.c 中找到如下信息static struct s3c2410fb_rgb xxx_tft_rgb_16 = {red: {offset:11, length:5,},green: {offset:5, length:6,},blue: {offset:0, length:5,},transp: {offset:0, length:0,},};这是对 16 位色的 RGB 颜色进行定义,R:G:B:I = 5:6:5:0,即我们常说的565 显示方式。呵呵,为了让有些朋友更好的理解,我多罗嗦几句,我们随便写一个 16 位数据的颜色数据(为了分析的方便,我把它写成二进制)RGB = 10101101 10111001根据上面的结构定义我们来分析一下 RGB 各是多少(因为没有透明色,我们不去分析)a) blue: {offset: 0, length: 5} 偏移量为 0,长度为 5,我们从那个 RGB 中提取出来便是“11001”b) green:{offset: 5, length: 6} 偏移量为 5,长度为 6,我们从那个 RGB 中提取出来便是 101 101c) red: {offset: 11, length: 5 } 偏移量为 11,长度为 5,我们从那个 RGB 中提取出来便是 10101d) 我们得到了一个 RGB 值为 13:45:200,就是这个颜色e) 那么反过来,有了 RGB的值我们该如何,因为 RGB 的有效位数都不足一个字节(8 位),那我们只能忍痛割爱了,舍弃掉低位数据,代码如下r=(rDat&0xF8);g=(gDat&0xFC);b=(bDat&0xF8);hight=r|(g3)|(b8)|low;记住,这段代码在 GUI 程序中是有用的2) 对于 8 位色(256 色)的数据结构定义static struct s3c2410fb_rgb rgb_8 = {red: {offset:0, length:4,},green: {offset:0, length:4,},blue: {offset:0, length:4,},transp: {offset:0, length:0,},};这是原程序中给出的定义,我感觉有些错误,我认为应该为 R:G:B = 3:3:2static struct s3c2410fb_rgb rgb_8 = {red: {offset:5, length:3,},green: {offset:2, length:3,},blue: {offset:0, length:2,},transp: {offset:0, length:0,},};因为没有亲自去调试,所以没有什么发言权,希望做过这方面的朋友给我一个答案。3) 对于 CSTN 屏,一般都能达到 12 位色(4096 色)的,S3C2410 这颗芯片也是支持的,但是在软件方面要做的工作比较大,因为从原有的代码,我们找不到任何 12位色显示的迹象,另外 Linux 本身好像也不支持 12 位色的,如果你要作的事情比较简单,那你就自己写代码吧。我在此给出 12位色的数据结构定义static struct s3c2410fb_rgb xxx_stn_rgb_12 = {red: {offset:8, length:4,},green: {offset:4, length:4,},blue: {offset:0, length:4,},transp: {offset:0, length:0,},};但是要完成 12 位色 CSTN 屏驱动程序的编写还有一些工作要做,稍后我会适当的向大家介绍。4) 接着看下面的代码,其中要修改的部分已经用绿色标出,下面分别进行介绍。0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=0>a) 颜色位数bpp:16如果你的 LCD 屏是 TFT 的,那一般都可以达到 16 位色或 24 位色,这也要看硬件怎么连接了,根据情况进行设置即可;如果你的 LCD屏是 CSTN的,按照常规 LCD手册的介绍,一般都可以支持到8 位色(256色),而实际的 CSTN屏的显示效果都可以达到 12 位色(4096色),那可有很大的区别的,如果你要选择便宜的屏又要丰富的颜色,那就费点劲,完成 12 位色的驱动。b) LCD屏的宽度和高度xres: 240yres: 320这个就不用多说了,你的屏的分辨率是多少就设置成多少呗。c) 寄存器的设置,这些也不困难。下面就让我们一起一口一口的将 S3C2410 的LCD寄存器统统吃掉! 首先介绍一下我这块屏,这是日立的一块 TFT 屏,大小为 640X240,可以支持到 16位色。 与驱动有关的一张表0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=0>图二 LCD屏资料有了这些信息,让我们看一下 LCD寄存器的设置。LCD控制器10 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=0>LINECNT --- 这是一个只读的数据,我们当然没有必要理它CLKVAL --- 这可是一个很有用的参数,其实没必要管它后面的计算,我们可以通过实际的测试来得出一个有效的值,对于320x240 的屏一般设置为 7 就可以了,而对于 640x480 的屏,该值可以小一点。对于后面的计算公式及注释(STN: CLKVAL =510){this.width=510;this.height=image.height*510/image.width;}}" border=0>对于 TFT 屏必须要填,至于什么意思怎么翻译,相信大家都比我的水平强,自己翻译吧。我只说明从 LCD中如何将这个值“扣”出来。很容易,看一下图二 LCD屏资料,对比一下得出如下信息:LCD2_VBPD:Vertical back porch 典型值为 7LCD2_VFPD:Vertical front porch 典型值为 4LCD2_VSPW:Vsync Valid width 典型值为 2关

    时间:2019-01-02 关键词: LCD s3c2410 gui 驱动程序 程序编写 移植

  • Linux-2.6.32.2内核在mini2440上的移植(一)---构建自主开发环境

    移植环境1,主机环境:VMare下CentOS 5.5 ,1G内存。2,集成开发环境:Elipse IDE3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。4,开发板:mini2440,2M nor flash,128M nand flash。5,u-boot版本:u-boot-2009.086,linux 版本:linux-2.6.32.27,参考文章:【1】嵌入式linux应用开发完全手册,韦东山,编著。【2】http://blogold.chinaunix.net/u3/101649/showart_2276906.html【3】Mini2440 之Linux 移植开发实战指南1.1,构建自主开发环境我们在进行u-boot移植时,在u-boot-2009.08在mini2440上的移植(六)---增加引导内核功能提到过机器码(MACH_TYPE),在引导测试时,为了便于测试,使用的是友善官方移植好的linux内核。现在我们将从这里着手,逐步开始linux内核的移植。【1】下载并解压内核源码在命令行终端中可以通过下列方式下载,当然用其它下载工具下载[root@localhost ~]# wgethttp://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.2.tar.gz然后解压:[root@localhost ~]# cd ./linux-test/[root@localhost linux-test]# tar -zxf ../linux-2.6.32.2.tar.gz[root@localhost linux-test]# lslinux-2.6.32.2 linux-2.6.39 yaffs2 yaffs2.tar.gz[root@localhost linux-test]# cd linux-2.6.32.2[root@localhost linux-2.6.32.2]#【2】指定交叉编译变量我们移植目的是让 Linux-2.6.32.2 可以在mini2440 上运行。首先,我们要使得Linux-2.6.32.2 的缺省目标平台成为ARM 的平台,修改总目录下的Makefile。用gedit打开/Makefile,定位到183行,修改如下:# Alternatively CROSS_COMPILE can be set in the environment.# Default value for CROSS_COMPILE is not to prefix executables# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefileexport KBUILD_BUILDHOST := $(SUBARCH)ARCH?= armCROSS_COMPILE?= arm-linux-# Architecture as present in compile.h其中,ARCH 是指定目标平台为arm,CROSS_COMPILE 是指定交叉编译器,这里指定的是系统默认的交叉编译器,如要使用其它的,则要把编译器的全路径在这里写出。注意,在arm和arm-linux-后不要留空格,否则在编译时会出现错误。接下来,要测试一下linux 的编译是否能正常通过。执行:[root@localhost linux-2.6.32.2]# make s3c2410_defconfig使用缺省内核配置文件,s3c2410_defconfig 是SMDK2440 的缺省配置文件[root@localhost linux-2.6.32.2]# make编译时间较长... ... 。编译通过,在此我们先不必烧写到开发板验证它的正确性。【3】建立自己的目标平台(1)关于机器码以上编译是用的 Linux 内核本身支持的目标平台配置,它对应于SMDK2440。现在我们要参考SMDK2440 加入自已的开发板平台,我们使用的是mini2440,因此取名为MINI2440。需要说明的是,Linux-2.6.32.2 本身已经包含了mini2440 的支持,这样就出现了重名。那怎么办呢?在此我们依然使用MINI2440 这个名称,只不过在后面的移植步骤中,把原始内核自带的mini2440 代码部分直接删除就可以了,以免和我们自己移植的混淆。首先,很关键的一点,内核在启动时,是通过bootloader 传入的机器码(MACH_TYPE)确定应启动哪种目标平台的,友善之臂已经为mini2440 申请了自己的机器码为1999,它位于linux-2.6.32.2/arch/arm/tools/mach_types 文件中,如下面所示:打开/arch/arm/tools/mach-types,定位到1989行,可以看到文件中有相应的机器码的定义定义如下(黑体部分):exedaMACH_EXEDAEXEDA1994mx31sf005MACH_MX31SF005MX31SF0051995f5d8231_4_v2MACH_F5D8231_4_V2F5D8231_4_V21996q2440MACH_Q2440Q24401997qq2440MACH_QQ2440QQ24401998mini2440MACH_MINI2440MINI24401999colibri300MACH_COLIBRI300COLIBRI3002000jadesMACH_JADESJADES2001sparkMACH_SPARKSPARK2002benzinaMACH_BENZINABENZINA2003在U-boot/include/asm-arm/mach-types.h 文件的1985行附近(u-boot-2009.08),可以看到mini2440 的机器码定义如下面所示:#define MACH_TYPE_Q2440 1997#define MACH_TYPE_QQ2440 1998#define MACH_TYPE_MINI2440 1999 //mini2440的机器码#define MACH_TYPE_COLIBRI300 2000#define MACH_TYPE_JADES 2001这需要两者相匹配,如果内核的机器码和bootloader 传入的不匹配,就会经常出现下面的错误:Uncompressing Linux................................................................................................................................. done, bootingthe kernel.运行到这不就停住了。接下来, 我们注意到linux-2.6.32.2/arch/arm/mach-s3c2440 目录下有个mach-mini2440.c 文件,它其实就是国外爱好者为mini2440 移植添加的主要内容了,但我们不用它,把它直接删除。将linux-2.6.32.2/arch/arm/mach-s3c2440/目录下的mach-smdk2440.c 复制一份。命名为mach-mini2440.c ,并打开文件定位到末尾处,找到MACHINE_START(S3C2440, "SMDK2440") , 将其修改为MACHINE_START(MINI2440, "Mini2440 development board")提示:开发板运行后,在命令行终端输入:cat /proc/cpuinfo 可以看到我们添加的开发板信息,当然这个信息可以定制成我们需要的信息。(2)修改时钟源频率在上面我们刚刚复制并修改过的mach-mini2440.c文件中,定位到163行附近,把其中的16934400(代表原SMDK2440 目标板的晶振是16.9344MHz)改为mini2440 开发板上实际使用的12000000(代表mini2440 开发板上的晶振12MHz,元器件标号为X2),如下所示: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)从SMDK2440 到MINI2440因为我们要制作自己的mini2440 平台体系,因此把mach-mini2440.c 中所有的smdk2440 字样改为mini2440,可以使用批处理命令修改,在vim 的命令模式下输入:%s/smdk2440/mini2440/g上面这句的意思是:把所有和“smdk2440”匹配的字符串全部替换为“mini2440”,前面的“%s“代表字符串匹配,最后的“g”代表global,是全局的意思,不过这里采用另一种办法,在gedit里用查找替换,比较方便,操作如下:gedit->搜索->替换,在打开的对话框中,在搜索一栏输入“smdk2440”,在替换为一栏输入“mini2440”然后点击全部替换按钮,即可完成。除此之外,还有一个地方需要改动,在mini2440_machine_init(void)函数中,把smdk_machine_init()函数调用注释掉,因为我们后面会编写自己的初始化函数,不需要调用smdk2440 原来的,定位到173行,修改如下:static void __init mini2440_machine_init(void){s3c24xx_fb_set_platdata(&mini2440_fb_info);s3c_i2c0_set_platdata(NULL);platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));//smdk_machine_init();}(4)编译测试在 Linux 源代码根目录下执行[root@localhost linux-2.6.32.2]# make mini2440_defconfig## configuration written to .config#[root@localhost linux-2.6.32.2]# make mini2440_defconfig使用Linux 官方自带的mini2440 配置。[root@localhost linux-2.6.32.2]# make uImage编译内核,时间较长,最后会生成uImage。把生成的内核文件uImage(位于arch/arm/boot 目录)下载到板子的内存中运行,可以看到内核已经可以正常启动了,如下所示,但此时大部分硬件驱动还没加,并且也没有文件系统,因此还无法登陆。[u-boot@MINI2440]# usbslaveUSB host is connected. Waiting a download.Now, Downloading [ADDRESS:31000000h,TOTAL:2067310]RECEIVED FILE SIZE: 2067310 (672KB/S, 3S)[u-boot@MINI2440]# go 0x31000000## Starting application at 0x31000000 ...Uncompressing Linux................................................................................................................................ done, booting the kernel.Linux version 2.6.32.2 (root@localhost.localdomain) (gcc version 4.4.3 (ctng-1.6.1) ) #4 Thu May 26 18:51:55 CST 2011CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=00007177CPU: VIVT data cache, VIVT instruction cacheMachine: mini2440 devolopment boardMemory policy: ECC disabled, Data cache writebackCPU S3C2440A (id 0x32440001)S3C24XX Clocks, (c) 2004 Simtec ElectronicsS3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHzCLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL onBuilt 1 zonelists in Zone order, mobility grouping on. Total pages: 16256Kernel command line: noinitrd console=ttySAC0,115200 init=/linuxrc mem=64M root=/dev/nfs rw nfsroot=10.1.0.128:/nfsboot ip=10.1.0.129:10.1.128:10.1.0.1:255.255.255.0::eth0:off... ...【4】内核配置菜单中的mini2440 选项和实际代码是如何关联的在开始移植其他驱动之前,我们再了解一些看起来比较“神秘”的常识,那就是运行make menuconfig 时,内核配置菜单中的mini2440 选项是如何出现的。需要确保前面已经执行了make mini2440_defconfig 加载了缺省配置,因为在x86平台下下执行此操作,系统默认的是x86平台,而且还要在顶层Makefile里作了如下修改:export KBUILD_BUILDHOST := $(SUBARCH)ARCH?= armCROSS_COMPILE?= arm-linux-现在在终端中进入到linux-2.6.32.2根目录下执行:[root@localhost linux-2.6.32.2]#make menuconfig出现下图所示内核配置根菜单 按上下箭头键移动到 System Type,按回车进

    时间:2018-12-31 关键词: 内核 Linux 开发环境 mini2440 移植

  • 在s3c2410板上移植2.6 kernel

    最近这几天的晚上我在移植2.6的kernel。因为水平很菜,所以不太顺利。 我用的是kernel是2.6.14.2, 这个内核直接支持S3C2410的板子,不必打任何补丁。从www.kernel.org下载了内核。然后找来了3.4.1的GCC交叉编译器(经典的2.95.3编译2.6内核会出错)。解开内核开始修改。(该部分转贴自:http://superlp.blogchina.com/blog/1391393.html感谢superlp)1. 增加nand分区信息 打开arch/arm/mach-s3c2410/devs.c 增加头文件 #include #include #include 增加分区数据 /*****************************add here***************************/ static struct mtd_partition partition_info[] ={ { name: "loader", size: 0x00020000, offset: 0, }, { name: "param", size: 0x00010000, offset: 0x00020000, }, { name: "kernel", size: 0x001c0000, offset: 0x00030000, }, { name: "root", size: 0x00200000, offset: 0x00200000, mask_flags: MTD_WRITEABLE, }, { name: "user", size: 0x03af8000, offset: 0x00400000, } }; struct s3c2410_nand_set nandset ={ nr_partitions: 5 , partitions: partition_info , }; struct s3c2410_platform_nand superlpplatform={ tacls:0, twrph0:30, twrph1:0, sets: &nandset, nr_sets: 1, }; /********************************end add****************************/ struct platform_device s3c_device_nand = { .name = "s3c2410-nand", .id = 0xec, .num_resources = ARRAY_SIZE(s3c_nand_resource), .resource = s3c_nand_resource, .dev = { .platform_data = &superlpplatform //***********add here***** } }; (分区部分根据实际情况修改)2. 打开arch/arm/mach-s3c2410/mach-smdk2410.c 把"&s3c_device_nand"添加到__initdata3. 打开drivers/mtd/nand/s3c2410.c 把chip->eccmode = NAND_ECC_SOFT;改成chip->eccmode = NAND_ECC_NONE;4. 修改Makefile, 把设定SUBARCH := arm CROSS_COMPILE ?= arm-linux-(事先得安装交叉 编译器)接着开始make menuconfig,并且载入arch/arm/configs/def_s3c2410config,保存后就make,如果编译器没有问题得话,应该一次就能编译成功。 接下来编译bootload, 我用vivi, 从www.mizi.com下 载vivi的源代码包,解开后make menuconfig, 载入arch/def-configs/smdk2410, 保存退出后修改arch/s3c2410/smdk.c,修改里面的分区信息和启动参数。分区信息根据实际情况设置,启动参数设置成“noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200 mac=00:0e:3a:aa:bb:cc”. 保存退出后make, 得到vivi的BIN. 把vivi和kernel的BIN文件烧录到FLASH后给板子上电,发现一个问题,vivi并没有使用我设置好的分区信息和启动参数,而是使用一个默认 的值,要使用命令param reset和part reset才可以重置我设置的值。vivi默认的kernel分区大小是1M,而我的kernel的BIN文件有1.2M,开始尝试了好多次都失败。重置 了参数以后kernel可以执行起来, 但是找不到根文件系统,那是当然的,因为我还没有烧录文件系统。一.准备必要的文件我们首先去官方网站下载最新的llinux内核http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.tar.bz2因为linux2.6.14内核需要更新版本的编译器,所以我们需要下载交叉编译器ftp://ftp.handhelds.org/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2注:这个编译器已经包含在光盘的DISK4linux相关linuxtool目录下面。二.安装文件我们把gcc安装在/usr/local/arm/3.4.1目录下,安装方法和安装gcc2.95.3和gcc3.3.2是相同的,(cd /tar jxvf arm-linux-gcc-3.4.1.tar.bz2vi ~/.bash_profile把arm-linux-gcc的路径/usr/local/arm/3.4.1/bin添加到PATH中)接下来需要解压linux内核,输入命令:[root·localhost hfrk]# tar jxvf linux-2.6.14.tar.bz2内核被解压到linux-2.6.14目录下。三.修改makefile文件内核的编译是根据makefile文件的指示进行的,Makefile文件来组织内核的各模块之间的关系,记录了各个模块之间的相互联系和依赖关系。我们首先修改linux-2.6.14的根目录下的makfile文件,我们须改的主要内容是目标代码的类型和为编译内核指定一个编译器。我们注释掉以下内容:#ARCH?= $(SUBARCH)#CROSS_COMPILE?=增加如下内容:ARCH: = armCROSS_COMPILE =/usr/local/arm/3.4.1/bin/arm-linux-四.修改相关的文件。1.修改archarmmach-s3c2410devs.c文件增加头文件定义/***********add here***********/ #include #include #include /**************end add********/增加nand flash分区信息/***********add here***********/static struct mtd_partition partition_info[] ={{name: "loader",size: 0x00020000,offset: 0,}, {name: "param",size: 0x00010000,offset: 0x00020000,}, {name: "kernel",size: 0x001c0000,offset: 0x00030000,}, {name: "root",size: 0x00200000,offset: 0x00200000,mask_flags: MTD_WRITEABLE,}, {name: "user",size: 0x03af8000,offset: 0x00400000,} };

    时间:2018-12-31 关键词: s3c2410 2.6 kernel 移植

  • S3C2416裸机开发系列十四_GCC下UCGUI的移植(2)

    现在主要讲解一下在GCC移植UCGUI,Makefile工程如何加入目录,加入源码,c标准库,编译选项的设置。笔者的Makefile模板提取自uboot,工程中加入目录,加入源码都是很简单的,详细的介绍请参考前面章节” GCC启动代码工程应用实例”。下面主要介绍UCGUI目录下很多的源码文件Makefile的编写,一种可行的方式就是把GUI目录上所有的c文件,不管有无用到,均加入工程进行编译,第一次编译时间较长,但以后不用重复编译。因此这部分的Makefile实现如下:include $(TOPDIR)/config.mkSRCS := $(wildcard *.c)$(wildcard *.C)OBJS := $(SRCS:.c=.o)$(SRCS:.C=.o)CURDIR := $(shell pwd)FOLDER := $(notdir $(CURDIR))LIB := lib$(FOLDER).a.PHONY: all cleanall: .depend $(LIB)$(LIB): $(OBJS) @$(AR) $(ARFLAGS) $@ $(OBJS)clean: rm -f .depend *.o $(LIB)########################################################################## defines$(obj).depend targetinclude$(TOPDIR)/rules.mksinclude .depend#########################################################################把这个Makefile模板加入到GUI下所有的子目录和GUIDemo目录中,其它目录的Makefile也类似编写加入,这样即可把所有要编译的源码加入工程。每个子目录的Makefile需加入该目录下要编译的源码文件,生成该目录下的源码依赖关系文件.depend,最终生成该目录下的静态库文件,以供顶层目录的Makefile链接输出相应的可执行代码文件,工作方式与uboot是完全一致的。修改顶层目录的Makefile,加入各个子目录Makefile的路径,以调用编译该目录下的源码。子目录路径SUBDIRS变量的修改如下:SUBDIRS = $(TOPDIR)/start_code$(TOPDIR)/appsSUBDIRS += $(TOPDIR)/GUI/AntiAlias$(TOPDIR)/GUI/ConvertColor $(TOPDIR)/GUI/ConvertMono $(TOPDIR)/GUI/Core $(TOPDIR)/GUI/Font $(TOPDIR)/GUI/LCDDriver $(TOPDIR)/GUI/MemDev $(TOPDIR)/GUI/MultiLayer $(TOPDIR)/GUI/Widget $(TOPDIR)/GUI/WMSUBDIRS += $(TOPDIR)/GUI_X$(TOPDIR)/GUIDemo修改顶层目录的config.mk,对编译选项如-O2二级编译优化或-g加入调试等进行设置,此处需加入工程c编译器的头文件的搜索路径,对于UCGUI头文件搜索路径只需加入Config、GUI/Core、GUI/Widget、GUI/WM这四个目录路径即可。头文件搜索路径CFLAGS变量的修改如下,s3c2416没有硬件浮点单元,加-msoft-float防止配置成只支持硬浮点的交叉工具通过编译。CFLAGS := -Wall -Wstrict-prototypes -mcpu=arm920t -msoft-floatCFLAGS += -I $(TOPDIR)/start_code -I$(TOPDIR)/appsCFLAGS += -I $(TOPDIR)/GUI/Core -I$(TOPDIR)/GUI/Widget -I $(TOPDIR)/GUI/WM -I $(TOPDIR)/ConfigCFLAGS += -I $(TOPDIR)/GUIDemo设置库,嵌入式开发很大程度上依赖于标准c库。在linux操作系统下,标配的c库为glibc,glibc囊括了几乎所有的UNIX通行标准,可见其内容包罗万象。因此glibc对于很多嵌入式系统来说过于臃肿和庞大,并且很多函数严重依赖于linux的系统调用。笔者在较老版本交叉编译工具开发裸机代码,可以链接glibc,但新版本的工具却无法顺利链接glibc。为了解决glibc在嵌入式应用中的不足,很多面向嵌入式的c标准库已经被开发出来,如uclibc、newlib、eglibc等。这些嵌入式c库特点就是比glibc小很多,相对独立,可不需要操作系统支持,不支持glibc的完整实现,很多功能可以根据空间需求进行取舍。一般开发linux系统,可以用glibc,如果对代码容量等方面有要求,也可使用嵌入式c库。笔者测试用相同的UCGUI移植代码分别链接uclibc和glibc,代码容量差距相当明显,链接uclibc时,可执行代码只有270k,而glibc达到700k。此处采用uclibc作为c库,对于在linux下做开发而采用glibc的读者,可以下载uclibc的最新源码库,通过make menuconfig简单配置,用交叉编译工具编译源码库,即可生成交叉编译工具可使用的c库。嵌入式开发最常使用到字符处理、数学处理方面的库函数,非linux操作系统开发,只能链接静态库,在linux下对应库名为libc.a和libm.a。由于不使用glibc,因此标准c库应指定uclibc的库存放路径。同时,对于没有硬件除法器,浮点处理单元的arm,对取余和除法操作,浮点处理都需要libgcc.a的支持。UCGUI移植用到了这三个库,因此需要在Makefile中指定这三个库的路径,库路径设置如下,对于uclibc中的libc.a和libm.a库路径,需要读者根据自己的嵌入式库路径进行修改。PLATFORM_LIBS :=# 加入uclibc标准c库以及数学函数库PLATFORM_LIBS += -L /opt/crosstool/uClibc-0.9.33.2/lib -lm -lc# 加入gcc库PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS)-print-libgcc-file-name`) –lgcc至此,Makefile工程设置完毕,跳转到顶层目录,执行make即可开始编译工程。编译时产生一大堆错误,主要是提示头文件未找到,micrium给出的GUIDemo目录下的测试代码写的不够严谨,源代码中include头文件名不区分大小写。例如实际要#include“GUI.h”,但有些源码中是#include"GUI.H",这对于windows来说是没有区别的,因为windows文件系统不区分大小写,但linux却是区分大小的,因此会提示找不到文件。windows操作系统假定它的用户是儿童,对一般用户来说,apple和Apple都是苹果,没有区别。但linux/unix操作系统假定它的用户是专业人士,apple和Apple虽然都是苹果,但它们的大小、产地、口感等均是不同的,因此是有区别的。为了代码的可重用,这些问题都是需要注意的,尤其是同时在windows和linux下做开发,应保证一定的规范性。如在windows下文件目录名区分大小写,在linux下文件名加后缀(如.c、.h)表示这个文件的用途等。此处没有好的方法,只能修改GUIDemo下所有不区分头文件名大小写的源码。6. 代码烧录修改编译通过后,会在顶层目录生成三个比较重要的文件,ucgui.map为链接Mapping文件,这里可以看到各个全局符号、各个段内存链接位置、大小等信息。s3c2416.dis为工程的汇编生成文件,这是编译器经过编译所有的源码并进行链接最终给出的汇编文件,这是最权威的查错文件,编译器的bug以及任何用户的失误造成编译器未能很好地按照用户的本意编译等出现的问题,在这里都可以查找出。s3c2416.bin即为我们用来烧录进SD卡或nand等存储器的二进制代码文件。此处说明一点,笔者此系列的裸机例程都是有启动代码的,可以自动从sd/mmc卡、nand启动的,代码的烧录与一般的bootloader的烧录方式无异。最常用的烧录方式是把裸机bin代码通过SdBoot工具进行格式转换,再通过三星sd卡烧写工具IROM_Fusing_Tool把转换后的bin代码烧写进sd卡,设置成sd卡启动即可。从sd卡启动成功后,通过调用相关的Nand模块接口函数,实现代码固化进Nand,以后即可从Nand启动。详细教程请参考笔者前面章节的” GCC启动代码工程应用实例”或” MDK启动代码工程应用实例”。7. 编译工具性能对比笔者采用了相同的UCGUI移植源码在MDK、GCC下进行编译,MDK和GCC均设置成二级优化条件下,对比这两个平台下编译器、标准c库的差异。7.1. 代码容量编译后,MDK下生成的二进制可执行代码大小为250k,而GCC在采用uclibc标准库时可执行代码大小为273k,在老版本的GCC交叉编译工具上,采用glibc生成的代码大小为700k,从代码容量看,MDK生成的代码更小,采用GCC加uclibc并不比商业公司开发的平台工具差很多。在linux下做嵌入式开发,对代码容量、性能有要求的话,无特殊情况,采用嵌入式c库如uclibc、newlib等更适合。7.2. 编译速率均把所有源码加入工程中进行全部编译,MDK下编译时间需225秒,可以明显看到提示窗口的源码在一个一个编译,GCC下编译时间为42秒,源码编译时可看到窗口是在刷屏的,编译速度不是MDK能比的。7.3. 代码生成质量此处并不能准确对比MDK与GCC代码生成质量的优劣,只能以UCGUI多层裁剪测试作为一个对比项。MDK生成的可执行代码裁剪打点速度为11526060 pixel/秒,而GCC生成的可执行代码打点速度为11985690 pixel/秒,打点速度GCC高出4%,可以看出开源免费的GCC编译器以及c库uclibc同样高效优越。对比可以看出,GCC与MDK不分上下,某些方面GCC做的更好,如编译速度。当然,MDK还有必杀技MicroLIB,这是MDK专为arm嵌入式应用高度优化的库,用了这个外挂库后,任何其它编译器的标准c库都暗然失色,当然只能够支持部分c库的实现。总体来说,对于移植平台多、开源免费的GNU软件来说,能达到丝毫不输商业软件的性能,确实令人尊敬,选择GNU软件进行开发也是相当不错的。移植后的UCGUI效果:8. 附录对于ucgui的移植,总体还是比较简单的,主要是根据特定的LCD和触摸屏进行相应的接口移植,这只需要实现相应的LCD、触摸屏驱动模块即可。如果读者在windows下进行过win32窗口编程(非MFC),那么对于ucgui的界面编程也会是得以应手的。ucgui_MDK.rar,MDK平台下的UCGUI 3.98版移植源码工程,需根据特定LCD、触摸屏进行驱动模块的更改。http://pan.baidu.com/s/1eQvcNWeu

    时间:2018-12-27 关键词: gcc ucgui s3c2416 裸机开发 移植

  • S3C2440 Linux驱动移植——SPI

    1. 配置内核首先,修改arch/arm/plat-s3c24xx/Kconfig,这一步的目的是为了可以在内核中使能SPI0的配置函数。修改后的内容如下:config S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13 bool " S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13" help SPI GPIO configuration code for BUS0 when connected to GPE11, GPE12 and GPE13.接着配置内核,首先打开S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13选项,这样编译的时候会将arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c一起进行编译。该源文件中的函数void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi, int enable)将用于配置spi控制器0的管脚。接着,使能SPI功能,这里打开2440的SPI控制器驱动和通用的protocol驱动spidev。2. 修改源码修改arch/arm/mach-s3c2440/mach-smdk2440.c增加内容:#include #include static struct s3c2410_spi_info s3c2410_spi0_platdata={ .pin_cs = S3C2410_GPG(2), .num_cs = 1, .bus_num = 0, .gpio_setup =s3c24xx_spi_gpiocfg_bus0_gpe11_12_13,};static struct spi_board_info s3c2410_spi0_board[]={ [0] = { .modalias = “spidev”, .bus_num = 0, .chip_select = 0, .max_speed_hz = 500 * 1000, },};在smdk2440_devices[]中增加&s3c_device_spi0,在smdk2440_mach_init函数中增加s3c_device_spi0.dev.platform_data = &s3c2410_spi0_platdata;spi_register_board_info(s3c2410_spi0_board,ARRAY_SIZE(s3c2410_spi0_board));修改完毕以后,重新编译内核,并下载内核。查看下设备节点:[root@yj423 /dev]#ls /dev/spidev0.0/dev/spidev0.03.测试用杜邦线将MOSI和MISO管脚相连。在内核源码中提供了SPI测试程序。源码位于Documentation/spi/spidev_test.c,编译之后,下到开发板并执行。[root@yj423 yj423]#./spidev_test -D /dev/spidev0.0spi mode: 0bits per word: 8max speed: 500000 Hz (500 KHz)FF FF FF FF FF FF40 00 00 00 00 95FF FF FF FF FF FFFF FF FF FF FF FFFF FF FF FF FF FFDE AD BE EF BA ADF0 0DNOTE:如果你只是为了移植而移植,那么后面的内容就不要看了。想知道WHY,那请继续往下看。4.原理首先,在第二小结中我们看到定义了两个数据结构,之所以要定义那是因为驱动程序需要用到,详见基于S3C2440的嵌入式Linux驱动——SPI子系统解读(二)需要这两个数据结构的地方,均用红色字体说明了。数据s3c2410_spi0_platdata是作为平台的私有数据,因此使用了s3c_device_spi0.dev.platform_data = &s3c2410_spi0_platdata来添加该数据。而s3c2410_spi0_board必须通过函数spi_register_board_info添加到内核中,最重要的一个问题,这些数据结构的值是怎么给出的?先来看看这两个数据结构:structspi_board_info{/*thedevicenameandmodulenamearecoupled,likeplatform_bus;*"modalias"isnormallythedrivername.**platform_datagoestospi_device.dev.platform_data,*controller_datagoestospi_device.controller_data,*irqiscopiedtoo*/charmodalias[32];constvoid*platform_data;void*controller_data;intirq;/*slowersignalingonnoisyorlowvoltageboards*/u32max_speed_hz;/*bus_numisboardspecificandmatchesthebus_numofsome*spi_masterthatwillprobablyberegisteredlater.**chip_selectreflectshowthischipiswiredtothatmaster;*it'slessthannum_chipselect.*/u16bus_num;u16chip_select;/*modebecomesspi_device.mode,andisessentialforchips*wherethedefaultofSPI_CS_HIGH=0iswrong.*/u8mode;/*...mayneedadditionalspi_devicechipconfigdatahere.*avoidstuffprotocoldriverscanset;butincludestuff*neededtobehavewithoutbeingboundtoadriver:*-quirkslikeclockratematteringwhennotselected*/};structs3c2410_spi_info{intpin_cs;/*simplegpiocs*/unsignedintnum_cs;/*totalchipselects*/intbus_num;/*busnumbertouse.*/void(*gpio_setup)(structs3c2410_spi_info*spi,intenable);void(*set_cs)(structs3c2410_spi_info*spi,intcs,intpol);};4.1 s3c2410_spi_infopin_cs:表示哪个管脚用输出片选信号,这里使用GPG2管脚,具体的管脚请参看你的datasheet。bus_num:表示总线接口。这里使用0,表示使用SPI0控制器。S3C2440有两个SPI控制器,分别为SPI0和SPI1。num_cs:表示该SPI控制器控制几个SPI从设备,这里为1,仅有一个设备。s3c2410_spi_info作为平台数据,在s3c24xx_spi_probe函数中,bus_cs和bus_num将被复制给master中的相应字段。也就是说,该master为SPI0控制器,有1个从设备。而pin_cs将由函数s3c24xx_spi_gpiocs使用,该函数使能片选信号。staticvoids3c24xx_spi_gpiocs(structs3c2410_spi_info*spi,intcs,intpol){gpio_set_value(spi->pin_cs,pol);}gpio_setup: 这里设置为函数s3c24xx_spi_gpiocfg_bus0_gpe11_12_13, 该函数用于初始化SPI控制器的管脚。该函数将在主控制驱动的s3c24xx_spi_initialsetup函数中被调用:4.2spi_board_info首先,我们知道spi_board_info作为SPI设备的板级信息,在spi_new_device函数中将该板级信息全部复制给spi_device。modalias:将用于绑定驱动和设备。我们看下match方法:staticintspi_match_device(structdevice*dev,structdevice_driver*drv){conststructspi_device*spi=to_spi_device(dev);returnstrcmp(spi->modalias,drv->name)==0;}而drv->name为在spi_driver中定义,如下staticstructspi_driverspidev_spi={.driver={.name="spidev",.owner=THIS_MODULE,},.probe=spidev_probe,.remove=__devexit_p(spidev_remove),/*NOTE:suspend/resumemethodsarenotnecessaryhere. * We don't do anything except pass the

    时间:2018-12-27 关键词: spi s3c2440 linux驱动 移植

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章

技术子站