打印

高手也要向低手学习

[复制链接]
1616|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
djyos|  楼主 | 2008-7-30 10:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近大家都在嚷看不懂菜高手的虫子,高手心中有乾坤,理解能力强,自然不需要注释和说明;而低手总是诚惶诚恐,一怕老师说看不懂,二怕程序以后出问题,自己都看不懂。我贴一段低手写的代码,大家看看能看懂不。
uint32_t __calculate_DDR_size(struct st_DBX_flash_tag *DBX_flash_tag)
{
    uint32_t size,blocks,fill,flash_MAT;
    uint64_t u64i;
    struct flash_chip *chip = DBX_flash_tag->chip;
    //下面计算1份DDR表尺寸,方法参见本文件开头部分的说明
    //粗算DDR表尺寸,可能是小数
    size =    4                                     //ADB磨损次数基数
            + 2*DBX_flash_tag->block_sum            //ART磨损次数表
            + 4                                     //FDS,fdt表首块块号
            + 4*2*DBX_flash_tag->block_sum;         //mat表
    //下式乘法可能造成32位整数溢出,故用64位整数
    u64i = chip->block_size * size + 4 * (chip->block_size-1);
    size = (uint32_t)(u64i / (chip->block_size-4));
    //上式得到的result可能会比实际需要多(0~3),下面调整之
    size = align_down_4(size);
    if(size > chip->block_size)       //超过1块,需考虑单个条目越块边界问题
    {//DDR表任意一个单项的任意一个条目不能跨块边界,下面调整之。
     //调整的过程中可能引起DDR_size变化,并连带引起DBL表长度变化
     //1、DBL表的起始偏移为0,表项固定为4字节,故无论DBL表占多少块,
     //   肯定不会有跨边界的项。
     //2、DBL表结束于4字节对齐地址,FDSB不可能跨边界。
     //2、FDSB结束于4字节对齐地址,磨损次数基数不可能跨边界。
     //3、磨损次数基数结束于4字节对齐地址,磨损次数表不可能跨界
     //4、磨损次数表结束于字节对齐地址,而MAT要求8字节对齐,故需要调整。
        blocks = (size +chip->block_size -1 ) / chip->block_size;   //块数
        flash_MAT = 4*blocks                        //DBL
                    + 4 + 4                         //ARB+FDSB
                    + 2*DBX_flash_tag->block_sum;   //ART
        fill = align_up_8(flash_MAT) - flash_MAT;  //算对齐损耗
        if((fill + size)/chip->block_size != size/chip->block_size)
        {//因调整增加了块数
            size += fill;
            if(fill < 4)   //对齐留下的空位不够一个DBL项
                size = size + 8;
        }else
        {
            size += fill;
        }
    }
    return size;
}

再来段汇编的
@----中断中的上下文切换-------------------------------------------------------
@功能:  保存被中断线程的上下文,切换到新线程的上下文中继续执行。本函数虽然在中
@        断服务函数(非用户用int_isr_connect函数连接的中断服务函数)中,但在ARM
@        中,却运行在svc态
@参数:  new_sp,新上下文的栈指针
@参数:  old_sp,被中断线程的上下文的栈指针的指针,即&vm->stack。无需提供旧上下
@               文栈指针,sp寄存器的当前值就是
@返回:  无
@函数原型: void __asm_switch_context_int(void *new_sp,void **old_sp);
@-----------------------------------------------------------------------------
    .global __asm_switch_context_int
__asm_switch_context_int:
    stmfd   sp!,{r2-r12,lr} @保存正在服务的中断上下文

    @以下几行把需要换出的上下文从正在服务的中断栈顶转移到虚拟机栈中
    ldr     r2,=IRQ_stack   @取irq栈基址,这里存放着被中断线程的上下文
@    mov     r11,sp
    ldmea   r2!,{r3-r10}    @按递增式空栈方式弹栈,结果:
                            @[r2-1]=LR_irq->r10,被中断线程的PC+4
                            @[r2-2]=r12->r9,被中断线程的r12
                            @[r2-3]=r11->r8,被中断线程的PC
                            @.......
                            @[r2-8]=r6->r3,被中断线程的r6
    sub     r10,r10,#4      @中断栈中的LR_irq-4=PC

    @以下三句就是取出被中断线程的SP_sys,只能通过stmfd指令间接取
    mov     r11,sp            @下一句不能用SP,故先拷贝到r11
    stmfd   r11!,{sp}^      @被中断线程的SP_sys压入正在服务的中断栈中
    ldmfd   r11!,{r12}      @从正在服务的中断栈中读取 SP_sys->R12

    stmfd   r12!,{r10}      @保存 PC_sys
    stmfd   r12!,{lr}^      @保存 lr_sys
    stmfd   r12!,{r3-r9}    @保存被中断线程的r12-r6到它的栈中
    ldmea   r2!,{r3-r9}     @读被中断线程的r5-r0->r9-r4,SPSR_irq->r3,递增式空栈
    stmfd   r12!,{r3-r9}    @保存被中断线程的r5-r0,CPSR_sys到它的栈中

    str     r12,[r1]        @换出的上下文的栈指针-->old_sp

    @以下几行把待换入的上下文copy到IRQ栈顶,r0即new_sp,保存待换入的上下文栈指针
    @与递减式满栈对应,此时IRQ栈用递增式空栈的方式访问

    mov     r12,r0          @读取需换入的栈指针
    ldmfd   r12!,{r3-r11}   @读取换入线程的CPSR_sys->r3
                            @读取换入线程的r0-r7->r4-r11
    stmea   r2!,{r3-r11}    @保存换入线程的CPSR_sys->SPSR_irq, r0-r7到IRQ栈
    ldmfd   r12!,{r3-r7}    @读取换入线程的r8-r12->r3-r7
    stmea   r2!,{r3-r7}     @保存换入线程的r8-r12到IRQ栈
    ldmfd   r12!,{lr}^      @恢复换入线程的LR_sys到寄存器中
    ldmfd   r12!,{r3}       @读取换入线程的PC->r3
    add     r3,r3,#4        @模拟IRQ保存被中断上下文PC的方式:PC+4->LR_irq
    stmea   r2!,{r3}        @保存换入线程的LR_irq到IRQ栈
    stmfd   r12!,{r12}      @读取SP_sys到r12
    ldmfd   r12!,{sp}^      @恢复SP_sys
    mov     r0,r0           @无论是否操作当前状态的SP,操作sp后,不能立即执行函数
                            @返回指令,否则返回指令的结果不可预知。
    ldmfd   sp!,{r2-r12,pc}
@ end of __asm_switch_context_int

相关帖子

沙发
sz_kd| | 2008-7-30 10:18 | 只看该作者

我是菜鸟,看了眼晕

使用特权

评论回复
板凳
zjh006| | 2008-7-30 10:23 | 只看该作者

没看懂

使用特权

评论回复
地板
djyos|  楼主 | 2008-7-30 11:50 | 只看该作者

看不懂吧

连我自己过两月也看不懂,需要对照方案文档才行。
所以,裸奔是没有用的,尤其是没有注释的裸奔,充其量只是自娱自乐。
重要的是讲设计思想,代码只是示例而已。

使用特权

评论回复
5
laoy| | 2008-7-30 13:00 | 只看该作者

看不懂

    还是留下相应程序版本的流程图位好,看起代码就晕

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

60

主题

454

帖子

1

粉丝