工程移植问题总结
1.ep0_send()函数不能发送
前段时间一直在移植CCID的下位机驱动程序,但是移植过程中枚举一直失败,经徐工改进在FW_HAL,实现了
CCID + MASS Storage共同枚举,但是我发现CCID demo工程中的ep0_send()函数仍无法使用,实际上复合设备
一直不能枚举是由于我一直想使用ep0_send()函数,但之前并不知道是这个函数导致的,所以工程进度一直
止步不前。
2.链接文件没有 DATA 数据段导致全部数据被放置在ROMDATA段
CCID demo工程分析如下:
MEMORY //这个是CCID demo 中的链接文件
{
TEXT (RX) : ORIGIN = 0x00002000, LENGTH = 0x00000000
ROMDATA (R) : ORIGIN = AFTER(TEXT), LENGTH = 0x00000000
BSS (RW) : ORIGIN = 0x00800000, LENGTH = 0x00000000
} //从这个链接文件可以看出这个链接文件没有 ‘DATA’ 数据段
unsigned char DeviceDescriptor[18] =
{
18, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x40,
0x09, 0x23, 0x06, 0x06, 0x01, 0x00,
0x01, 0x02, 0x03, 0x01
};
static unsigned char ConfigurationDescriptor[0x56] =
{...........
};
以上两个描述符是CCID demo内的描述符其没有在描述符前面加 const 关键字,这将直接造成被分配到 DATA段
但是由于本工程没有DATA段所以这两个描述符被放到ROMDATA段。
FW_HAL 工程分析如下:
MEMORY
{
//VECTORS (R) : ORIGIN = 0x00803C00, LENGTH = 0x00000200
TEXT (RX) : ORIGIN = 0x00002000, LENGTH = 0x00000000
ROMDATA (R) : ORIGIN = AFTER(TEXT), LENGTH = 0x00000000
DATA (RW) : ORIGIN = 0x00800000, LENGTH = 0x00000000 //指定程序运行时的数据地址
BSS (RW) : ORIGIN = AFTER(DATA), LENGTH = 0x00000000
}
.main_application_data : //定义ROM数据段存储地址详细信息
{
. = ALIGN(0x4); //数据四字节对齐
* (.rodata) //保存在ROM中的常数 只读数据段
__data_ROM_begin = .; //记录数据复制起始地址 在此只是保存一个标号真正的data数据放入是在 .data:AT(__data_ROM_begin) 这里放入的!
//这个标号起到在DATA段的内容知道要存储在什么地方
//* (.data) //所有模块中的数据
//注:此处将//* (.data)数据段注释掉而在DATA段让其存在是因为如果在此处放置data数据内容,而DATA段内容为空由于BSS段放在DATA段之后,
//由于DATA段为空所以BSS段的内容就被放在DATA段处,由于在cpu上点后要将__data_ROM_begin处的data数据内容读到DATA段,这时BSS段就被破坏
//导致编译正常的程序无法运行!
__data_ROM_end = .; //记录数据复制终止地址 在此只是保存一个标号
//* (.vtables)
//* (.exception)
//__sinit_= . ; //仅用于C++程序
//STATICINIT
} > ROMDATA
.data:AT(__data_ROM_begin)
{
__data_begin = 0x00800000; //标定程序开始地址(运行时的数据地址存储是存储在__data_ROM_begin处得!)
. = ALIGN(0x4);
* (.data) //程序运行时在0x00800000处,存储是在__data_ROM_begin处
} > DATA
此工程中多了DATA数据段,在移植过程中由于我直接将CCID demo中的描述符直接添加到FW_HAL工程中这次CCID demo中的描述符被放置到DATA数据段,从.data:AT(__data_ROM_begin)
可以知道工程中的数据存在__data_ROM_begin处,但是由于在FW_HAL的Startup.c中有__copy_rom_section(__data_begin, __data_ROM_begin, (unsigned long)__data_size);
数据搬移指令,程序会将DATA段的数据搬移至DATA (RW) : ORIGIN = 0x00800000,处,DATA段数据被搬移至0x00800000处之后,由于人为定义了DATA段,程序在运行时,
当用到属于DATA段的内容时,程序会到DATA段去取数据,如本例,程序回到SRAM的0x00800000附近去取两个描述符,但是由于本CPU没有MMU(MMU要开启),SRAM中的数据,不具备
安全性,当程序去SRAM中取描述符时,可能描述符所在的内存数据已被修改,导致设备枚举出错。
3.综上所述,采取将设备描述符加 const 关键字,让其为只读数据,存于ROMDATA中,程序在运行时,获取描述符时,会到ROMDATA中去取,不会出现取得的描述符被其他代码修改的
情况!工程启示:在没有MMU开启,没有内存数据保护的裸机程序中一定要注意数据的保护!在Linux中此问题被称为 临界资源问题 和用户空间内存访问保护,及内核空间的没有内存保护。
阅读(503) | 评论(0) | 转发(0) |