NXP

LPC1778 U盘进行bootloader

2019-07-12 11:58发布

      最近在搞BOOT,于是利用手里的板子LPC1778的片子进行调试。   先去网上找了下发现没有LPC1778U盘进行更行的历程,于是只能自己动手做了。
  1.首先当然是U盘底层驱动,这里没什么可说的,当然是下载NXP官网最新的底层库,然后再弄个FAT文件系统,一切似乎都是水到渠成没有什么大的问题。但是当我在调试时却发现枚举成功后却不能读写U盘。单步调试发现没有文件系统,读写U盘零扇区返回0,本来应该是返回MBR的。 这是为什么呢?在网上找了问了好久才找到,可能问题出在LPC1778片子上。重新查看数据手册,发现U盘底层读写的缓存是存放在设备RAM中的,而FAT文件系统中的BUFF是放在RAM中,无法读取设备RAM中的数据。于是这又引出另一个问题:如何读取设备RAM中的数据呢?    1)可以将FAT中的结构体(主要是FAT FIL)定义到设备RAM中。(此设计到MDK的环境设置以及分散加载文件,后续会讲如何修改)    2)利用NXP底层驱动中定义的变量 volatile  uint8_t *FATBuffer;   /* Buffer used by FAT file system     */ volatile  uint8_t *UserBuffer;  /* Buffer used byapplication          */  进行读写,再使用memcpy进行复制到FAT的BUFF中,虽然繁琐但是简单实用。 到这里U盘底层驱动就结束了。
2.调试FAT文件系统 由于考虑到后续可能也要通过SD卡进行升级,所以FAT文件系统需要支持两个或两个以上的设备。 之前都是搞过FAT只加载一个驱动盘,没有试过加载多个驱动盘。所以也去网上查了下资料——大失所望,基本没有什么历程和讲解。看来只能自己摸索了。 在仔细查看了FAT文件系统的移植手册和配置文件后,发现原来也不是这么难。 1)首先修改ffconf.h #define _VOLUMES 3
/* Number of volumes (logical drives) to be used. */
#define _FS_RPATH 2 /* 0 to 2 */
/* The _FS_RPATH option configures relative path feature.
/
/   0: Disable relative path feature and remove related functions.
/   1: Enable relative path. f_chdrive() and f_chdir() are available.
/   2: f_getcwd() is available in addition to 1.
2)之后只需在disk.c中添加相应的底层读写驱动就OK了 似乎到这里应该就能随便读写SD卡或者U盘了,但是(我只能说个但是)。 只能读写0盘符的设备,这是为什么呢? 原来f_mount默认创建0盘符的工作区,所以在调用f_mount之前必须先调用f_chdrive进行盘符切换,之后就能自由切换了。 3)最后就是修改配置添加自己需要的功能。 这里我在读长文件名时还是出现了点小问题。在ffconf.h中虽然修改了 #define _USE_LFN 2 /* 0 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
/   0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
/   1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
/   2: Enable LFN with dynamic working buffer on the STACK.
/   3: Enable LFN with dynamic working buffer on the HEAP.
注意:堆栈溢出问题,所以需要在启动文件.s中修改默认的堆栈大小(带操作系统的可以不用考虑这个问题,因为操作系统的堆栈是自己分配的) 可是还是不能读长文件名,单步调试:#if _USE_LFN fn = *g_Finfo.lfname ? g_Finfo.lfname : g_Finfo.fname; #else fn = g_Finfo.fname; #endifg_Finfo.lfname地址一直是0,是不是没有分配地址呢? 再次仔细读了一遍FAT的确是没有分配地址空间。只需添加一下代码即可: #if _USE_LFN static char lfn[_MAX_LFN * 2 + 1]; g_Finfo.lfname = lfn; g_Finfo.lfsize = sizeof(lfn); #endif
到此基本完成了U盘读写.bin文件了。 下面就是主讲了——bootloader /******************************************************************************* * 函数介绍: 跳转到应用程序 * 输出参数: N/A * 输出参数: N/A * 返回值 : N/A ******************************************************************************/ __asm void boot_jump( uint32_t address ) { LDR SP, [R0] ;Load new stack pointer address LDR PC, [R0, #4] ;Load new program counter address } void ExecuteUserCode(uint32_t addr) { SysTick->CTRL = 0; SCB->VTOR = addr & 0xFFFFFF80; boot_jump(addr); } void Jump_To_Application(void) { ExecuteUserCode(APP_ADDRESS); }应用程序需将ROM起始地址修改,MDK环境设置中需在ASM中添加NO_CRP(不能不能通过自己的BOOT进行更新)。另外需注意,BOOT中已将中断向量表进行了地址映射,所以需屏蔽掉应用程序中的中断向量表配置: //#ifdef __RAM_MODE__ // SCB->VTOR = 0x10000000 & 0x3FFFFF80; //#else // SCB->VTOR = 0x00000000 & 0x3FFFFF80; //#endif
到这里整个工程完成。当然这其中还有一些小细节需要注意,还有一些保护策略、校验方式等。
另外,在烧写flash时,由于只能使用NXP自带的BOOT区开放接口函数,并且因为是CORE3内核,需地址4K对齐,写入的BUFF需4字节对齐。这里也随便普及一下再ARM中的字节对齐的命令: 1)使用伪指令 #pragram pack(n) C编译器将按照n字节对齐    使用伪指令 #pragram pack()  取消自定义字节对齐方式    此两条需配对使用,这区间内所有变量将按n字节对齐,否则会出现不可预知的问题。 2)__attribute((aligned (n))) 具体要了解为什么需要字节对齐,字节对齐有什么优势和风险,这里提供一个外链,有兴趣的朋友可以去研究一下:http://blog.csdn.net/21aspnet/article/details/6729724 
至此本文结束,希望能和大家多交流经验以便共同进步。