zoukankan      html  css  js  c++  java
  • 一步步学习操作系统(1)——参照ucos,在STM32上实现一个简单的多任务(“精简版”)

    相同的代码,另外还提供了讲解更详细的“啰里啰嗦版”,以供参考。

    这里,我们将实现一个简单的多任务OS。其任务调度的机理如下:

    1、 main函数创建任务,任务的数量上限由OS_MAX_TASKS宏指定(默认为16个);

    2、所有任务轮流执行,每个任务执行相同的时间;

    3、PendSV中断用来完成任务的切换与任务信息保存的工作;

    4、SysTick中断规定次数后(由TASK_TIME_SLICE宏指定),触发PendSV中断,从而实现任务切换;

    5、在OSStart之前,会创建一个“Idle Task”任务,当没有任务需要执行时,该任务独占CPU。

    这里的代码创建的Task1与Task2都是与具体硬件相关的LED开关任务,注意对照着匹配自己的硬件,或使用USART任务来代替这些任务。

    总共5个文件,给出如下:

    1、main.c:

     1 #include "include.h"
     2 
     3 //#define LED1TURN() (GPIOA->ODR ^= 1<<8)
     4 //#define LED2TURN() (GPIOD->ODR ^= 1<<2)
     5 
     6 extern OS_TCB OSTCBTbl[OS_MAX_TASKS]; // (OS Task Control Block Table)
     7 extern OS_STK TASK_IDLE_STK[TASK_STACK_SIZE]; //("TaskIdle" Stack)
     8 extern OS_TCB *OSTCBCur; // Pointer to the current running task(OS Task Control Block Current)
     9 extern OS_TCB *OSTCBNext; // Pointer to the next running task(OS Task Control Block Next)
    10 extern INT8U OSTaskNext; // Index of the next task
    11 extern INT32U TaskTickLeft; // Refer to the time ticks left for the current task
    12 extern INT32U TimeMS;       // For system time record                             
    13 extern INT32U TaskTimeSlice; // For system time record
    14 
    15 OS_STK Task1Stk[TASK_STACK_SIZE];
    16 OS_STK Task2Stk[TASK_STACK_SIZE];
    17 OS_STK Task3Stk[TASK_STACK_SIZE];
    18 
    19 void Task1(void *p_arg);
    20 void Task2(void *p_arg);
    21 void Task3(void *p_arg);
    22 //void LedInit(void);
    23 
    24 int main(void)
    25 {
    26     
    27     
    28     OSInit();
    29     OSTaskCreate(Task1, (void*)0, (OS_STK*)&Task1Stk[TASK_STACK_SIZE-1]);
    30     OSTaskCreate(Task2, (void*)0, (OS_STK*)&Task2Stk[TASK_STACK_SIZE-1]);
    31     OSTaskCreate(Task3, (void*)0, (OS_STK*)&Task3Stk[TASK_STACK_SIZE-1]);
    32     SysTickInit(5);
    33     LedInit();
    34     USART1_Configuration(8, 9600);
    35 
    36     //while(1);
    37     OSStart();
    38     
    39     // while(1);
    40     //while(1){
    41     //    GPIOA->ODR &= ~(1<<8);
    42     //    GPIOD->ODR |= 1<<2;
    43     //}
    44 }
    45 
    46 /*void LedInit(void)
    47 {
    48     RCC->APB2ENR |= 1<<2;
    49     RCC->APB2ENR |= 1<<5;
    50     //GPIOE->CRH&=0X0000FFFF;  
    51     //GPIOE->CRH|=0X33330000;
    52     
    53     GPIOA->CRH &= 0xfffffff0;
    54     GPIOA->CRH |= 0x00000003;
    55     //GPIOA->ODR &= 0xfffffeff;
    56     GPIOA->ODR |= 1<<8;
    57 
    58     GPIOD->CRL &= 0xfffff0ff;
    59     GPIOD->CRL |= 0x00000300;
    60     //GPIOD->ODR &= 0xfffffffd;    
    61     GPIOD->ODR |= 1<<2;
    62     
    63     //LED1TURN();
    64     LED2TURN();
    65     
    66 }*/
    67 
    68 void Task1(void *p_arg)
    69 {
    70     while(1) {
    71         delayMs(100);
    72         LED1TURN();
    73     }
    74 }
    75 void Task2(void *p_arg)
    76 {
    77     while(1) {
    78         delayMs(200);
    79         LED2TURN();
    80     }
    81 }
    82 
    83 void Task3(void *p_arg)
    84 {
    85     while(1) {
    86             USART1->DR = 'B';
    87             while((USART1->SR & 0x40) == 0);
    88             USART1->DR = '
    ';
    89             while((USART1->SR & 0x40) == 0);
    90             USART1->DR = '
    ';
    91             while((USART1->SR & 0x40) == 0);
    92             delayMs(50);
    93     }
    94 }

    2、include.h:

     1 #ifndef INCLUDE_H
     2 #define INCLUDE_H
     3 
     4 #include <stdlib.h>
     5 
     6 #include "myos.h"
     7 
     8 #include "stm32f10x.h"
     9 
    10 #endif

    3、myos.h:

     1 #ifndef MYOS_H
     2 #define MYOS_H
     3 #include "stm32f10x.h"
     4 
     5 /**********CPU DEPENDENT************/
     6 #define TASK_TIME_SLICE     5         // 5ms for every task to run every time
     7 
     8 typedef unsigned char  INT8U;            // Unsigned  8 bit quantity  
     9 typedef unsigned short INT16U;            // Unsigned 16 bit quantity 
    10 typedef unsigned int   INT32U;            // Unsigned 32 bit quantity
    11 
    12 typedef unsigned int   OS_STK;            // Each stack entry is 32-bit wide(OS Stack)
    13 
    14 // assembling functions
    15 void OS_ENTER_CRITICAL(void);             // Enter Critical area, that is to disable interruptions
    16 void OS_EXIT_CRITICAL(void);            // Exit Critical area, that is to enable interruptions
    17 void OSCtxSw(void);                // Task Switching Function(OS Context Switch)
    18 void OSStart(void);
    19 
    20 OS_STK* OSTaskStkInit(void (*task)(void *p_arg), // task function
    21               void *p_arg, // (pointer of arguments)
    22                 OS_STK *p_tos); // (pointer to the top of stack)
    23 /**********CPU INDEPENDENT************/
    24 
    25 #define OS_MAX_TASKS    16
    26 
    27 #define TASK_STATE_CREATING     0
    28 #define TASK_STATE_RUNNING    1
    29 #define TASK_STATE_PAUSING    2
    30 
    31 #define TASK_STACK_SIZE     64
    32               
    33 #define LED1TURN() (GPIOA->ODR ^= 1<<8)
    34 #define LED2TURN() (GPIOD->ODR ^= 1<<2)
    35 
    36 
    37 typedef struct os_tcb {
    38     OS_STK    *OSTCBStkPtr;     // (OS Task Control Block Stack Pointer)
    39     INT8U     OSTCBStat;     // (OS Task Control Block Status)
    40 } OS_TCB; // (OS Task Control Block)
    41 
    42 void OSInit(void);     // (OS Initialization)
    43 void LedInit(void);
    44 void USART1_Configuration(u32 pclk2, u32 bound);
    45 void OS_TaskIdle(void *p_arg);
    46 void OSInitTaskIdle(void); // (OS Initialization of "TaskIdle")
    47 void OSTaskCreate(void (*task)(void *p_arg), // task function
    48           void *p_arg,     // (pointer of arguments)
    49           OS_STK *p_tos); // (pointer to the top of stack)
    50 void OSTCBSet(OS_TCB *p_tcb, OS_STK *p_tos, INT8U task_state);
    51 
    52 
    53 void SysTickInit(INT8U Nms); // (System Tick Initialization)
    54 void SysTick_Handler(void); // The interrupt function 
    55 
    56 INT32U GetTime(void);
    57 void delayMs(volatile INT32U ms); // The argument can't be too large
    58 
    59 #endif

    4、myos.c:

      1 #include "myos.h"
      2 #include "stm32f10x.h"
      3 
      4 
      5 OS_TCB OSTCBTbl[OS_MAX_TASKS]; // (OS Task Control Block Table)
      6 OS_STK TASK_IDLE_STK[TASK_STACK_SIZE]; //("TaskIdle" Stack)
      7 OS_TCB *OSTCBCur; // Pointer to the current running task(OS Task Control Block Current)
      8 OS_TCB *OSTCBNext; // Pointer to the next running task(OS Task Control Block Next)
      9 INT8U OSTaskNext; // Index of the next task
     10 INT32U TaskTickLeft; // Refer to the time ticks left for the current task
     11 INT32U TimeMS;
     12 INT32U TaskTimeSlice;
     13 char * Systick_priority = (char *)0xe000ed23;
     14 // Initialize the stack of a task, it is of much relationship with the specific CPU
     15 OS_STK* OSTaskStkInit(void (*task)(void *p_arg),
     16           void *p_arg,
     17           OS_STK *p_tos)
     18 {
     19     OS_STK *stk;
     20     stk = p_tos;
     21 
     22     *(stk)    = (INT32U)0x01000000L;             // xPSR                                               
     23     *(--stk)  = (INT32U)task;                    // Entry Point  
     24 
     25     // Don't be serious with the value below. They are of random
     26     *(--stk)  = (INT32U)0xFFFFFFFEL;             // R14 (LR) 
     27     *(--stk)  = (INT32U)0x12121212L;             // R12                                                
     28     *(--stk)  = (INT32U)0x03030303L;             // R3                                                 
     29     *(--stk)  = (INT32U)0x02020202L;             // R2                                                 
     30     *(--stk)  = (INT32U)0x01010101L;             // R1                                                 
     31 
     32     // pointer of the argument
     33     *(--stk)  = (INT32U)p_arg;                   // R0
     34 
     35     // Don't be serious with the value below. They are of random
     36     *(--stk)  = (INT32U)0x11111111L;             // R11 
     37     *(--stk)  = (INT32U)0x10101010L;             // R10 
     38     *(--stk)  = (INT32U)0x09090909L;             // R9  
     39     *(--stk)  = (INT32U)0x08080808L;             // R8  
     40     *(--stk)  = (INT32U)0x07070707L;             // R7  
     41     *(--stk)  = (INT32U)0x06060606L;             // R6  
     42     *(--stk)  = (INT32U)0x05050505L;             // R5  
     43     *(--stk)  = (INT32U)0x04040404L;             // R4  
     44     return stk;
     45 }
     46 
     47 // Only to initialize the Task Control Block Table
     48 void OSInit(void)
     49 {
     50     INT8U i;
     51     OS_ENTER_CRITICAL();
     52     for(i = 0; i < OS_MAX_TASKS; i++) {
     53         OSTCBTbl[i].OSTCBStkPtr = (OS_STK*)0;
     54         OSTCBTbl[i].OSTCBStat = TASK_STATE_CREATING;
     55     }
     56     OSInitTaskIdle();
     57     OSTCBCur = &OSTCBTbl[0];
     58     OSTCBNext = &OSTCBTbl[0];
     59     OS_EXIT_CRITICAL();
     60 }
     61 
     62 void OSInitTaskIdle(void)
     63 {
     64     OS_ENTER_CRITICAL();
     65     OSTCBTbl[0].OSTCBStkPtr = OSTaskStkInit(OS_TaskIdle, (void *)0, (OS_STK*)&TASK_IDLE_STK[TASK_STACK_SIZE - 1]);
     66     OSTCBTbl[0].OSTCBStat = TASK_STATE_RUNNING;
     67     OS_EXIT_CRITICAL();
     68 }
     69 
     70 void OSTaskCreate(void (*task)(void *p_arg), 
     71           void *p_arg, 
     72           OS_STK *p_tos)
     73 {
     74     OS_STK * tmp;
     75     INT8U i = 1;
     76     OS_ENTER_CRITICAL();
     77     while(OSTCBTbl[i].OSTCBStkPtr != (OS_STK*)0) {
     78         i++;
     79     }
     80     tmp = OSTaskStkInit(task, p_arg, p_tos);
     81     OSTCBSet(&OSTCBTbl[i], tmp, TASK_STATE_CREATING);
     82     OS_EXIT_CRITICAL();
     83 }
     84 
     85 void OSTCBSet(OS_TCB *p_tcb, OS_STK *p_tos, INT8U task_state)
     86 {
     87     p_tcb->OSTCBStkPtr = p_tos;
     88     p_tcb->OSTCBStat = task_state;
     89 }
     90 
     91 void OS_TaskIdle(void *p_arg)
     92 {
     93     p_arg = p_arg; // No use of p_arg, only for avoiding "warning" here.
     94     for(;;) {
     95         // OS_ENTER_CRITICAL();
     96         // Nothing to do
     97         // OS_EXIT_CRITICAL();
     98     }
     99 }
    100 
    101 // void SysTick_Handler(void)
    102 // {
    103 //     // OS_ENTER_CRITICAL();
    104 //     // OS_EXIT_CRITICAL();
    105 // }
    106 void SysTick_Handler(void)
    107 {
    108     OS_ENTER_CRITICAL();
    109     if((--TaskTimeSlice) == 0){
    110         TaskTimeSlice = TASK_TIME_SLICE;
    111         OSTCBCur = OSTCBNext;
    112         OSCtxSw();
    113         OSTaskNext++;
    114         while(OSTCBTbl[OSTaskNext].OSTCBStkPtr == (OS_STK*)0) { 
    115             OSTaskNext++;
    116             if(OSTaskNext >= OS_MAX_TASKS) {
    117                 OSTaskNext = 0;
    118             }
    119         }
    120         OSTCBNext = &OSTCBTbl[OSTaskNext];
    121         TaskTimeSlice = TASK_TIME_SLICE;
    122     }
    123     TimeMS++;
    124     OS_EXIT_CRITICAL();
    125 }
    126 
    127 void SysTickInit(INT8U Nms)
    128 {
    129     
    130     OS_ENTER_CRITICAL();
    131     
    132     TimeMS = 0;
    133     TaskTimeSlice = TASK_TIME_SLICE;                             
    134 
    135     SysTick->LOAD  = 1000 * Nms - 1; 
    136     *Systick_priority = 0x00;
    137     SysTick->VAL   = 0;  
    138     SysTick->CTRL = 0x3;
    139     OS_EXIT_CRITICAL();
    140 }
    141 
    142 INT32U GetTime(void)
    143 {
    144     return TimeMS;
    145 }
    146 
    147 void delayMs(volatile INT32U ms)
    148 {
    149     INT32U tmp;
    150     tmp = GetTime() + ms;
    151     while(1){
    152         if(tmp < GetTime()) break;
    153     }
    154 }
    155 
    156 void LedInit(void)
    157 {
    158     RCC->APB2ENR |= 1<<2;
    159     RCC->APB2ENR |= 1<<5;
    160     //GPIOE->CRH&=0X0000FFFF;  
    161     //GPIOE->CRH|=0X33330000;
    162     
    163     GPIOA->CRH &= 0xfffffff0;
    164     GPIOA->CRH |= 0x00000003;
    165     //GPIOA->ODR &= 0xfffffeff;
    166     GPIOA->ODR |= 1<<8;
    167 
    168     GPIOD->CRL &= 0xfffff0ff;
    169     GPIOD->CRL |= 0x00000300;
    170     //GPIOD->ODR &= 0xfffffffd;    
    171     GPIOD->ODR |= 1<<2;
    172     
    173     //LED1TURN();
    174     LED2TURN();
    175     
    176 }
    177 
    178 void USART1_Configuration(u32 pclk2, u32 bound)
    179 {
    180     float tmp;
    181     u16 mantissa;
    182     u16 fraction;
    183     tmp = (float)(pclk2 * 1000000)/(bound * 16);
    184     mantissa = tmp;
    185     fraction = (tmp - mantissa) * 16;
    186     mantissa <<= 4;
    187     mantissa += fraction;
    188     RCC->APB2ENR |= 1 << 2;
    189     RCC->APB2ENR |= 1 << 14;
    190     GPIOA->CRH &= 0xFFFFF00F;
    191     GPIOA->CRH |= 0x000008b0;
    192     RCC->APB2RSTR |= 1 << 14;
    193     RCC->APB2RSTR &= ~(1<<14);
    194     USART1->BRR = mantissa;
    195     USART1->CR1 |= 0x2008; // enable usart1, TE
    196     USART1->CR2 &= ~(0x3000); // stop 1 bit
    197 }

    5、os_cpu_a.asm:

      1     IMPORT     OSTCBCur
      2     IMPORT    OSTCBNext
      3     
      4     EXPORT    OS_ENTER_CRITICAL
      5     EXPORT     OS_EXIT_CRITICAL
      6     EXPORT    OSStart
      7     EXPORT    PendSV_Handler
      8     EXPORT     OSCtxSw
      9     
     10 NVIC_INT_CTRL    EQU            0xE000ED04    ; Address of NVIC Interruptions Control Register
     11 NVIC_PENDSVSET    EQU            0x10000000    ; Enable PendSV
     12 NVIC_SYSPRI14   EQU         0xE000ED22  ; System priority register (priority 14).
     13 NVIC_PENDSV_PRI EQU         0xFF        ; PendSV priority value (lowest).
     14     
     15     PRESERVE8 ; align 8
     16 
     17     AREA    |.text|, CODE, READONLY 
     18     THUMB 
     19 
     20 ;/******************OS_ENTER_CRITICAL************/
     21 OS_ENTER_CRITICAL
     22     CPSID    I    ; Enable interruptions(Change Processor States: Interrupts Disable)
     23     BX    LR    ; Return
     24 
     25 ;/******************OS_EXIT_CRITICAL************/
     26 OS_EXIT_CRITICAL
     27     CPSIE    I    ; Disable interruptions
     28     BX    LR     ; Return
     29 
     30 ;/******************OSStart************/
     31 OSStart
     32     ; disable interruptions
     33     CPSID    I                            ; OS_ENTER_CRITICAL();
     34     ; initialize PendSV
     35     ; Set the PendSV exception priority
     36     LDR     R0, =NVIC_SYSPRI14              ; R0 = NVIC_SYSPRI14;
     37     LDR     R1, =NVIC_PENDSV_PRI            ; R1 = NVIC_PENDSV_PRI;
     38     STRB    R1, [R0]                        ; *R0 = R1;
     39     
     40     ; initialize PSP as 0
     41     ; MOV    R4, #0
     42     LDR R4,  =0x0                        ; R4 = 0;
     43     MSR    PSP, R4                            ; PSP = R4;
     44     
     45     ; trigger PendSV
     46     LDR    R4, =NVIC_INT_CTRL                ; R4 = NVIC_INT_CTRL;
     47     LDR    R5, =NVIC_PENDSVSET                ; R5 = NVIC_PENDSVSET;
     48     STR    R5, [R4]                        ; *R4 = R5;
     49     
     50     ; enable interruptions
     51     CPSIE    I                            ; OS_EXIT_CRITICAL();
     52 
     53 ; should never get here
     54 ; a endless loop
     55 OSStartHang                                    
     56     B    OSStartHang
     57 
     58 ;/******************PendSV_Handler************/
     59 PendSV_Handler
     60     CPSID    I                            ; OS_ENTER_CRITICAL();
     61     ; judge if PSP is 0 which means the task is first invoked
     62     MRS     R0, PSP                        ; R0 = PSP;
     63     CBZ     R0, PendSV_Handler_NoSave    ; if(R0 == 0) goto PendSV_Handler_NoSave;
     64     
     65     ;     R12, R3, R2, R1
     66     SUB     R0, R0, #0x20                ; R0 = R0 - 0x20;
     67     
     68     ; store R4 
     69     STR     R4 , [R0]                ; *R0 = R4;
     70     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     71     ; store R5 
     72     STR     R5 , [R0]                ; *R0 = R5;
     73     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     74     ; store R6 
     75     STR     R6 , [R0]                ; *R0 = R6;
     76     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     77     ; store R7 
     78     STR     R7 , [R0]                ; *R0 = R7;
     79     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     80     ; store R8 
     81     STR     R8 , [R0]                ; *R0 = R8;
     82     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     83     ; store R9
     84     STR     R9, [R0]                ; *R0 = R4;
     85     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     86     ; store R10 
     87     STR     R10, [R0]                ; *R0 = R10;
     88     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     89     ; store R11 
     90     STR     R11, [R0]                ; *R0 = R11;
     91     ADD     R0, R0, #0x4            ; R0 = R0 + 0x4;
     92 
     93     SUB     R0, R0, #0x20             ; R0 = R0 - 0x20;
     94     
     95     ; easy method
     96     ;SUB     R0, R0, #0x20
     97     ;STM     R0, {R4-R11}
     98     
     99     LDR     R1, =OSTCBCur            ; R1 = OSTCBCur;
    100     LDR     R1, [R1]                 ; R1 = *R1;(R1 = OSTCBCur->OSTCBStkPtr)
    101     STR     R0, [R1]                 ; *R1 = R0;(*(OSTCBCur->OSTCBStkPrt) = R0)
    102 
    103 PendSV_Handler_NoSave
    104     LDR     R0, =OSTCBCur             ; R0 = OSTCBCur;
    105     LDR     R1, =OSTCBNext            ; R1 = OSTCBNext;
    106     LDR     R2, [R1]                 ; R2 = OSTCBNext->OSTCBStkPtr;
    107     STR     R2, [R0]                ; *R0 = R2;(OSTCBCur->OSTCBStkPtr = OSTCBNext->OSTCBStkPtr)
    108     
    109     LDR     R0, [R2]                 ; R0 = *R2;(R0 = OSTCBNext->OSTCBStkPtr)
    110     ; LDM     R0, {R4-R11}
    111     ; load R4 
    112     LDR     R4, [R0]                  ; R4 = *R0;(R4 = *(OSTCBNext->OSTCBStkPtr))
    113     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    114     ; load R5 
    115     LDR     R5, [R0]                ; R5 = *R0;(R5 = *(OSTCBNext->OSTCBStkPtr))
    116     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    117     ; load R6
    118     LDR     R6, [R0]                ; R6 = *R0;(R6 = *(OSTCBNext->OSTCBStkPtr))
    119     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    120     ; load R7 
    121     LDR     R7 , [R0]                ; R7 = *R0;(R7 = *(OSTCBNext->OSTCBStkPtr))
    122     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    123     ; load R8 
    124     LDR     R8 , [R0]                ; R8 = *R0;(R8 = *(OSTCBNext->OSTCBStkPtr))
    125     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    126     ; load R9 
    127     LDR     R9 , [R0]                ; R9 = *R0;(R9 = *(OSTCBNext->OSTCBStkPtr))
    128     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    129     ; load R10 
    130     LDR     R10 , [R0]                ; R10 = *R0;(R10 = *(OSTCBNext->OSTCBStkPtr))
    131     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    132     ; load R11 
    133     LDR     R11 , [R0]                ; R11 = *R0;(R11 = *(OSTCBNext->OSTCBStkPtr))
    134     ADD     R0, R0, #0x4             ; R0 = R0 + 0x4;(OSTCBNext->OSTCBStkPtr++)
    135     
    136     MSR     PSP, R0                 ; PSP = R0;(PSP = OSTCBNext->OSTCBStkPtr)
    137     ; P42
    138     ; P139 (key word: EXC_RETURN)
    139     ; use PSP
    140     ORR     LR, LR, #0x04         ; LR = LR | 0x04;
    141     CPSIE     I                     ; OS_EXIT_CRITICAL();
    142     BX    LR                         ; return;
    143 
    144 OSCtxSw ;OS context switch
    145     PUSH    {R4, R5}                
    146     LDR     R4, =NVIC_INT_CTRL             ; R4 = NVIC_INT_CTRL
    147     LDR     R5, =NVIC_PENDSVSET            ; R5 = NVIC_PENDSVSET
    148     STR     R5, [R4]                     ; *R4 = R5
    149     POP     {R4, R5}
    150     BX     LR                                 ; return;
    151     
    152     align 4
    153     end
  • 相关阅读:
    HDU 4548 美素数 在线打表加数状数组
    HDU 1023 Train Problem II
    HDU 4707 Pet 邻接表实现
    如何在VS2010环境下编译C++程序
    《Visual C++ 2010入门教程》系列五:合理组织项目、使用外部工具让工作更有效
    《Visual C++ 2010入门教程》系列一:关于Visual Studio、VC和C++的那些事
    C++格式化代码,去掉vs2010编辑器里中文注释的红色波浪线
    c++中%是什么意思?
    windows定位dll的搜索顺序
    VC6.0 error LNK2001: unresolved external symbol _main解决办法
  • 原文地址:https://www.cnblogs.com/ansersion/p/4396766.html
Copyright © 2011-2022 走看看