写给十年后的自己,勿忘艰辛
一、 起步
主要工作写代码,完成的代码如下
1、 中断
中断的处理方式是arm9和arm11一个主要区别点,arm11支持Vectored Interrupt Controller,而arm9不支持,因此arm9需要在0地址开始的地方建立中断向量表。
2、 使能Dcache Icache
1)、使能Dcache的同时必须使能mmu,而使能mmu必须先初始化页表
2)、对DMA区域的单独处理
3、使用scaterr文件进行代码空间的重新规划
为了处理中断需要对原来的区域重新做一下规划,如下:(使能Dcahce之前)
RO(.text,.constdata)
RW(.data)
ZI (.bss)
HEAP
STACK(SVC)
STACK(IRQ)
二、 攻坚
主要工作是调代码,主要解决的问题如下:
1、 使能Dcache之后,usb枚举不成功
主要问题是cache区域不能用作DMA,解决方法有两种,一种是flush cache(函数已有,但作出模版),一种建立Ucache的DMA区域(目前采用,还不完美)。
2、 稳定性问题
解决两个bug,如下:
1)、对NULL指针赋值,指针如下:
P_Mac_data_Frm_Hr
解决方法,将其赋值为:
(MAC_DATA_FRM_HR*)&pCurRxDataNode->Data[pCurRxDataNode->MacCb.DataOffset];
2)、对齐问题,结构体如下:
typedef PACKED struct _FID_ACK
{
UINT16 Fid : 4; //流标识
UINT16 SSN : 12;
UINT8 Resv : 3; //预留
UINT8 BitMapLenIdx : 4; //BitMapLen索引
UINT8 FragInd : 1; //是否分片
UINT8 BitMap[MAXBITMAPSIZE];
}FID_ACK;
修改方案:
对于第二个流,先在对齐地址去赋值,然后再memcpy到非对齐的地址。(UINT8*类型的拷贝)。
3、scatter文件
使用scat文件,必须得重新书写__user_initial_stackheap函数,原来库中的不能用了。只要我们调用__main,就需要__user_initial_stackheap函数,反汇编一下就能看到__main会调用_rt_entry,在_rt_entry中调用__user_initial_stackheap和main函数。
三、 总结
1、 关于中断,主要针对arm11和arm9中断处理方式不同,没有什么太多的说的,代码移植跑通了之后,基本就没怎么改过。至于效率的高低,有待进一步验证。只有一个宏给我留下了印象,代码如下:
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does''t push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
这个宏是处理中断调转经典的宏。
2、关于对齐,这部分看arm手册的时候,看的最乱的一部分,今天试着梳理一下,梳理一下的好处就是我们以后写代码的时候心里有根弦,不要去碰高压线。我们之前的代码中也出现了没有对齐的bug。求求朋友们,以后写代码之前,先背诵一遍下面的规则,工欲善其事,必先利其器。
先来说说什么叫非对齐地址:
Halfword access Address[0] is 1.
Word access Address[1:0] is not b00.
LDRD or STRD Address [2:0] is not b000.
Multiple access Address [1:0] is not b00.
访问非对齐地址的行为:
If alignment faults are enabled(即cp15 Register c1的A位被置1) and the access is not aligned then the Data Abort vector is entered with an Alignment Fault status code.
If no alignment fault is enabled, that is, if bit 1 of CP15 Register c1, the A bit, is not set:
Byte access Memory interface uses full Address [31:0].
Halfword access Memory interface uses Address [31:1]. Address [0] asserted as 0.
Word access Memory interface uses Address [31:2]. Address [1:0] asserted as 0.
以上规则适合armV5和armV6版本,下面再来说说,armV6版的改进
Support for unaligned data access in ARMv6,若要启用未对齐支持,必须执行下列操作:
• 在初始化代码中清除 CP15 寄存器 1 的 A 位(即位 1)。
• 在初始化代码中设置 CP15 寄存器 1 的 U 位(即位 22)。
当然了好东西,一定会有一堆的限制,终的目的就就是告诉你最好别用,但是经常有一群壮士,牛人偏偏去用,他们心目的中信念是“名若天定,我便破了这天”,为了这些壮士,我还是把V6版本使用非对齐访问的限制列出来:
Accesses are not guaranteed atomic.
Unaligned accesses loading the PC produce an alignment trap.
Accesses typically take a number of cycles to complete compared to a naturally aligned transfer.
Accesses can abort on either or both halves of an access where this occurs over a page boundary.
3、关于稳定性,给我最深刻的印象就是坚持,很多的仁人志士倒下打好地基,那么胜利一定属于最后坚持下来的那个人。我们试着来分析一下,这个稳定性问题根源。
usb处理的突发性停止加上arm9处理速度的弱势,使得arm9比arm11更容易出现上面说到的那个空指针的bug,造成的结果就是arm9看起来没有arm11稳定。
双流的地址非对齐觉得是一个bug,当这个非对齐的地址在栈上时候,访问的时候就会破坏栈,早晚会死机。
4、关于cache,印象最深刻的是发现arm9的Icache没打开的瞬间,那叫一个兴奋啊,以及康永说要打开Dcache必须要开mmu的时候,那叫一个失望啊。还有一个瞬间是我们在写完Dcache的代码后,USB不能枚举,我们分析出来是DMA区不能cache的时候,又是一阵兴奋。
Cahce的打开对稳定性的贡献有两点,一、Icahce的打开使得软件的速度能赶上硬件的速度了,二、Dcache打开使得速度进步提高,减少了出现NULL指针bug的可能性。
四、 遗留问题
1、arm11编译问题,怀疑缺少bcd包
2、 Flush cache 现在只提供了刷cache的函数,应该做一版基于刷cache的软件(目前的软件是基于cache区和uncache区分割)
3、 Dcache性能的评估
4、 O3的支持
5、 ucos现在跑到svc模式下,可以使其跑到sys模式下,因为svc模式一般用作软中断,典型的应用是系统调用(代码已经完成,有待测试)
阅读(3006) | 评论(0) | 转发(0) |