【复习】复习之学习笔记

持续更新...
//=========================================================================================

=============第一期、ARM裸机复习笔记=============

-----------------第一遍-------------------
2018-08-05开始复习:
0、对裸机的大部分的单一特殊功能都是按照使用要求(使用者的主观使用要求和外接硬件的客观物理使用要求)和时序要求,
对特殊功能模块的寄存器组进行设置。
1、SUBSRCPND(指示次级中断源请求状态)和INTPND(指示中断源请求状态)寄存器的用法,都是只管读状态就可以吗?
复习中断控制器课程并结合本节课程,总结归纳;
答:可以读相应的位来判断相应级别响应的中断响应状态,但中断处理结束后需要手动清除对应的中断!
注释:    a.但异常向量表中,中断异常会自动跳转到函数handle_irq_c();执行已注册好并在响应的中断的处理函数,处理
        结束后自动清除中断源和中断; 再之后,程序退出中断返回发生中断异常时的指令重新执行延续原来的进程!
        b.外部中断和次级中断清中断时需要先在中断处理函数末尾清除EINTPEND寄存器、SUBSRCPND寄存器,方法与清除SRCPND寄
        存器、INTPND寄存器一样,写1到寄存器相应的位,别的位不用管,如下例;
        c.注册中断时,由于register_irq(irq, fp); 函数会自动注册中断及其处理函数并使能INTMSK的相应位,但对于次级中断
        需要另外先使能INTSUBMSK寄存器的相应次级中断使能位,且对于外部中断也需要先使能EINTMASK寄存器的相应外部中断使
        能位;
实例:
请清断:/*清中断:从源头开始清*/【EINTPEND = val; SUBSRCPND = (1<<TC_INT_BIT) | (1<<ADC_INT_BIT);    SRCPND = (1<<bit);    INTPND = (1<<bit);】
使能中断:【EINTMASK &= ~((1<<11) | (1<<19));    INTSUBMSK &= ~((1<<ADC_INT_BIT) | (1<<TC_INT_BIT));    INTMSK &= ~(1<<irq);】

2、开发板上的Norflash的位宽是16bit,所以可以把要写的数据构造成16bit,然后再写入Norflash中!
具体使用参考do_write_nor_flash();函数中写数据到flash的内存空间的写入格式!
3、可不可以以面向对象的思维重新结构化编写Nor、Nand程序?答:可以的
4、使用函数指针调用函数的正确方法:
int (*p)(int, int);
int max(int, int)    //    int min(int, int) 
有p = max;
所以调用 c = max(a,b); 即:
1)c = (*p)(a, b);
2)c = p(a, b);
问题1:两种方法导致的结果一样吗?均为正确使用函数指针的方法吗?
例子:    
/* 处理中断 */
1)(*irq_array[bit])(bit);    //我的程序--定时器中断课程     
2)irq_array[bit](bit);        //视频程序--定时器中断课程     
答:通过vc++6.0和裸机定时器中断一课的程序可知,两种方法在两个平台均可成功使用!
注意:
1)vc++6.0中,
typedef int (*p1)(int, int);    //需要另外声明;
typedef int (*p2)(int, int);    //需要另外声明;
int (*p3)(int, int);            //不需要另外声明;
即p1, p2使用前,需要:int (*p1)(int, int);int (*p2)(int, int);
问题2:    typedef int (*p1)(int, int);    
        int (*p3)(int, int);      
的区别?
答:typedef int (*p1)(int, int);是定义一种数据类型,而int (*p3)(int, int);是直接定义一种int (*)(int, int)类型的函数指针变量!

5、通过阅读.dis文件可知,强制 PC 从相关异常向量处取下条指令,所用异常向量表为重定位之后的向量表地址,
其中的跳转指令为绝对跳转,即跳转到重定位之后的异常处理指令的位置,

6、测试Nand_flash时需要指令序列:
    nand_init();
    nand_flash_test(); 
测试Nor_flash不需要,直接测试:
    nor_flash_test();
问题:不测试,直接使用Nand_flash,即进行代码重定位和烧写运行程序,有没有影响?
答:在Nand_flash重定位代码中,自有代码先对Nand_flash进行初始化,然后再重新复制代码到sdram, 所以没有影响!

7、    static int n; xx{...}    //定义静态全局变量;
    extern int n; xx{...}    //定义全局变量;
    xx{static int n;}        //定义静态局部变量;
静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。
该变量在全局数据区分配内存;
静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;

8、关于结构体本身是否可以作为真假的判断条件的测试
File:    timer.c
typedef void (*timer_func)(void);
typedef struct timer_desc
{
    char * name;
    timer_func fp;
}timer_desc, *p_timer_desc;
timer_desc timer_array[TIMER_NUM];
int register_timer_irq(char * name, timer_func fp)
{
    int i;
    for(i = 0; i < TIMER_NUM; i++)
    {
        if(!timer_array[i].fp)    {...}
    }
}
经上机编译及裸板测试,得timer_array[i].fp/name可以被用来判断真假,但是timer_array[i]本身不可以!否则,编译错误!

9、关于结构体元素赋值的问题:
typedef struct i2c_controller {
    int (*init)(void);
    int (*master_xfer)(p_i2c_msg msgs, int num);
    char *name;
}i2c_controller, *p_i2c_controller;
static i2c_controller s3c2440_i2c_con = {
    .name = "s3c2440",
    .init = s3c2440_i2c_con_init,
    .master_xfer = s3c2440_master_xfer,
};
或者
static i2c_controller s3c2440_i2c_con = {"s3c2440",    s3c2440_i2c_con_init,    s3c2440_master_xfer};

上述程序成功编译,并在裸板上成功运行,证明定义结构体变量并初始化时,初始化列表内元素间用‘,’隔开且顺序没有要求!


---------------第二遍、兼移植程序到 MINI2440 ----------------

MINI2440与JZ2440开发板的外围电路区别:
//========================================================================================
【整理】
Mini2440 使用了两片外接的 32M bytes 总共 64M bytes 的 SDRAM 芯片(型号为:HY57V561620FTP/MT48LC16M16A2);
=>EM63A165TS-6IG;
SDRAM(64M): LnSCS0 —— nGCS6:nSCS0,片选引脚和内存大小同JZ2440一样!
【Norflash】S29AL016J70TFI020_中文手册_Norflash, 大小为 2Mbyte, 如下为该芯片手册数据:
Tacc--对应2440的BANKCON0[10:8], 即Norflash的读/写访问周期:55ns/70ns两种,取70ns, 可选默认值
nGCS0;
Block/Sector Start Address:
0x00000000 0x00004000 0x00006000 0x00008000 0x00010000
0x00020000 0x00030000 0x00040000 0x00050000 0x00060000
0x00070000 0x00080000 0x00090000 0x000a0000 0x000b0000
0x000c0000 0x000d0000 0x000e0000 0x000f0000 0x00100000
0x00110000 0x00120000 0x00130000 0x00140000 0x00150000
0x00160000 0x00170000 0x00180000 0x00190000 0x001a0000
0x001b0000 0x001c0000 0x001d0000 0x001e0000 0x001f0000
【Nandflash】型号为 K9F1G08,大小为 128M=====>K9F2G08U0C-SCB0, 256M;型号同jz2440的Nandflash一样。
试验验证对比,两款开发板的SDRAM, NORFLASH, NANDFLASH的使用方法一模一样,程序不需要修改丝毫!
====================================================================================
【LCD】
数据格式为32bit时,数据缓冲区的大小为:
240*320*4byte = 300 Kbyte = 0x12c Kbyte;
// LCD背光
#define GPB1_TO_OUT()       (rGPBUP &= 0xfffd, rGPBCON &= 0xfffffff3, rGPBCON |= 0x00000004)
#define GPB1_TO_1()         (rGPBDAT |= 0x0002)
#define GPB1_TO_0()         (rGPBDAT &= 0xfffd)
====================================================================================

2018-09-13 第一期视频结束复习:
1.1)关于异常向量表,发生异常时跳转的地址是 0x00000000/4/8/c/10/14/18/1c 之类的初始地址,还是重定位之后的地址 0x30000000 之类?
答:
2)相对跳转和绝对跳转的指令分别是什么?
答: 1> b step1 :b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于
    要跳到的代码的位置,只看指令本身。
    2> ldr pc, =step1 :该指令是从内存中的某个位置(step1)读出数据并赋给PC,同样依赖当前PC的值,但是偏移量是那个位置(step1)
    的连接地址(运行时的地址),所以可以用它实现从Flash到RAM的程序跳转。
3)指令【und_addr:    .word do_und】的作用?是绝对跳转到do_und的绝对地址吗?
答:
4)【reset】之后程序是在 0x00000000 运行还是 0x30000000 运行?其中的sp栈地址在什么地方(下面的哪一个)?
    cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    moveq sp, #4096  /* nand启动 */
    streq r0, [r1]   /* 恢复原来的值 */
答:reset之后,cpu处于svc模式,重定位,接着切换CPU从svc模式到usr模式并设置 sp_usr:
    mrs r0, cpsr             /* 读出cpsr */
    bic r0, r0, #0xf        /* 修改M4-M0为0b10000, 进入usr模式 */
    bic r0, r0, #(1<<7)     /* 清除I位, 使能中断 */
    msr cpsr, r0
    ldr sp, =0x33f00000        /* 设置 sp_usr */
然后绝对跳转:
    ldr pc, =sdram
从而,把程序从Nor/SRAM区拉到SRAM执行。
而对于    
    ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    moveq sp, #4096  /* nand启动 */
这个栈是 sp_svc 的栈地址,实际只在执行重定位代码时:
    bl sdram_init
    bl copy2sdram    /* 重定位text, rodata, data段整个程序 */
    bl clean_bss    /* 清除BSS段 */
给相关函数提供栈缓冲区。
注意:所有重定位代码(start.S + sdram.c的二进制.bin)必须在可执行范围内,即Norflash时重定位代码 < 2M, Nandflash时重定位代码 < 4K。
否则,超出范围之外的代码不能被调用到,就会重定位出错,程序编译结果不能执行(主要是Nandflash)!这也是,视频程序把start.S + sdram.c
放到编译顺序的最开头的原因!
5)问题代码:
目录E:\Linux-ARM编程\mini2440编程\hardware\relocate\relocate_test1__0
----------------成功在Nor/Nand运行打印-------------------
    //.bss清0
    bl clean_bss
    ldr pc, =sdram

sdram:
    bl uart0_init
    bl print1
/* 插入未定义异常指令 */
und_code:
    bl print2
    .word 0xdeadc0de

    //bl main
    ldr pc, =main
//------------------------------------------------------------
在Nor可打印,在Nand不可打印;
    //.bss清0
    bl clean_bss
    //bl main
    ldr pc, =main    //查看.dis 反汇编,跳转不成功;
问题原因:未知啊


=======第12/15/16课、SDRAM / Norflash / Nandflash章节========
2、复习第一遍专注于课程内容复习,结束后应再揣摩一遍程序的结构!
3、内存类设备SDRAM, DM9000, NORFLASH等怎样互不干扰?
答:1)通过片选引脚(CS:)??
2)CPU根据指令发 Addr 信号到内存控制器,内存控制器根据地址选择片选引脚(硬件自动完成?);
3)GPIO/门电路, 协议类接口(UART, I2C, I2S等), 内存类接口(SDRAM, DM9000, NORFLASH等)都属于CPU统一编址,Nandflash不属于(因此Nandflash单独需要手动连接片选引脚?)! 

3、读全英文手册的方便之处:在设置 s3c2440 时,可以更方便查询外设芯片数据手册,可以直接英文原词搜索,如此可也!
4、芯片手册内容结构,一般比较重要的特性在第一页就写出来了,查找数据时先看第一页。

5、有视频可知,SDRAM章节在 MINI2440 上运行时,参数不需要修改,因为视频编程时已经参考了 MINI2440 的SDRAM芯片HY57V561620(L)T;

6、Norflash/Nandflash章节复习时,程序烧写到Norflash没有问题,读写擦除功能都可实现; 
烧写到Nandflash时一直无打印结果,当在重定位代码之前插入打印程序时,会一直爆炸式打印。
bug代码路径E:\Linux-ARM编程\mini2440开发板\hardware\16_nandflash\001_nandflash_1_error
查找了一天,还是没有找到原因,先过去吧,希望以后可以找到答案。
7、今天把第16课_Nandflash章节前面的都复习完了,目前为止,对比mini2440和jz2440的电路区别:
1)只有LED、按键引脚不一样,别的引脚(包括UART0_RXD0/TXD0, Norflash_nGCS0)都一样; 
2)Norflash芯片不一样,但是操作时序(时间参数的大小和顺序)和命令一模一样,两款芯片手册也基本类同; 对芯片进行读/写/擦除的程序结构及程序也一模一样; 厂家/设备_ID不一样,内部区块/扇区?未究,但是擦除、读、写扇区的操作是根据扇区地址操作的,而所有扇区地址(也即擦除地址)会被程序计算并打印出来,并不影响对Norflash芯片的测试;
3)与JZ2440开发板的Nandflash芯片一模一样,该章程序不需做丝毫改动。
因此,除了 led.c/ timer.c/interrupt.c 文件的程序关于【LED/按键】部分需要修改外,别的文件都不需要修改。
目前为止,所有文件的目录:
start.o,interrupt.o, sdram_init.o,  uart.o,  nand_flash.o,  led.o,  main.o,  exception.o,  timer.o, |\
nor_flash.o, lib1funcs.o, string_utils.o, my_printf.o; 


=======第17课、LCD章节========
7、LCD章节,对比mini2440和jz2440的电路区别:
1)引脚极性反转的情况根据mini2440的 TD35 液晶屏幕,重新审定:
2)LCD的各项时序的时间参数大小:
.time_seq = {
        /* 垂直方向 */
        .tvp=    2,      /* vysnc脉冲宽度 */
        .tvb=    2,   /* 上边黑框, Vertical Back porch */
        .tvf=    9,   /* 下边黑框, Vertical Front porch */

        /* 水平方向 */
        .thp=    5,     /* hsync脉冲宽度 */
        .thb=    35,  /* 左边黑框, Horizontal Back porch */
        .thf=    40,  /* 右边黑框, Horizontal Front porch */

        .vclk=    6,   /* MHz */
    },
虽然和百度搜来的博客不一样,但是遵循了LCD液晶屏幕 TD35—TD035STEB2 的对于垂直/水平两个方向的参数的规定:
240 x RGB x 320;
Vertical Display Active   = 320;    Vertical Blank Time   = 13;
Horizontal Display Active = 240;    Horizontal Blank Time = 80;
3)引脚的区别:
    a.    jz2440:    R:G:B =5:6:5 = [VD23:VD19, GND] : [VD15:VD10] : [VD7:VD3, GND];
        MINI2440:    R:G:B=6:6:6 = R[5:0]:G[5:0]:B[5:0] = [VD23:VD18] : [VD15:VD10] : [VD7:VD2]; 
        
    b.    jz2440:        bit'2 = DE数据使能位;
    
    c.    jz2440:        VCLK,即Pixel CLK;    VCLK/GPC1;
    d.    jz2440:        LED+-, LED背光引脚 —— TOUT0/GPB0;
    e.    jz2440:        LCD_PWREN/EINT12/GPG4;
                    说明:LCD_PWREN为LCD电源,作用为此电源电路起作用的前提是LCD PWREN引脚是高电平,+5V的VDD就可以生成AVDD;
            
    //f.    jz2440:    VLINE-NC, VFRAME-NC;(即没接用);
   //g.  jz2440:    触摸屏引脚(4个):ADC:SYM--T16--AIN4/TSYM; TSYP--T17--AIN5/TSYP;TSXM--R16--AIN6/TSXM;TSXP--P16--AIN7/TSXP;

8、本章节问题,fb_get_lcd_params()函数内:
{
    get_lcd_params(&xres, &yres, &bpp, &fb_base);    错写为:
    get_lcd_params(&fb_base, &xres, &yres, &bpp);
}
浪费了大量的时间来检查查找错误,还有程序修改之后需要clean一下重新编译,否则,有些未 volatile 修饰的变量会仍旧保留错误的值,而不会
主动自动修改!
9、当数据格式 bpp = 32/16 时,在mini2440烧写运行均可实现全部功能:画线,画圆,显示字符串;
=======第18课、ADC_TC章节========
1、触摸屏工作的前提,即初始化:
a.初始化工作的寄存器:        ADCCON = (1<<14) | (49<<6) | (0<<3);
                            ADCDLY = 60000;
b.初始化INT_ADC_S, INT_TC:register_irq(31, AdcTcIntHandle);
                            INTSUBMSK &= ~((1<<INT_ADC_S) | (1<<INT_TC));

s3c2440是不支持中断嵌套的。
MINI2440的触屏是一线制,应恢复为四线制。

其他区别:
【串口使用】:JZ2440开发板是自带USB转串口电路,MINI2440是用的RS232串口线。
【AD测试】:JZ2440开发板外接SPI模块,上有一个可调电阻,一端接3.3V电源,一端接GND,中间的电位器接模拟输入端口0:AIN0; 旋转可调电阻即可得到不同的电压,JZ2440开发板上并没有接有诸如:ADS7812之类的ADC元件。
        MINI2440上自带 1 个可调电阻,用于AD 模数转换测试。
【LCD测试】:背光引脚灯电源控制:MINI2440-GPB0;  MINI2440-GPB1;
        MINI2440开发板LCD屏幕不一样,各参数有区别,但是控制方法与JZ2440开发板一模一样。
触摸屏:MINI2440 的TD35/P35触摸屏是通过通过使用STC单片机和AD芯片实现的;首先通过AD芯片连接触摸屏,采集触摸屏数据再发送给STC单片机,再通过STC单片机发送给2440(单片机一只引脚与2440一只引脚相连,所以称之为一线触控),需要改一线触控为常规四线触控,JZ2440开发板即是四线触控。
        触摸屏触点电压转数字是硬件自动主动完成的?
【I2C测试】:JZ2440开发板的AT24C08是在外接模块上的,需要外接模块才能S3C2440芯片与I2C设备AT24CXX做 I2C 通信测试;
         MINI2440开发板自带 1 个I2C 总线AT24C08 芯片,用于I2C 总线测试。

--------------本次复习结束---------------

//==========================================================================================


 

猜你喜欢

转载自blog.csdn.net/weixin_39420903/article/details/82842594