精华内容
下载资源
问答
  • arm <p><img alt="image" src="https://user-images.githubusercontent.com/19410501/95097803-8594df80-074b-11eb-9fd7-04b83a96667f.png" /></p><p>该提问来源于开源项目:fluxcd/flux2</p></div>
  • arm assembly note

    2004-11-16 11:56:00
    ADS->GCC ARM assembly porting http://yygoing.spaces.live.com/?_c11_BlogPart_FullView=1&_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=amonth%3D9%26ayear%3D2006 转载于:...

    2004年11月16日13:44:40

    gcc inline assmbly 也放这吧
    http://gcc.gnu.org/onlinedocs/gcc-3.2.2/gcc/Extended-Asm.html

    1)tmp.jpg
    ZT FROM wanchengbuyi

    注意这些指令的配对使用,例如stmdb/ldmia

    2)关于!
    表示数据回写
    例如:
    ldr r0,[r1]!
    stmdb sp!,{r0,r4}
    !用于前索引方式中表示数据回写,例如:ldr r0,[r1,#4]!
    后索引方式不用!,数据始终回写,例如:ldr r0,[r1],#4
    对堆栈方式中用!,表示堆栈自动增加或者减少


     

    3)访问内存的LDR/STR指令索引方式
    ldr r0,[r1,#4]前索引,先加
    ldr r0,[r1],#4后索引,后加

    4)比较常用的加载地址指令
    Var EQU 0x1000
    ldr r0, =Var
    EQU生成的实际是一个标号(定义变量?),用于相对积存器寻址,与PC相对寻址相对。用EQU生成的标号用于数据段寻址。

     

    5)关于DCD指令,注意与EQU不同,相应的ldr指令用法也不同.
    定义一段内存区
    semantec
    Label DCD expr
    例如:
    ldr pc,Vector
        ....
    Vector DCD restVector
    restVector
        ....

     

    (6)LTORG与LDR
    LTORG是与LDR联合使用的literal pool,可以在函数尾部声明,这样相对PC偏移最少,如果不用LTORG,则编译器自动在(整个)程序末尾声名,但这样偏移有可能太大而编译不通过.

     

     

    (7)ADR,ADRL,LDR,MOV加载立即数
    关于这些指令的区别最好的文章是:
    http://dsl.ee.unsw.edu.au/dsl-cdrom/examples/intro/pseudo.s
    总结一下:
    adr用来加载地址,例如adr r0,var1
    ldr用来加载地址处的内容,例如ldr r0,var1
    上面的这种语法只能从.text段中加载(pc偏移?)
    但ldr r0,=var1可从任意段中加载地址

    MOV加载8位立即数
    8位立即数即第2操作数,必须可由一个8位常数循环移位偶数位得到,如0xf0000000,0xf00000001都是合法的。

    ldr有伪指令和非伪指令,伪指令后面的立即数前加=
    ADR在编译时会被替换成一条add或者sub指令,如果替换不了则报错。相对PC寻址
    ADRL会被替换成两条指令,替换不了报错误。相对PC或者积存器寻址
    这两条指令依据立即数的对齐方式不同,允许的立即数范围也不同。
    LDR则是产生文字池的方式加载常量,基于PC的相对寻址,专用加载32bit立即数.

    (7)stmdb与stmia
    如<采用公开源码和strongarm>书中P357页所说

    2007年5月30日
    关于APCS最权威的ARM官方
    http://www.arm.com/pdfs/aapcs.pdf
    http://www.ethernut.de/en/documents/arm-inline-asm.html
    这篇文章里谈到反汇编GCC时常看到的lr,fp,ip,等符号的意义.实际是APCS规定的,见
    http://www.sfmcu.com/ns_detail.asp?id=500725&nowmenuid=500416&previd=500715


    ADS->GCC ARM assembly porting
    http://yygoing.spaces.live.com/?_c11_BlogPart_FullView=1&_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=amonth%3D9%26ayear%3D2006

    转载于:https://www.cnblogs.com/embed/archive/2004/11/16/64330.html

    展开全文
  • ARM_Linux_NOTE_2

    2016-08-15 19:43:39
    ARM_Linux NOTE_2 Vine Farer 2016.08.09

    ARM_Linux NOTE_2

    Vine Farer

    2016.08.09


    1、ARM裸板汇编

    1)立即数

    一条指令是32位,最后一个操作数只剩下12位,高四位放幂,后8位放有效位

    • 当一个数的有效位(第1个1到最后一个1 总间隔)小于8位( 256 ),则是立即数

    • 当一个数的有效位大于8位,则不是立即数

    • 当一个数的有效位等于8:

      1)最后一个1在奇数位上,不是立即数

      2)最后一个1在偶数位上,是立即数

    • 若一个数按位取反是立即数,称之为有效数,只能用于mov后面。

      如:mov r0,#0xff00ffff
      其反汇编生成 mvn r0, #0x00ff0000



    2)相关指令

    • 数据处理指令

      算数指令:ADD、ADC、SUB、SBC、RSB、RSC

      逻辑指令:BIC、AND、ORR、EOR

      比较指令:CMP、CMN、TST、TEQ

      数据搬移:MOV、MVN
      (mov用来访问CPU内部寄存器,str、ldr用来访问片外资源,如内存或片上外设寄存器)

      此类指令只能对寄存器操作,不针对存储器

      • 进位加法

        ADDS r0, r0, r1 //加S是因为要让这个操作影响CPSR标志位(进位c)

        ADC r2,r2,r3//ADC是带进位的加法,如果上一条指令产生进位则一起加进来

      • 借位减法

        SUBS r0, r0, r1 //加S是因为要让这个操作影响CPSR标志位(进位c)

        SBC r2, r2, r3// SBC 是带进位的减法指令

    • SWP

      功能:寄存器和存储器间,由一次存储器读、一次存储器写组成原子操作。完成一个字节或字的交换

      不会被中断异常打断

      可以用来实现信号量

    • 软中断SWI

      32位:4位条件码、4位指令码、24位数据(包括 SWI 号)

      产生异常陷阱,跳转到SWI硬件向量

      SWI处理程序课检测SWI号,再采取对应操作
      ldr r0,[lr,#-4]
      bic r0,r0,#0xff000000

      进入 SVC 模式,进行特权操作

    • PSR传送指令

      专门用来访问 CPSR

      MRS 读取 CPSR 值,改变后,由 MSR 写回 CPSR



    3)ARM处理器寻址方式

    • 立即数:有一个数据是通过立即数获得

      mov r0,#34
      add r0,r1,#56

    • 寄存器寻址:所有操作数都是通过寄存器直接获得

      mov r0,r1
      add r0,r1,r2
      sub r0,r1,r4

    • 寄存器移位寻址:有一个操作数是通过寄存器移位计算获得

      mov r0,r1,lsl #4
      add r0,r1,r2,lsl #12

    • 寄存器间接寻址:把一个寄存器的值当做指针,来读写内存值

      ldr r0,[ r1 ] <=> r0 = *( r1 )
      str r0,[ r1 ] <=> *( r1 ) = r0
      (*往往会同时用到伪指令:ldr r0, = 0xffff0000. 让r0存一个值或地址 )

      ldrb strb ldrsb
      ldrh strh ldrsh

    • 基址变址寻址:把一个寄存器值当做基地址,然后做地址偏移,访问内存

      前索引:ldr r0,[ r1,#4 ] a = *( p + 1 )

      后索引:ldr r0,[ r1 ],#4 a = *( p ++ )

      自动索引: ldr r0,[ r1,#4 ]! a = *( ++p )

    • 多寄存器寻址:一次赋值或拷贝多个寄存器

      ldmxx r0!,{r1-r6,r9}
      stmxx r0!,{r1-r6,r9}

      i:增,指针增加 a:后,先取值后累加
      d:减,指针减小 b:前,先累加后取值

    • 堆栈寻址:专项用于 堆栈的 多寄存器寻址

      ldm、stm

      f:满、a:增、e:空、d:减

      ldmfd sp!,{r0-r12,lr} pop
      stmfd sp!,{r0-r12,lr} push

    • 相对寻址:相对于当前pc值得跳转

      b、bl
      bx、blx 带指令集切换跳转



    2、ARM汇编代码

    LED实验

    • 通过查找芯片手册与原理图找到需要配置的管脚

    • 配置相应管脚的寄存器

    • 源码(程序单步运行验证结果)

      安全代码:不影响其他寄存器中原有状态,只改变待操作的寄存器状态

      .text
      .globl _start
      _start:
      
          ldr r0,=0x114001e0   #读取GPF3CON寄存器地址到r0
          ldr r1,[r0]          #让r1存放r0指向的地址内的值,即待配置的寄存器值
          bic r1,r1,#0xf00000  #清零相应位
          orr r1,r1,#0x100000  #相应位置一
          str r1,[r0]          #将修改后的r1内的值回写到对应寄存器中
                               #管脚呈输出态
      
          ldr r0,=0x114001e4   
          ldr r1,[r0]
          orr r1,r1,#0b100000  #将对应数据寄存器置1,管脚输出高电平
          str r1,[r0]          #灯亮
      
          ldr r0,=0x114001e4
          ldr r1,[r0]
          bic r1,r1,#0b100000  #将对应数据寄存器清0,管脚输出低电平
          str r1,[r0]          #灯灭
      
      _stop:
          b _stop

      不安全代码:直接赋值给寄存器,会改变其他位的状态,不推荐

      ldr r1,=0x114001e0
      ldr r0,=0x00110000  #改变两个引脚状态为输出态
      str r0,[r1]
      
      ldr r1,=0x114001e4
      ldr r0,=0x30        #直接让led5、led4亮
      str r0,[r1]
    • Makefile

      SHELL=C:\WINDOWS\system32\cmd.exe
      all:
          arm-none-eabi-gcc -c -g asm.s -o asm.o
          arm-none-eabi-ld  -Ttext 0x40008000 asm.o -o asm.elf
          arm-none-eabi-objdump -D asm.elf > asm.dis  #生成反汇编文件
      clean:
          rm -rf *.elf *.o



    展开全文
  • ARM_Linux_NOTE_5

    2016-08-13 18:05:05
    ARM_Linux NOTE_5 Vine Farer 2016.08.12

    ARM_Linux NOTE_5

    Vine Farer

    2016.08.12


    4、Timer定时中断

    1)基本的定时(计时)中断

    • 配置定时器中断,需要额外设置TINT_CSTAT寄存器

      Timer 2为例

      Timer 2 interrupt enable 置一,使能Timer 2

      Timer 2 interrupt status 置一,清除中断状态

    • Timer 2中断模式初始化(code)

      void init_timer2(int ms) 
      {
          //-------------------Timer2----------------------//
          //----------- 39  71  ¨C  TIMER2-----------------//
          PWM.TCFG0 = (PWM.TCFG0 & (~(0xff << 8))) | (99 << 8); 
          // 100M / 100 = 1MHz
          PWM.TCFG1 = (PWM.TCFG1 & (~(0xf << 8))) | (0b0000 << 8);
          // 1M / 1 = 1MHz
      
          PWM.TCNTB2 = 1000000;// 1M / 1M 获得一秒的周期,初值自减到0,无需设置占空比
          PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b1010 << 12); 
          PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b1001 << 12); 
          //依旧循环自动装载,保证每1s减到0能触发一次中断
          PWM.TINT_CSTAT |= (1 << 2); //Timer 2 中断使能
      
          fun_p[71] = timer2_int;//装载定时器中断处理函数
      
          //------------------GIC中断设置------------------//
          ICDISER.ICDISER2 |= (1 << 7); 
          ICDIPTR.ICDIPTR17 = (ICDIPTR.ICDIPTR17 & (~(0xff << 24))) | (1 << 24); 
      
          ICDDCR = 1; 
          CPU0.ICCICR = 1; 
      }

      作定时器中断时,只须设置PWM.TCNTB2初值,确定一个计时的长度,自减到0触发中断即可。无需设置占空比

    • Timer 2中断处理代码(code)

      void (*fun_p[160])(void);
      
      void do_irq(void) //Timer定时中断也属IRQ,依旧调用do_irq()
      {
          int irq_number;
          irq_number = CPU0.ICCIAR & 0x3ff; 
          printf("irq:%d\n", irq_number);
      
          (*fun_p[irq_number])(); 
      
          CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_number; 
          //CPU0.ICC关闭对57号中断源的响应
      }
      
      void timer2_int(void)
      {
          printf("timer2\n"); //每1s触发一次中断,打印信息
      
          PWM.TINT_CSTAT = (PWM.TINT_CSTAT & (~(0b11111 << 5))) | (1 << 7);
          ICDICPR.ICDICPR2 = (1 << 7);
      }
      

      定时器中断也属IRQ,一样进入do_irq()处理,再调用timer2_int()

    2)用Timer 2中断处理按键消抖

    • 按键的外部中断初始化函数(code)

      void init_key()
      {
          /*gpx1_1 >> xeint_9 >> eint[9] >> 25  57  ¨C  EINT[9]*/
          GPX1.CON = (GPX1.CON & (~(0xf << 4))) | (0xf << 4);//配置GPIO端口为接收中断状态
          //配置中断源相关寄存器
          EXT_INT41_CON = (EXT_INT41_CON & (~(0xf << 4))) | (0x2 << 4);
          EXT_INT41_FLTCON0 |= (1 << 15);
          EXT_INT41_FLTCON0 &= ~(1 << 14); 
          EXT_INT41_MASK &= ~(1 << 1);
      
          fun_p[57] = key2_int;
      
          //日常GIC中断控制器设置
          ICDISER.ICDISER1 |= (1 << 25); //打开57号中断控制
          ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14 & (~(0xff << 8))) | (0b00000001 << 8); 
          //对应57号中断,选择CPU0处理
          ICDDCR = 1; //开中断混合器,等待外设中断触发
          CPU0.ICCICR = 1; //使能中断信号发送给CPU0
      }

      main()中须添加init_key();,然后死循环等待中断触发

    • Timer 2初始化函数(计时消抖)

      void init_timer2(int ms) 
      {
          //-----------------Timer2--------------------//
          PWM.TCFG0 = (PWM.TCFG0 & (~(0xff << 8))) | (99 << 8); // 100M / 100 = 1MHz
          PWM.TCFG1 = (PWM.TCFG1 & (~(0xf << 8))) | (0b0000 << 8); // 1M / 1 = 1MHz
      
          PWM.TCNTB2 = 1000 * ms; //可传参设置定时量
          PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b1010 << 12); 
          PWM.TCON = (PWM.TCON & (~(0xf << 12))) | (0b0001 << 12); 
          //必须关闭自动装载,按键触发中断后,只须一轮计时
          PWM.TINT_CSTAT |= (1 << 2);
      
          fun_p[71] = timer2_int;
          /* 39  71  ¨C  TIMER2*/
          ICDISER.ICDISER2 |= (1 << 7); 
          ICDIPTR.ICDIPTR17 = (ICDIPTR.ICDIPTR17 & (~(0xff << 24))) | (0b00000001 << 24); 
          ICDDCR = 1;
          CPU0.ICCICR = 1; 
      }
    •  中断处理函数

      void (*fun_p[160])(void);//函数指针数组,存放各个中断源处理函数
      
      void do_irq(void) 
      {
          int irq_number;
          irq_number = CPU0.ICCIAR & 0x3ff; 
          printf("irq:%d\n", irq_number);
      
          (*fun_p[irq_number])();
      
          CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_number;
          //CPU0.ICC关闭对71号中断源的响应
      }
      
      void key2_interrupt(void) 
      {
          init_timer2(20);
      
          EXT_INT41_PEND = (1 << 1); //清除中断源
          ICDICPR.ICDICPR1 = (1 << 25); //清除ICD对中断响应
      }
      
      void timer2_interrupt(void) 
      {
          printf("timer2\n");
          if (0 == (GPX1.DAT & (1 << 1)))
                  printf(">>>>>>>>>>>key2\n");
          PWM.TINT_CSTAT = (PWM.TINT_CSTAT & (~(0b11111 << 5))) | (1 << 7);//清除中断状态
          ICDICPR.ICDICPR2 = (1 << 7); //清除ICD对中断响应
      }

      程序执行过程中,按键按下触发 57 号外部中断,进入do_irq()后调用按键中断处理函数key2_interrupt()
      key2_interrupt()中初始化了Timer 2定时中断,开始计时,并且按键中断响应结束;
      等待 n ms后触发Timer 2定时中断,再次进入do_irq()调用timer2_interrupt(),打印信息。



    5、Watchdog Timer

    • Watchdog Timer定时喂狗,使整个硬件重启

      两级分频器,WTDATWTCNT、复位信号生成器

      WTCONWatchdog timer control register

      WTDATWatchdog Timer Data

      WTCNTWatchdog Timer Counter

      WTCLRINTWatchdog timer interrupt clear register

    • 定时重启 code

      int i = 10000;
      
      /*led5  GPX3_5*/
      GPF3.CON = (GPF3.CON & (~(0xf << 20))) | (0x1 << 20);
      
      //两级分配系数:255、128,最后为3khz
      WDT.WTCON = (WDT.WTCON & (~(0xff << 0))) | (0xff39 << 0);
      WDT.WTCNT = 6000;//计数从6000开始减,结束时过去2秒
      
      //正常情况下,看门狗计数减不到0循环就结束了,不会触发喂狗
      //但最后i = 10000,延时很长可以等到喂狗触发,硬件重启
      while (1)
      {
          WDT.WTCNT = 6000;
      
          GPF3.DAT ^= (1 << 5);
          mydelay_ms(500);
          GPF3.DAT ^= (1 << 5);
          mydelay_ms(500);
      
          GPF3.DAT ^= (1 << 5);
          mydelay_ms(i);
      }
    • Watchdog Timer定时器中断

      一般来说不会用此定时器中断



    6、RTC实时时钟

    • 基本功能

      自带Alarm FunctionTick Time Interrupt

      Supports BCD Number支持BCD码格式的年月日时间

      Supports Leap Year Generator支持闰年发生器

      Supports Independent Power Pin (RTCVDD)

      Supports millisecond tick time interrupt for RTOS kernel time tick.

    • RTC实时时钟的时间显示

      用BCD码配置初始时间信息,启动RTC时间开始走

      int main(void)
      {
          int sec,min,hour,week,day,mon,year;
      
          RTCCON = (RTCCON & (~(0xff << 0))) | (0b0001 << 0);
          //you can change the BCD time count setting开启时间设置功能
      
          RTC.BCDSEC = 0x48;
          RTC.BCDMIN = 0x59;
          RTC.BCDHOUR = 0x04;
          RTC.BCDWEEK = 0x3;
          RTC.BCDDAY = 0x22;
          RTC.BCDMON = 0x10;
          RTC.BCDYEAR = 0x016;
      
          RTCCON = RTCCON & (~(0xff << 0));//关闭时间设置功能
      
          while(1)
          {
              printf("%x-%x-%x week:%x %x:%x:%x\n",
                      RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,RTC.BCDWEEK,
                      RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);
          }
          return 0; // mov pc,lr  bx lr
      }
    • RTC定时闹钟

      本质是定时中断的闹钟系统

      void do_irq(void) 
      {
          int irq_number;
          irq_number = CPU0.ICCIAR & 0x3ff; 
          printf("irq:%d\n", irq_number);
      
          (*fun_p[irq_number])();
      
          CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_number; 
      }
      void alarm_int(void)
      {
          printf("alarm\n");
      
          RTCINTP = (1 << 1);
          ICDICPR.ICDICPR2 = (1 << 12);
      }
      int main(void) 
      {
          int i = 500;
      
          //依旧重设初始时间线
          RTCCON |= 1;
          RTC.BCDYEAR = 0x016;//(0 << 8)|(1 << 4)|(6 << 0);
          RTC.BCDMON = 0x08;
          RTC.BCDDAY = 0X31;
          RTC.BCDWEEK = 0X7;
          RTC.BCDHOUR = 0X23;
          RTC.BCDMIN = 0X59;
          RTC.BCDSEC = 0X55;
          RTCCON &= ~1;
      
          RTCALM.SEC = 0x2;//每分钟的第二秒触发中断
          RTCALM.ALM |=  (1 << 6) | (1 << 0);
          //  44  76  RTC_ALARM
          fun_p[76] = alarm_int;
      
          ICDISER.ICDISER2 |= (1 << 12); 
          ICDIPTR.ICDIPTR19 = (ICDIPTR.ICDIPTR19 & (~(0xff << 0))) | (0b00000001 << 0); 
          ICDDCR = 1; 
          CPU0.ICCICR = 1; 
      
          while(1){
              printf("2%03x-%02x-%02x week:%x %02x:%02x:%02x\n",
              RTC.BCDYEAR,RTC.BCDMON,RTC.BCDDAY,
              RTC.BCDWEEK,RTC.BCDHOUR,RTC.BCDMIN,RTC.BCDSEC);
      
              mydelay_ms(500);
          }
      
          return 0; // mov pc,lr  bx lr
      }
      



    7、ADC模数转换器

    • KEY Features of ADC for motor control

      Resolution: 10-bit / 12-bit (optional)
      Differential Nonlinearity Error: ± 2.0 LSB (Max.)
      Integral Nonlinearity Error: ± 4.0 LSB (Max.)
      Top Offset Error : 0 ~ + 55 LSB
      Bottom Offset Error : 0 ~ - 55 LSB
      Maximum Conversion Rate: 1 MSPS
      Low Power Consumption
      Power Supply Voltage: 1.8V (Typ.), 1.0V (Typ., Digital I/O Interface)
      Analog Input Range: 0 ~ 1.8V
      samsung / david.pang at 14:21,2012.05.07

    • 寄存器

      ADCCONADC Control Register

      ADCDLYADC Start or Interval Delay Register

      ADCDATADC Conversion Data Register

      CLRINTADCClear ADC Interrupt

      ADCMUXSpecifies the Analog input channel selection

    • ADC采集可调电阻的电压值code

      int main(void)
      {
          int value;
      
          ADCCON = (ADCCON & (~(0xf << 0)));
          ADCCON = (ADCCON & (~(0xff << 6)))| (99 << 6);
          ADCCON |= (1 << 14);
          ADCCON |= (1 << 16);
          ADCMUX = 0b0011;
      
          while(1)
          {
              ADCCON |= 1;
              printf("---\n");
              if((ADCCON & (1 << 15)) != 0){
                  value = ADCDAT & 0xfff;
                  printf(">>>>>>> value: %d\n",value);
              }
              mydelay_ms(500);
          }
      
          return 0; // mov pc,lr  bx lr
      }
      

      特别的,ADC有两种开启方式。
      ADCCON寄存器中

      • ENABLE_START = 1 ,
        A/D conversion starts and this bit is automatically cleared after the start-up.

        所以每次采样都需要使能一次

      • READ_START读启动,必须只读位ECFLG = 1才可启动,
        所以设置读启动后,要先象征性读一次ECFLG才可启动采样



    展开全文
  • ARM_Linux_NOTE_4

    2016-08-13 18:03:46
    ARM_Linux NOTE_4 Vine Farer 2016.08.11

    ARM_Linux NOTE_4

    Vine Farer

    2016.08.11


    1、GPIO

    ———— 详见NOTE_3实例


    2、外部中断IRQ

    1)Contex-A9共160个中断源(0 ~ 159)

    2)整个中断系统,以外部中断为例:

    • 中断源(如:按键中断)—> GIC 中断控制器 —> 内核

    • 中断触发后,中断源将中断请求发给 GIC

      GIC 第一级 ICD 中断混合器,获取中断号并按请求选择相应内核来处理

      GIC 第二级 ICC接口,Contex-A9四核处理器,每个处理器对应一个ICC

      GIC中含中断向量表,选择相应CPU时,要配置寄存器;
      160个中断源,每个分配8位地址空间,一共40个32位寄存器存放相关设置;
      8位的空间默认最多可选择8个CPU,对应位置一,则选中相应CPU。若同时选中多个CPU,则这些CPU须要竞争;
      如57号中断源,(57 + 1) / 4 = 14 余 2,则在推算对应寄存器位置时,找到第 14 行第 2 组的 8 位空间

    • 芯片手册查询(too important! English must be good!)

      获得中断源端口,到2.5章pin表中找对应标号

      由对应标号到9.9.2的GIC Interrupt Table中找到对应中断号

    • 中断流程中的寄存器配置(code)

      /*************************
       * key2  irq_set  GPX1_1 *
       *************************/
      GPX1.CON |= (0xf << 4);         //WAKEUP_INT1
      EXT_INT41_CON = (EXT_INT41_CON & ~(0xf << 4)) | (0x2 << 4);        //Falling edge triggered
      EXT_INT41_FLTCON0 |= 1 << 15;          //Enables Filter
      EXT_INT41_FLTCON0 &= ~(1 << 14);       //Delays filter
      EXT_INT41_MASK &= ~(1 << 1);           //Enables Interrupt
      
      ICDISR.ICDISR1 &= ~(1 << 25);      // The corresponding interrupt is Secure
      ICDISER.ICDISER1 |= (1 << 25);     //Enables the corresponding interrupt 57
      ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14 & ~(0xff << 8)) | (0b00000001 << 8);  //select CPU0
      
      ICDDCR = 1; //monitors the peripheral interrupt signals andforwards pending interrupts to the CPU interfaces.
      
      CPU0.ICCICR = 1;
      
    • 多中断处理(code)

      void (*irq_handler[160])(void);
      
      void do_irq(void)           //interrupt handler
      {
          int irq_num;
      
          irq_num = CPU0.ICCIAR & 0x3ff;      //get the interrupt ID
      
          printf("irq_num = %d\n", irq_num);
          (*irq_handler[irq_num])();
      
          CPU0.ICCEOIR = (CPU0.ICCEOIR & ~0x3ff) | irq_num;  //The ACKINTID value from the corresponding ICCIAR access
      }
      
      void key2(void)
      {
          mydelay_ms(30);
          if (0 == (GPX1.DAT & (1 << 1)))
                  printf("key2\n");
      
          EXT_INT41_PEND |= (1 << 1);     //Interrupt Occurs
          ICDICPR.ICDICPR1 |= (1 << 25);  //The effect depends on whether the interrupt is edge-triggered or level-sensitive
      }
      
      void key3(void)
      {
          mydelay_ms(20);
          printf("key3\n");
      
          EXT_INT41_PEND |= (1 << 2);     //Interrupt Occurs
          ICDICPR.ICDICPR1 |= (1 << 26);  //The effect depends on whether the interrupt is edge-triggered or level-sensitive
      
      }
      

      另外,在main函数中加上这几句:

      irq_handler[57] = key2;
      ...
      irq_handler[58] = key3;
      
      while (1);
      return 0; // mov pc,lr  bx lr
      



    3、时钟Timer

    Exynos 4412 SCP has five 32-bit Pulse Width Modulation (PWM) timers.

    Timer本身输出100M时钟信号

    我们可以利用多级分频器和脉宽设置,最终输出所需要的时钟信号

    • 4412 手册 P1292/1295 工作原理图

      100M 时钟信号经过两级分频器

      第一级系数0~255,第二级可设置系数1、1/2、1/4、1/8、1/16

      再经过Control Logic单元
      包括:TCNTBnTCMPBnTCNTnTCMPn4个寄存器

      1、TCNTBn填计数初值,这个值在Timer工作后会自减,TCMPBn填比较值。

      正常情况下:
      *:If the timer reaches 0, then TCNTBn and TCMPBn registers are loaded into TCNTn and TCMPn.
      反之:

      • manual update = 1 手动更新,
        初值和比较值从TCNTBnTCMPBn填入到TCNTnTCMPn
        Timer从初值开始自减。初值自减到和比较值相等后,执行 * ,会使电平反转一次。
        (第一次必须手动更新,因为TCNTnTCMPn里面可能值为0,无法启动,手动给个值让它开始自减)
      • 然后Timer继续减到0,再次出发 * 的操作,电平再次反转。此轮手动更新结束;
        之后设置manual update = 0,auto-reload = 1 自动装载。则后面一直自动装载,每减到0,电平翻转。形成再一级的时钟分频。
        (可调节比较值改变时钟信号的占空比,输出特定的PWM波)

      2、如果开启Timer定时中断,则只要设置一个初值,自动装载,减到 0 ,会触发interrupt request,再去IRQ中断处理函数执行

    • code(为beep输出稳定而精确的时钟信号)

      GPD0.CON = (GPD0.CON & (~(0xf << 0))) | (0x2 << 0);
      //beep设置为时钟控制模式
      
      PWM.TCFG0 = (PWM.TCFG0 & (~(0xff << 0))) | (99 << 0);
      // 100M / (99 + 1) = 1MHz 
      PWM.TCFG1 = (PWM.TCFG1 & (~(0xf << 0))) | (0b0010 << 0);
      // 1M / 4 = 250KHz
      
      PWM.TCNTB0 = 250 - 1;// 250K / 250 = 1KHz
      PWM.TCMPB0 = 250 / 2;// 50%占空比输出
      
      PWM.TCON = (PWM.TCON & (~(0xff << 0))) | (0b01010 << 0);
      //Stops Timer 0、manual update、auto-reload
      PWM.TCON = (PWM.TCON & (~(0xff << 0))) | (0b01001 << 0);
      //Stops Timer 0、auto-reload
    展开全文
  • ARM_Linux_NOTE_6

    2016-08-14 17:52:46
    ARM_Linux NOTE_6 Vine Farer 2016.08.14 定时闹钟实验
  • ARM_Linux_NOTE_1

    2016-08-15 19:42:13
    ARM_Linux NOTE_1 Vine Farer 2016.08.05 1、基本结构 2、计算机系统硬件组成
  • ARM_Linux_NOTE_3

    2016-08-13 18:01:14
    ARM_Linux NOTE_3 Vine Farer 2016.08.10 3、ARM汇编、C混合编程1)LED实验 汇编.text .globl _start _start: nop bl main #跳进main函数 nop_stop: b _stopmain.c中的main函数volatile: 1、修饰代码块,...
  • <div><p>Can you please add an Arm 7 64 build for the latest major build similar to your effort in 1.20.0 - Simplenote-linux-1.20.0-arm64.deb OR please add instructions to build as I trying to learn by...
  • ARM Juno GCC5 support note.

    2020-11-23 01:14:50
    <div><p>It fixes #822 (ramdisk.img size) <p>Signed-off-by: Miraje Gentilal miraje.gentilal.com</p><p>该提问来源于开源项目:OP-TEE/optee_os</p></div>
  • <div><p>Signed-off-by: Cedric Chaumont cedric.chaumont.com</p><p>该提问来源于开源项目:OP-TEE/optee_os</p></div>
  • arch/arm/kernel/calls.S 声明了系统调用函数和sys_call_table include/asm-arm/unistd.h 定义了系统调用的调 用号规则 vector_swi定义在arch/arm/kernel/entry-common.S vector_IRQ定义在 arch/arm/kernel/...
  • <div><p>Nordic Dev Kit board names were changed in Zephyr v2.3 release, following the standard Board deprecation policy. Two releases later we do not need to keep references to the old names in the ...
  • <ul><li>Added clarification regarding the installation of the ARM Compiler 5 on 64-bit Linux machines</li><li>Added an example WIndows path to the IAR toolchain information</li><li>My text editor ...
  • arm linux debug notes (error note)

    千次阅读 2014-06-25 11:17:43
    Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c53c7d Table: 8000406a DAC: 00000015 2. pointer should not NULL porch = kzalloc(sizeof(struct timing_rgb), GFP_...
  • <div><p>as describe in title</p><p>该提问来源于开源项目:opengapps/opengapps</p></div>
  • Note that some targets which are incompatible with ARMC6 will stay with ARMC5, but this is temporary and we expect to move all targets to ARMC6 soon. The tools changes are in place to use the right ...
  • ARM Support

    2020-12-30 12:22:09
    <p>On a side note, building maturin works, but then fails to be used since this happens: <pre><code> 💥 maturin failed Caused by: The architecture ARM is not supported </code></pre>该提问来源于...
  • AndroidStudio for arm aapt for arm* https://www.jianshu.com/search?q=androidstudio for arm&page=1&type=note
  • note: the mangling of 'va_list' has changed in GCC 4.4 I think that the warning is accurate; the mangling of va_list has indeed changed on ARM in GCC 4.4 in order to conform to the ARM ABI
  • <p>Note that now it is easy to do arm64 assembly diffs using the <a href="https://github.com/dotnet/jitutils">jit-diff</a> tool, on Windows using the arm64 protononjit.dll compiler, as follows: ...
  • /mnt/j/workspace/dotnet_coreclr_arm64_linux_debug/src/pal/src/exception/seh-unwind.cpp:88:73: note: passing argument to parameter 'cursor' here static void WinContextToUnwindCursor(CONTEXT ...
  • bde on ARM architecture

    2020-11-27 16:41:54
    ’ are: arm1020e arm1020t arm1022e arm1026ej-s arm10e arm10tdmi arm1136j-s arm1136jf-s arm1156t2-s arm1156t2f-s arm1176jz-s arm1176jzf-s arm2 arm250 arm3 arm6 arm60 arm600 arm610 arm620 arm7 arm70 arm...
  • Adding ARM Architecture

    2020-12-09 12:22:16
    <p>Side note: arm-linux-gnueabi-gcc-5 is being used instead of arm-linux-gnueabi-gcc because, using some code from the devtty0's blog to build an nvram hook, I found it was looking for libc.so.6 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,042
精华内容 3,216
关键字:

armnote