Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2697519
  • 博文数量: 877
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 5921
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-05 12:25
个人简介

技术的乐趣在于分享,欢迎多多交流,多多沟通。

文章分类

全部博文(877)

文章存档

2021年(2)

2016年(20)

2015年(471)

2014年(358)

2013年(26)

分类: 嵌入式

2014-07-21 15:16:15

工程移植问题总结
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中此问题被称为 临界资源问题 和用户空间内存访问保护,及内核空间的没有内存保护。
阅读(507) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~