• Tiny4412之重力感应器驱动


    一:Tiny4412 裸板重力感应驱动编写

      整个编写过程大概分为如下几步:

      (1)在底板上找到重力感应器的所在位置,找到芯片型号(我用的板子上重力感应器芯片型号为:MMA7660FC

      (2)通过型号查看重力感应器电路图,了解每个引脚的功能

      (3)找到引脚对应的网标(EINT,SDL,SCL)配置其相应的gpio口

      (4)配置芯片相关寄存器

      (5)使用I2C来读取重力感应器相应寄存器的值

      下面是整个驱动的简单流程图:

    通过看底板我们知道了重力感应器的控制芯片型号为:MMA7660FC,接下来我们就在看看改芯片的电路图(如下):

    由上图我们可以看出它的外部中断XEINT25,用到的i2c总线为SDA3、SCL3

    通过网标我们可以看到它是怎么连接到核心板上的(soc)

    由上图可知,XEINT25、I2CSDA3、SCL3所对应的gpio分别为GPA1_2、GPA1_3、GPX3_1,之后我们就可以配置gpio口为相应的功能

    通过datasheet我们可以找到它的外部中断号为64,如下图:

     简单了解了mma7660的电路图之后我们就需要看芯片的datasheet,了解里面寄存器的配置及功能

    首先看一下整个芯片与我们核心板的连接图:

    由上图我们可以看出,芯片连接到我们核心板(soc)的总共为三根线:INT( 中断信号),SDA、SCL(通i2c来进行寄存器的配置和读取)

    下面看一下该芯片的几种工作模式:

    今天我们实验的所需要的就是就当板子在晃动的时候它会出发中断,我们利用i2c来读取它相应寄存器的值,来判断前后左右以及X、Y、Z的值

    下面是该芯片的寄存器及功能:

    由上图我们可以看出寄存器:0x00、0x01、0x02它的底六位分别存储着对应的X、Y、Z的值,因此在之后的试验中我们就可以利用i2c来读取它里面的值

    0x03这个寄存器的具体功能如下所所示、它里面存储了前后左右上下的值:

    下面的几个寄存器是我们需要配置的:

    这个寄存是:该芯片里面的中断寄存器,我们需要配置相应值来响应中断,光配置外部中断是不可以的,我们需要配置该寄存器来响应我们的外部中断

    该寄存器是配置相应的模式,我们需要配置它为shake,当我们在晃动板子是可以出发中断;配置好这两个寄存器之后,我们就可以使用I2C来读取对应寄存器的值了

    接下来我们需要做的就是设置相应的gpio口,以及配置好I2C的相应寄存器:

      I2C总线驱动在上一篇中已经介绍了,I2C总线设备分为四种模式:主端发送、主端接收,从端发送、从端接收,在该驱动中我们用到的只有主发跟主收,下面是相应的流程图,整个I2C的读写都是按照这个流程:

      主端发送:

    主端接收:

    配置好整个I2C之后我们就可以对芯片进行相应的设置和读取了,下面贴出真个重力感应驱动的代码:

     1 #ifndef __REGS_H
     2 #define __REGS_H
     3 
     4 #define printf(...) (((int (*)(const char *, ...))0xc3e114d8)(__VA_ARGS__))
     5 
     6 #define GPA1CON            (*(volatile unsigned long *)0x11400020)
     7 #define I2CCON3         (*(volatile unsigned long *)0x13890000)
     8 #define I2CADD3         (*(volatile unsigned long *)0x13890008)
     9 #define I2CSTAT3        (*(volatile unsigned long *)0x13890004)
    10 #define I2CDS3          (*(volatile unsigned long *)0x1389000C)
    11 #define I2CLC3          (*(volatile unsigned long *)0x13890010)
    12 
    13 #define GPD1CON            (*(volatile unsigned long *)0x114000C0)
    14 #define GPD1PUD         (*(volatile unsigned long *)0x114000C8)
    15 #define I2CCON1         (*(volatile unsigned long *)0x13870000)
    16 #define I2CADD1         (*(volatile unsigned long *)0x13870008)
    17 #define I2CSTAT1        (*(volatile unsigned long *)0x13870004)
    18 #define I2CDS1          (*(volatile unsigned long *)0x1387000C)
    19 #define I2CLC1          (*(volatile unsigned long *)0x13870010)
    20 
    21 #define ICCICR_CPU0        (*(volatile unsigned long *)0x10480000)
    22 #define ICCPMR_CPU0        (*(volatile unsigned long *)0x10480004)
    23 #define ICDDCR            (*(volatile unsigned long *)0x10490000)
    24 #define ICDIPR15_CPU0    (*(volatile unsigned long *)0x1049043C)
    25 #define ICDIPTR15_CPU0    (*(volatile unsigned long *)0x1049083C)
    26 #define ICDISER1_CPU0    (*(volatile unsigned long *)0x10490104)
    27 #define ICDSGIR            (*(volatile unsigned long *)0x10490f00)
    28 #define ICCIAR_CPU0     (*(volatile unsigned long *)0x1048000C)
    29 #define ICCEOIR_CPU0     (*(volatile unsigned long *)0x10480010)
    30 
    31 #define GPX1CON            (*(volatile unsigned long *)0x11000C20)
    32 
    33 #define EXT_INT41_CON        (*(volatile unsigned long *)0x11000E04)
    34 #define EXT_INT41_MASK        (*(volatile unsigned long *)0x11000F04)
    35 #define EXT_INT41_PEND        (*(volatile unsigned long *)0x11000F44)
    36 
    37 #define GPX3CON (*(volatile unsigned long *)0x11000c60)
    38 #define GPX3DAT    (*(volatile unsigned long *)0x11000c64)
    39 #define GPD0CON    (*(volatile unsigned long *)0x110000a0)
    40 #define GPD0DAT    (*(volatile unsigned long *)0x110000a4)
    41 
    42 #define ICCICR_CPU0        (*(volatile unsigned long *)0x10480000)
    43 #define ICCPMR_CPU0        (*(volatile unsigned long *)0x10480004)
    44 #define ICDDCR            (*(volatile unsigned long *)0x10490000)
    45 #define ICDIPR16_CPU0    (*(volatile unsigned long *)0x10490440)
    46 #define ICDIPTR16_CPU0    (*(volatile unsigned long *)0x10490840)
    47 #define ICDISER2_CPU0    (*(volatile unsigned long *)0x10490108)
    48 #define ICDSGIR            (*(volatile unsigned long *)0x10490f00)
    49 #define ICCIAR_CPU0     (*(volatile unsigned long *)0x1048000C)
    50 #define ICCEOIR_CPU0     (*(volatile unsigned long *)0x10480010)
    51 
    52 #define EXT_INT43_CON        (*(volatile unsigned long *)0x11000E0C)
    53 #define EXT_INT43_MASK        (*(volatile unsigned long *)0x11000F0C)
    54 #define EXT_INT43_PEND        (*(volatile unsigned long *)0x11000F4C)
    55 
    56 #endif
    regs.h
     1 #ifndef __MMA_H
     2 #define __MMA_H
     3 
     4 void mma_set();
     5 void mma_read();
     6 void i2c_gpio_set();
     7 int master_write(unsigned char slaveaddr, unsigned char subaddr, unsigned char *data);
     8 int master_read(unsigned char slaveaddr, unsigned char subaddr, unsigned char *data);
     9 void i2c_init();
    10 void i2c_exit();
    11 void irq_init();
    12 void do_irq();
    13 void enable_mmu();
    14 void init_table(unsigned long *addr);
    15 void memcpy(unsigned char *dest, unsigned char *src, unsigned int len);
    16 
    17 extern unsigned long vector_start;
    18 
    19 #endif //MMA_H
      1 #include "mma.h"
      2 #include "regs.h"
      3 
      4 void (*udelay)(int ) = 0xc3e04fec;
      5 
      6 int main(void)
      7 {
      8     *(unsigned long *)0x47000000 = do_irq;
      9     enable_mmu();
     10     i2c_gpio_set(); 
     11     mma_set();    
     12     irq_init();
     13     memcpy(0x0, vector_start, 0x1000);
     14 }
     15 
     16 void do_irq()
     17 {
     18     if(EXT_INT43_PEND & (1 << 1)) {//judge interrupt occurs
     19         EXT_INT43_PEND |= (1 << 1);//clear interrupt 
     20         mma_read(); 
     21     }
     22 }
     23 
     24 void mma_set()
     25 {
     26     /*$06: Interrupt Setup Register
     27        0x98 <--> 芯片地址 0x6 <---> 寄存器地址
     28      */
     29     master_write(0x98, 0x6, 0xe3); // e3 1110 0011
     30     /*
     31      -----------------------------------------------------------
     32     D7         D6         D5         D4         D3         D2         D1         D0
     33     SHINTX SHINTY SHINTZ  GINT       ASINT    PDINT   PLINT  FBINT
     34     1         1         1         0         0         0         1         1
     35     -----------------------------------------------------------
     36     FBINT
     37     0: Front/Back position change does not cause an interrupt
     38     1: Front/Back position change causes an interrupt
     39     PLINT
     40     0: Up/Down/Right/Left position change does not cause an
     41     interrupt
     42     1: Up/Down/Right/Left position change causes an interrupt
     43     PDINT
     44     0: Successful tap detection does not cause an interrupt
     45     1: Successful tap detection causes an interrupt
     46     ASINT
     47     0: Exiting Auto-Sleep does not cause an interrupt
     48     1: Exiting Auto-Sleep causes an interrupt
     49     GINT
     50     0: There is not an automatic interrupt after every
     51     measurement
     52     1: There is an automatic interrupt after every measurement,
     53     SHINTX
     54     0: Shake on the X-axis does not cause an interrupt or set the
     55     Shake bit in the TILT register
     56     1: Shake detected on the X-axis causes an interrupt, and sets
     57     the Shake bit in the TILT register
     58     SHINTY
     59     0: Shake on the Y-axis does not cause an interrupt or set the
     60     Shake bit in the TILT register
     61     1: Shake detected on the Y-axis causes an interrupt, and sets
     62     the Shake bit in the TILT register
     63     SHINTZ
     64     0: Shake on the Z-axis does not cause an interrupt or set the
     65     Shake bit in the TILT register
     66     1: Shake detected on the Z-axis causes an interrupt, and sets
     67     the Shake bit in the TILT register.
     68 
     69     */
     70 
     71     /*$07: Mode Register (Read/Write)*/
     72     master_write(0x98, 0x7, 0xd9); //d9 1101 1001
     73     /*
     74      -----------------------------------------------------------
     75     D7         D6         D5         D4         D3         D2         D1         D0
     76    IAH        IPP    SCPS     ASE     AWE     TON       -     MODE
     77     1        1         0         1       1       0          0       1
     78     -----------------------------------------------------------
     79      MODE
     80     0: Standby mode or Test Mode depending on state of TON
     81     1: Active mode
     82     TON
     83     0: Standby Mode or Active Mode depending on state of MODE
     84     1: Test Mode
     85     AWE
     86     0: Auto-Wake is disabled
     87     1: Auto-Wake is enabled.
     88     ASE
     89     0: Auto-Sleep is disabled
     90     1: Auto-Sleep is enabled
     91     SCPS
     92     0: The prescaler is divide-by-1. The 8-bit internal Sleep
     93     Counter input clock is the samples per second set by
     94     AMSR[2:0]
     95     1: Prescaler is divide-by-16. The 8-bit Sleep Counter input
     96     clock is the samples per second set by AMSR[2:0] divided by
     97     16,
     98     IPP
     99     0: Interrupt output INT is open-drain.
    100     1: Interrupt output INT is push-pull
    101     IAH
    102     0: Interrupt output INT is active low
    103     1: Interrupt output INT is active high
    104      */
    105 }
    106 
    107 void mma_read()
    108 {
    109     unsigned char val;
    110     unsigned char i;
    111     for(i = 0; i < 4; i++)
    112     while(1) {
    113         master_read(0x98, i, &val); //read 
    114         if((val & (1 << 6)) == 0) {
    115             if(0 == i) {
    116                 printf("X is %d
    ", 0x3f & val); //6-bit output value X 
    117             }
    118             if(1 == i) {
    119                 printf("Y is %d
    ", 0x3f & val); //6-bit output value Y
    120             }
    121             if(2 == i) {
    122                 printf("Z is %d
    ", 0x3f & val); //6-bit output value Z
    123             }
    124             if(3 == i) {
    125                 /*BaFro[1:0]
    126                    *01: Front
    127                    *10: Back
    128                    */
    129                 if((val & 3) == 1)
    130                     printf("Front
    ");
    131 
    132                 if((val & 3) == 2)
    133                     printf("Back
    ");
    134                 /*PoLa[2:0]
    135                  * 001: Left 
    136                  * 010: Right
    137                  * 101: Down 
    138                  * 110: Up   
    139                  * */
    140                 if(((val >> 2) & 0x7) == 1)
    141                     printf("Left
    ");
    142 
    143                 if(((val >> 2) & 0x7) == 2)
    144                     printf("Right
    ");
    145 
    146                 if(((val >> 2) & 0x7) == 5)
    147                     printf("Down
    ");
    148 
    149                 if(((val >> 2) & 0x7) == 6)
    150                      printf("Up
    ");
    151 
    152             }
    153             break;    
    154         }
    155     }
    156 }
    157 
    158 int master_write(unsigned char slaveaddr, unsigned char subaddr, unsigned char *data)
    159 {
    160     i2c_init();
    161 
    162     unsigned char timeout = 50;
    163     while(timeout) {
    164         udelay(20);    
    165         if(!(I2CSTAT3 & (1 << 5))){ //judge I2C-bus busy signal (0 busy or no busy) 
    166             I2CCON3 |= (1 << 7); //I2C-bus acknowledge enable 
    167             I2CDS3 = slaveaddr; // slave addr
    168             I2CSTAT3 = 0xf0;   // Master transmit mode 
    169             udelay(20);
    170 
    171             timeout = 50;
    172             while(timeout) {
    173                 udelay(20);
    174                 if(I2CCON3 & (1 << 4)) {//Interrupt is pending 
    175                     I2CDS3 = subaddr; //register addr
    176                     udelay(10);
    177                     I2CCON3 &= ~(1 << 4); //Clears pending condition and resumes the operation
    178                     udelay(20);
    179                     break;                    
    180                 }
    181                 timeout --;
    182             } 
    183             if(0 == timeout)
    184                 return -1;
    185             
    186             timeout = 50;
    187             while(timeout) {
    188                 udelay(20);
    189 
    190                 if(I2CCON3 & (1 << 4)) { // interrupt is pending
    191                     I2CDS3 = data; //write data
    192                     udelay(10);
    193                     I2CCON3 &= ~(1 << 4); //Clear pending bit to resume.(每次都要写0才会发送) 
    194                     udelay(10);
    195                     break; 
    196                 } 
    197                 timeout--;
    198                 if(0 == timeout)
    199                     return -1;
    200             }
    201         
    202             timeout = 50;
    203             while(timeout) {
    204                 udelay(20);
    205                 if(I2CCON3 & (1 << 4)) {//interrupt is pending
    206                     I2CSTAT3 = 0xd0; //Master transmit mode stop
    207                     udelay(10);
    208                     I2CCON3 &= ~(1 << 4);
    209                     udelay(10);
    210                     break;
    211                 }
    212                 timeout--;
    213             }
    214             if(0 == timeout)
    215                 return -1;
    216             
    217             while(1 == (I2CSTAT3 & (1 << 5))) {// Wait until the stop condition takes effect
    218                  ;
    219             }
    220             i2c_exit(); //exit i2c
    221             return 0;
    222         }
    223         timeout--;
    224     }
    225     return -1;
    226 }
    227 
    228 int master_read(unsigned char slaveaddr, unsigned char subaddr, unsigned char *data)
    229 {
    230     i2c_init();
    231     unsigned char count = 0;
    232     unsigned char buf[14];
    233     unsigned char timeout = 50;    
    234 
    235     //-------------write------------------
    236     while(timeout)
    237     {    
    238         udelay(20);
    239         if(!(I2CSTAT3 & (1 << 5)))//判断忙与不忙
    240         {
    241             I2CCON3 |= (1 << 7);  //开启I2C总线ack信号
    242             I2CDS3 = slaveaddr;  //写入要读的芯片地址
    243             I2CSTAT3 = 0xf0;    //选择主端发送模式
    244             udelay(20);
    245             timeout = 50;
    246             while(timeout)
    247             {
    248                 udelay(20);
    249                 if( I2CCON3 & (1<<4)) //等待中断(ACK信号)
    250                 {
    251                     I2CDS3 = subaddr; //写入要读的寄存器地址
    252                     udelay(10);
    253                     I2CCON3 &= ~(1 << 4); //向这一位写0,发送,清楚等待条件,恢复操作
    254                     udelay(20);
    255                     break;
    256                             
    257                 }
    258                 timeout--;
    259             }
    260             if(0 == timeout)
    261                 return -1;
    262             timeout = 50;
    263             while(timeout)
    264             {
    265                 udelay(20);
    266                 if(I2CCON3 & (1 << 4))
    267                 {    
    268                     I2CSTAT3 = 0xd0; //set Read Not busy (If Read) 
    269                     udelay(10);
    270                     I2CCON3 &= ~(1<<4);
    271                     udelay(10);
    272                     break;
    273                 }
    274                 timeout--;
    275             }
    276             if(0 == timeout)
    277                 return -1;
    278 
    279     //------------read------------------
    280             timeout = 50;
    281             while(timeout)
    282             {
    283                 udelay(20);
    284                 if(!(I2CSTAT3 & (1 << 5)))
    285                 {
    286                     I2CCON3 |= (1 << 7);    
    287                     I2CDS3 = slaveaddr;//写入芯片地址
    288                     I2CSTAT3 = 0xb0; //选择主端接收模式
    289                     udelay(10);
    290                     break;
    291                 }
    292                 timeout--;
    293             }
    294             if(0 == timeout)
    295                 return -1;
    296 
    297             timeout = 100;
    298             while(timeout)
    299             {
    300                 udelay(20);
    301                 if(I2CCON3 & (1 << 4))
    302                 {
    303                     buf[count] = I2CDS3; //read
    304                     count++;
    305                     if(12 == count)    
    306                         I2CCON3 &= ~(1 << 7);//I2C-bus acknowledge Disable 
    307 
    308                     I2CCON3 &= ~(1 << 4); //Clear pending bit to resume 
    309                     udelay(10);
    310                     if(12 == count)
    311                         break;
    312                 }
    313                 timeout--;
    314             }
    315             if(0 == timeout)
    316                 return -1;
    317 
    318             timeout = 50;
    319             while(timeout)
    320             {
    321                 udelay(20);
    322                 if(I2CCON3 & (1 << 4))//wait ack
    323                 {
    324                     I2CSTAT3 = 0x90;//主端接受模式结束
    325                     I2CCON3 &= ~(1 << 4);
    326                     udelay(10);
    327                     break;
    328                 }
    329                 timeout--;
    330             }
    331             if(0 == timeout)
    332                 return -1;
    333 
    334             while(1 == (I2CSTAT3 & (1 << 5))) //Wait until the stop condition takes effect
    335 
    336             {
    337                 printf("in while read 
    ");;
    338             }
    339             i2c_exit(); //exit i2c
    340             *data = buf[subaddr + 1];
    341             
    342             return 0;
    343         }
    344         timeout--;
    345     }
    346     return -1;
    347 }
    348 
    349 /*SDA3 <---> GPA1_2 SCL3 <-->GPA1_3 */
    350 void i2c_gpio_set()
    351 {
    352     printf("i2c_gpio_set
    ");
    353     GPA1CON &= ~(0xff << 8);
    354     GPA1CON |= (0x33 << 8);
    355 }
    356 
    357 void i2c_init()
    358 {
    359     I2CCON3 = 1 | (1 << 5) | (1 << 6);
    360     I2CSTAT3 = (1 << 4);
    361     I2CLC3 = 0x7;    
    362 }
    363 
    364 void i2c_exit()
    365 {
    366     I2CCON3 = 0;
    367     I2CSTAT3 = 0;
    368     I2CLC3 = 0;    
    369 
    370 }
    371 
    372 void irq_init()
    373 {
    374     //step 1: enable cpu cpsr
    375     __asm__ __volatile__(
    376         "mrs r0, cpsr
    "
    377         "bic r0, r0, #0x80
    "
    378         "msr cpsr, r0
    "
    379         ::: "r0"
    380     );
    381 
    382     //step 2: GIC NO.62
    383     ICCICR_CPU0 = 1;//global enable interrupt (total switch)
    384     ICCPMR_CPU0 = 0xff;//This register provides an interrupt priority filter. 
    385     ICDDCR = 1;//This register enables forwarding of pending interrupts to the CPU interfaces
    386 
    387     /*一共有1024个中断源,只有160个中断号*/
    388     //id = 64. 一个ICDIPR 控制4个中断,64 / 4 = 16 ...0, so ICDIPR=16 
    389     ICDIPR16_CPU0 = (1 << 0);//the zero is the highest priority 
    390     ICDIPTR16_CPU0 = (1 << 0);//0x1 ---> for cpu0
    391     ICDISER2_CPU0 = (1 << 0);// enable interrupt 0
    392  
    393     //step 4:set ext_int    
    394     EXT_INT43_CON &= ~(0xf << 4);
    395     EXT_INT43_CON |= (0x4 << 4);//falling edge; low level
    396     EXT_INT43_MASK = 0;//enable extint43_1
    397 
    398     //step 3: set gpio
    399     GPX3CON &= ~(0xf << 4);
    400     GPX3CON |= (0xf << 4);//xeint25 <==> gpx3_1 ---->0xF = EXT_INT43[1]
    401     
    402     printf("irq over
    ");
    403 }
    404 
    405 
    406 void enable_mmu()
    407 {
    408     /*构建表*/
    409      unsigned long addr = 0x50000000;
    410      init_table(addr);
    411 
    412      /*打开mmu*/
    413      unsigned long mmu = 0;
    414      mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8);
    415 
    416      __asm__ __volatile__ (
    417              "mov r0, #3
    "
    418              "MCR p15, 0, r0, c3, c0, 0
    "//设置为管理员
    419              "MCR p15, 0, %0, c2, c0, 0
    "//设置表的地址
    420              "MCR p15, 0, %1, c1, c0, 0
    "//开启mmu
    421              :
    422              :       "r" (addr), "r" (mmu)
    423              :
    424      );
    425 
    426 }
    427 
    428 void init_table(unsigned long *addr)
    429 {
    430     unsigned long va = 0;
    431     unsigned long phys = 0;
    432  
    433     //0x40000000-0x80000000 -> 0x40000000-0x80000000        
    434     for(va = 0x40000000; va < 0x80000000; va += 0x100000) {
    435             phys = va;
    436             addr[va >> 20] = phys | 2;
    437     }
    438  
    439     //0x10000000-0x14000000 -> 0x10000000-0x140000000       
    440     for(va = 0x10000000; va < 0x14000000; va += 0x100000) {
    441             phys = va;
    442             addr[va >> 20] = phys | 2;
    443     }
    444     //0x10000000-0x14000000 -> 0x10000000-0x140000000       
    445     for(va = 0x0; va < 0x10000000; va += 0x100000) {
    446             phys = va + 0x70000000;
    447             addr[va >> 20] = phys | 2;
    448     }
    449 
    450 }
    451 
    452 void memcpy(unsigned char *dest, unsigned char *src, unsigned int len)
    453 {
    454     int i = 0;
    455     for(i = 0; i < len; i++) {
    456         dest[i] = src[i];
    457     }
    458 }
    459 
    460  __asm__(
    461  
    462 /*异常向量表*/
    463  "vector: 
    "
    464  "       b reset
    "
    465  "       b und
    "
    466  "       b swi
    "
    467  "       b pre_abt
    "
    468  "       b data_abt
    "
    469  "       .word 0x0
    "
    470  "       b irq
    "
    471  "       b fiq
    "
    472  "reset:
    "
    473  "und:
    "
    474  "       mov sp, #0x47000000
    "
    475  "       stmdb sp!, {r0-r12, lr}
    "
    476  
    477  "       ldr r3, =0x47000004
    "
    478  "       ldr r2, [r3]
    "
    479  "       blx r2
    "
    480  
    481  "       mov sp, #0x47000000
    "
    482  "       ldmdb sp, {r0-r12, pc}^ 
    "
    483  
    484  "swi:
    "
    485  "       mov sp, #0x47000000
    "
    486  "       stmdb sp!, {r0-r12, lr}^
    "
    487  
    488  "       mov sp, #0x47000000
    "
    489  "       ldmdb sp, {r0-r12, pc}^ 
    "
    490  
    491  "pre_abt:
    "
    492  
    493  "data_abt:
    "
    494  "       mov sp, #0x47000000
    "
    495  "       sub lr, lr, #4
    "
    496  "       stmdb sp!, {r0-r12, lr}
    "
    497  
    498  "       ldr r3, =0x47000008
    "
    499  "       ldr r2, [r3]
    "
    500  "       blx r2
    "
    501  
    502  "       mov sp, #0x47000000
    "
    503  "       ldmdb sp, {r0-r12, pc}^ 
    "
    504  "irq:
    "
    505  
    506  "       mov sp, #0x47000000
    "
    507  "       sub lr, lr, #4
    "
    508  "       stmdb sp!, {r0-r12, lr}
    "
    509  
    510  "       ldr r3, =0x47000000
    " //跳转到c语言
    511  "       ldr r2, [r3]
    "
    512  "       blx r2
    "
    513  
    514  "       mov sp, #0x47000000
    "
    515  "       ldmdb sp, {r0-r12, pc}^ 
    "
    516  
    517  "fiq:
    "
    518  
    519          ".global vector_start
    "
    520  "vector_start: 
    "
    521          ".word vector 
     "
    522  
    523  );

      

      

  • 相关阅读:
    python中字典dict pop方法
    Markdown 学习资源
    Windows bat 设置代理
    Warning: Permanently added '...' (RSA) to the list of known hosts --Windows下git bash 警告处理
    subilme增加对markdown的高亮支持
    ubuntu笔记1
    Sublime Python 插件配置合集
    Excel VBA 快捷键 代码
    贩卖守望先锋账号
    如何用VS2017用C++语言写Hello world 程序?
  • 原文地址:https://www.cnblogs.com/wenqiang/p/4957641.html
Copyright © 2020-2023  润新知