Detailed explanation of ucosii transplantation on stm32 3

Publisher:雷电狂舞Latest update time:2016-06-14 Source: eefocusKeywords:ucosii Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
    Transplantation Detailed Explanation 1 and 2 mainly discuss the basic knowledge needed for transplantation. This article introduces the specific transplantation process.

    First, download the official ported version from the Micrium website (the compiler uses ARM/Keil, version V2.86, V2.85 has problems).
    Download address: http://micrium.com/page/downloads/ports/st/stm32
    After decompression, you will get the following folders and files:
    Micrium\
       AppNotes
       Licensing
       Software
       ReadMe.pdf

    AppNotes contains the ucosii porting description file. Of these two files, we only need to care about Micrium\AppNotes\AN1xxx-RTOS\AN1018-uCOS-II-Cortex-M3\AN-1018.pdf. Because this file describes the code that needs to be modified in the CM3 kernel porting process for ucosii.
   Licensing contains the ucosii license.
   There are several folders under Software. In this article's porting, we only need to care about uCOS-II.
       CPU: stm32 standard peripheral library
       EvalBoards: micrium official evaluation board related code
       uc-CPU: ucosii porting code based on micrium official evaluation board
       uC-LCD: micrium official evaluation board LCD driver code
       uc-LIB: micrium official library code
       uCOS-II: ucosii source code
       uC-Probe: and uC-Probe related code
   ReadMe.pdf will not be mentioned.

    OK, now that we have introduced the official stuff, it is time for us to create our own project and start the porting. I have already introduced how to create a project and use the stm32 standard peripheral library in my previous article "Detailed Explanation of Using the Stm32 Standard Peripheral Library". Here, please download the template code ( http://download.csdn.net/source/3448543 ). The porting in this article is based on this project.
    Create folders template\src\ucosii, template\src\ucosii\src, template\src\ucosii\port;
    copy the files under Micrium\Software\uCOS-II\Source to template\src\ucosii\src;
    copy the files under Micrium\Software\uCOS-II\Ports\ARM-Cortex-M3\Generic\RealView to

template\src\ucosii\port;
   The code under ucosii\src is the part of ucosii that does not need to be modified, and the code under ucosii\port needs to be modified during porting. To prevent the porting failure caused by the accidental modification of the source code, the code files under ucosii\src can be set to read-only.
   Here, based on the basic knowledge of porting introduced in AN-1018.pdf and Porting Detailed Explanation 1 and 2, the code under ucosii\port is explained.

os_cpu.h

#ifdef OS_CPU_GLOBALS
#define OS_CPU_EXT
#else
#define OS_CPU_EXT extern
#endif

typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned short INT16U;
typedef signed short INT16S;
typedef unsigned int INT32U;
typedef signed int INT32S;
typedef float FP32;
typedef double FP64;
There is no explanation.

typedef unsigned int OS_STK; 
typedef unsigned int OS_CPU_SR;

   Because CM3 is 32-bit wide, OS_STK (the data type of the stack) is redefined as unsigned int.
   Because the status register (xPSR) of CM3 is 32-bit wide, OS_CPU_SR is redefined as unsigned int. OS_CPU_SR is used to save the CPU status register in OS_CRITICAL_METHOD method 3. In CM3, porting OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() is the most appropriate method 3.

#define OS_CRITICAL_METHOD 3

#if OS_CRITICAL_METHOD == 3
#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();}
#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);}
#endif

   Specifically define the macros OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL(), where OS_CPU_SR_Save() and OS_CPU_SR_Restore() are written in assembly code. The code is in os_cpu_a.asm and will be explained later.

#define OS_STK_GROWTH 1
   In CM3, the stack grows from high address to low address, so OS_STK_GROWTH is defined as 1.

#define OS_TASK_SW() OSCtxSw()
   defines the task switching macro. OSCtxSw() is written in assembly code. The code is in os_cpu_a.asm and will be explained later.

#if OS_CRITICAL_METHOD == 3                        
OS_CPU_SR OS_CPU_SR_Save(void);
void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
#endif

void OSCtxSw(void);
void OSIntCtxSw(void);
void OSStartHighRdy(void);
void OS_CPU_PendSVHandler(void);
 
void OS_CPU_SysTickHandler(void);
void OS_CPU_SysTickInit(void);
INT32U OS_CPU_SysTickClkFreq(void);

    Declare several functions. Note that the last three functions need to be commented out. Why?
    OS_CPU_SysTickHandler() is defined in os_cpu_c.c. It is the interrupt handling function of SysTick interrupt. However, stm32f10x_it.c already has the definition of SysTick_Handler() for this interrupt function. It is not needed here. Isn't it strange why the official porting version does this? I will explain it later.
    OS_CPU_SysTickInit() is defined in os_cpu_c.c. It is used to initialize the SysTick timer. It depends on OS_CPU_SysTickClkFreq(). We will implement this function ourselves, so comment it out.
    OS_CPU_SysTickClkFreq() is defined in BSP.C (Micrium\Software\EvalBoards). BSP.C is not used in this porting. We will implement it ourselves later, so it can be commented out.

os_cpu_c.c
    ucosii porting requires us to write 10 fairly simple C functions.

    OSInitHookBegin()
    OSInitHookEnd()
    OSTaskCreateHook()
    OSTaskDelHook()
    OSTaskIdleHook()
    OSTaskStatHook()
    OSTaskStkInit()
    OSTaskSwHook()
    OSTCBInitHook()
    OSTimeTickHook()

    Except for OSTaskStkInit(), these functions are all hook functions. If these hook functions are not enabled, they will not be used. They are also relatively simple and should be understood by looking at them, so I will not introduce them. Let's
    talk about OSTaskStkInit(). Before talking about it, we still have to talk about task switching, because initializing the task stack is for task switching. When the code is running normally, it is executed line by line. How can it run to another task (i.e. function) for execution? First of all, you can recall the interrupt process. When an interrupt occurs, the original function execution location (program counter PC, processor status register and all general registers, i.e. the current code scene) is saved in the stack, and then the interrupt vector is fetched and it runs to the interrupt function for execution. After the execution is completed, if you want to return to the original function execution location, what should you do? Just restore the original function execution information saved in the stack (reassign the code scene saved in the stack to each register of the CPU), and everything will go back, as if nothing happened. Everyone should be familiar with this process. What does task switching have to do with this? Imagine that if there are three functions foo1(), foo2(), and foo3(), they are saved to the stack as if they were just interrupted, and when the interrupt returns, they do something (the role of the scheduler) to return to whichever one they want. Isn't this a function (task) switch? You should understand the role of OSTaskStkInit() by now. It is called by the task creation function, so at the beginning, it is necessary to make the illusion that the task has just been interrupted in the stack. (The principle of task switching is introduced in Section 3.06 of Mr. Shao's book).
    So what is the situation in the stack after the interrupt? It is introduced in 9.1.1 of <> that xPSR, PC, LR, R12, R3-R0 are automatically saved to the stack, and R11-R4 can only be saved manually if they need to be saved. Therefore, the job of OSTaskStkInit() is to save all the registers of the CPU in the task's own stack. Among these values, R1-R12 have no meaning. The corresponding digital codes (such as R1 uses 0x01010101) are used here mainly to facilitate debugging.
    Others:
    xPSR = 0x01000000L, xPSR T bit (bit 24) is set to 1, otherwise a fault will occur when the task is executed for the first time.
    PC must point to the task entry,
    R14 = 0xFFFFFFFEL, the lowest 4 bits are E, which is an illegal value. The main purpose is to prevent the use of R14, that is, the task cannot return.
    R0 is used to pass the parameters of the task function, so it is equal to p_arg.   
OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
{
    OS_STK *stk;


    (void)opt; /* 'opt' is not used, prevent warning */
    stk = ptos; /* Load stack pointer */

    /* Registers stacked as if auto-saved on exception */
    *(stk) = (INT32U)0x01000000L; /* xPSR */
    *(--stk) = (INT32U)task; /* Entry Point */
    /* R14 ( LR) (init value will cause fault if ever used)*/
    *(--stk) = (INT32U)0xFFFFFFFEL;  
    *(--stk) = (INT32U)0x12121212L; /* R12 */
    *(--stk) = (INT32U)0x03030303L; /* R3 */
    *(--stk) = (INT32U)0x02020202L; /* R2 */
    *(--stk) = (INT32U)0x01010101L; /* R1 */
    *(--stk) = (INT32U)p_arg; /* R0 : argument */

    /* Remaining registers saved on process stack */
    *(--stk) = (INT32U)0x11111111L; /* R11 */
    *(--stk) = (INT32U)0x10101010L; /* R10 */
    *(--stk) = (INT32U)0x09090909L; /* R9 */
    *(--stk) = (INT32U)0x08080808L; /* R8 */
    *(--stk) = (INT32U)0x07070707L; /* R7 */
    *(--stk ) = (INT32U)0x06060606L; /* R6 */
    *(--stk) = (INT32U)0x05050505L; /* R5 */
    *(--stk) = (INT32U)0x04040404L; /* R4 */

    return (stk);
}

Comment out OS_CPU_SysTickHandler() and OS_CPU_SysTickInit().

#define OS_CPU_CM3_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010)) 
#define OS_CPU_CM3_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014)) 
#define OS_CPU_CM3_NVIC_ST_CURRENT (*((volatile INT32U *)0 xE000E018)) 
#define OS_CPU_CM3_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01C))

#define OS_CPU_CM3_NVIC_ST_CTRL_COUNT 0x00010000   
#define OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC 0x00000004   
#define OS_CPU_CM3_NVIC_ST_CTRL_INTEN 0x00000002   
#define OS_CPU_CM3_NVIC_ST_CTRL_ENABLE 0x0 0000001 

Comment out the above macro definitions as well, because they are all used for OS_CPU_SysTickHandler(), OS_CPU_SysTickInit().

The file os_cpu_a.asm
contains the code that must be written in assembly.

    EXTERN OSRunning; External references
    EXTERN OSPrioCur
    EXTERN OSPrioHighRdy
    EXTERN OSTCBCur
    EXTERN OSTCBHighRdy
    EXTERN OSIntNesting
    EXTERN OSIntExit
    EXTERN OSTaskSwHook
    declares that these variables are defined in other files and are only referenced in this file (some of them do not seem to be referenced, but it does not matter).

    EXPORT OS_CPU_SR_Save ; Functions declared in this file
    EXPORT OS_CPU_SR_Restore
    EXPORT OSStartHighRdy
    EXPORT OSCtxSw
    EXPORT OSIntCtxSw
    EXPORT OS_CPU_PendSVHandler
    Declare that these functions are defined in this file.

NVIC_INT_CTRL EQU 0xE000ED04 ;Address of interrupt control and status register ICSR
NVIC_SYSPRI14 EQU 0xE000ED22 ;Address of PendSV priority register
NVIC_PENDSV_PRI EQU 0xFF ;The priority of PendSV interrupt is 255 (lowest)
NVIC_PENDSVSET EQU 0x10000000 ;Bit 28 is 1
    to define several constants, similar to the #define preprocessing instruction in C language.

OS_CPU_SR_Save
    MRS R0, PRIMASK ; Read PRIMASK to R0, R0 is the return value
    CPSID I ; PRIMASK=1, disable interrupts (NMI and hard fault can be responded to)
    BX LR ; Return

OS_CPU_SR_Restore
    MSR PRIMASK, R0 ; Read R0 into PRIMASK, R0 is parameter
    BX LR ; Return

OSStartHighRdy() is called by OSStart() to start the highest priority task. Of course, the task must have been created before OSStart().

OSStartHighRdy
    ;Set the priority of PendSV interrupt #1
    LDR R0, =NVIC_SYSPRI14 ;R0 = NVIC_SYSPRI14
    LDR R1, =NVIC_PENDSV_PRI ;R1 = NVIC_PENDSV_PRI
    STRB R1, [R0] ;*(uint8_t *)NVIC_SYSPRI14 = NVIC_PENDSV_PRI

    ;Set PSP to 0 #2
    MOVS R0, #0 ;R0 = 0
    MSR PSP, R0 ;PSP = R0

    ;Set OSRunning to TRUE
    LDR R0, =OSRunning ;R0 = OSRunning
    MOVS R1, #1 ;R1 = 1
    STRB R1, [R0] ;OSRunning = 1
 
    ;Trigger PendSV interrupt #3
    LDR R0, =NVIC_INT_CTRL ;R0 = NVIC_INT_CTRL
    LDR R1, =NVIC_PENDSVSET ;R1 = NVIC_PENDSVSET
    STR R1, [R0] ;*(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET

    CPSIE I ; Enable interrupt                 

OSStartHang; infinite loop, should not come here
    B OSStartHang

#1. The priority of the PendSV interrupt should be the lowest priority. The reason is explained in Section 7.6 of <>.
#2. PSP is set to 0 to tell the specific task switch program (OS_CPU_PendSVHandler()) that this is the first task switch. After the switch, PSP will not be 0, as you will see later.
#3. Writing 1 to the 28th bit of the interrupt control and status register ICSR (0xE000ED04) can generate a PendSV interrupt. This is explained in <> 8.4.5 Configuration registers for other exceptions.

    When a task gives up the right to use the CPU, it will call the OS_TASK_SW() macro, which is OSCtxSw(). OSCtxSw() should do task switching. However, in CM3, all task switching is done in the PendSV interrupt handler, so OSCtxSw() only needs to trigger the PendSV interrupt. OS_TASK_SW() is called by OS_Sched().

void OS_Sched (void)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr = 0;
#endif


    OS_ENTER_CRITICAL();
    if (OSIntNesting == 0) {
        if (OSLockNesting == 0) {
            OS_SchedNew();
            if (OSPrioHighRdy != OSPrioCur) {
                OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
                OSTCBHighRdy->OSTCBCtxSwCtr++;
#endif
                OSCtxSwCtr++; 
                OS_TASK_SW(); /* Trigger PendSV interrupt*/
            }
        }
    }
    /* Once the interrupt is turned on, the PendSV interrupt function will be executed (of course, after the higher priority interrupt is processed) */
    OS_EXIT_CRITICAL();  
}

OSCtxSw
    ;Trigger PendSV interrupt
    LDR R0, =NVIC_INT_CTRL ;R0 = NVIC_INT_CTRL 
    LDR R1, =NVIC_PENDSVSET ;R1 = NVIC_PENDSVSET
    STR R1, [R0] ;*(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET
    BX LR ;Return

    When an interrupt handler exits, OSIntExit() is called to determine if there is a higher priority task to be executed. If there is, OSIntExit() calls OSIntCtxSw() to switch tasks.

OSIntCtxSw
    ; trigger PendSV interrupt
    LDR R0, =NVIC_INT_CTRL
    LDR R1, =NVIC_PENDSVSET
    STR R1, [R0]
    BX LR

    Seeing this, some students may wonder why OSCtxSw() and OSIntCtxSw() are exactly the same. In fact, the meanings of these two functions are different. OSCtxSw() switches between tasks, such as switching from task A to task B because it is waiting for a resource or doing a delay, while OSIntCtxSw() switches from the interrupt state to another task when the interrupt exits. When switching from an interrupt to a task, the work of pushing the CPU registers into the stack has been completed, so there is no need to do it a second time (refer to Section 3.10 of Mr. Shao's book). It's just that due to the special mechanism of CM3, in these two functions, only the PendSV interrupt needs to be triggered, and the specific switching is handled by the PendSV interrupt.

    As mentioned before, the real task switching is done in the PendSV interrupt processing function. Since half of the registers of CM3 will be automatically saved to the task stack when an interrupt occurs, it is only necessary to save R4-R11 and adjust the stack pointer in the PendSV interrupt processing function.

The pseudo code of the PendSV interrupt handling function is as follows:
OS_CPU_PendSVHandler()
{
        if (PSP != NULL) {
                Save R4-R11 onto task stack;
                OSTCBCur->OSTCBStkPtr = SP;
        }
        OSTaskSwHook();
        OSPrioCur = OSPrioHighRdy;
        OSTCBCur = OSTCBHighRdy;
        PSP = OSTCBHighRdy->OSTCBStkPtr;
        Restore R4-R11 from new task stack;
        Return from exception; 
}

OS_CPU_PendSVHandler ;xPSR, PC, LR, R12, R0-R3 have automatically saved
    CPSID I ;Interrupts need to be disabled during task switching
    
    MRS R0, PSP ;R0 = PSP
    ;If PSP == 0, jump to OS_CPU_PendSVHandler_nosave to execute #1
    CBZ R0, OS_CPU_PendSVHandler_nosave

    ;Save R4-R11 to the task stack
    SUBS R0, R0, #0x20 ;R0 -= 0x20                         
    STM R0, {R4-R11} ;Save R4-R11 to the task stack

    ;OSTCBCur->OSTCBStkPtr = SP;
    LDR R1, =OSTCBCur ;R1 = &OSTCBCur
    LDR R1, [R1] ;R1 = *R1 (R1 = OSTCBCur)
    STR R0, [R1] ;*R1 = R0 (*OSTCBCur = SP) #2                      

OS_CPU_PendSVHandler_nosave
    ;Call OSTaskSwHook()
    PUSH {R14} ;Save R14, because the function will be called later            
    LDR R0, =OSTaskSwHook ;R0 = &OSTaskSwHook 
    BLX R0 ;Call OSTaskSwHook()
    POP {R14} ;Restore R14

    ;OSPrioCur = OSPrioHighRdy;
    LDR R0, =OSPrioCur ;R0 = &OSPrioCur
    LDR R1, =OSPrioHighRdy ;R1 = &OSPrioHighRdy
    LDRB R2, [R1] ;R2 = *R1 (R2 = OSPrioHighRdy)
    STRB R2, [R0] ;*R0 = R2 (OSPrioCur = OSPrioHighRdy)

    ;OSTCBCur = OSTCBHighRdy;
    LDR R0, =OSTCBCur ;R0 = &OSTCBCur      
    LDR R1, =OSTCBHighRdy ;R1 = &OSTCBHighRdy
    LDR R2, [R1] ;R2 = *R1 (R2 = OSTCBHighRdy)
    STR R2, [R0] ;*R0 = R2 (OSTCBCur = OSTCBHighRdy)

    LDR R0, [R2] ;R0 = *R2 (R0 = OSTCBHighRdy), now R0 is the SP of the new task
                                 ;SP = OSTCBHighRdy->OSTCBStkPtr #3   
    LDM R0, {R4-R11} ;Restore R4-R11 from task stack SP       
    ADDS R0, R0, #0x20 ;R0 += 0x20
    MSR PSP, R0 ;PSP = R0, load PSP with the SP of the new task 
    ORR LR, LR, #0x04 ;Make sure LR bit 2 is 1, use process stack #4 after returning      
    CPSIE I ;Open interrupt
    BX LR ;Interrupt return                

    END

#1 If PSP == 0, it means that the task switch is done for the first time after OSStartHighRdy() is started, and R4-R11 has been saved in the stack when the task is just created, so there is no need to save it again.
#2 OSTCBStkPtr is the first variable of the task control block structure, so *OSTCBCur = SP (not very scientific) means OSTCBCur->OSTCBStkPtr = SP;
#3 Similar to #2.
#4 Because MSP is used in the interrupt handling function, PSP must be used after returning to the task, so LR bit 2 must be 1.

os_dbg.c
is used for system debugging and can be ignored.

    The code that needs to be modified is introduced here. If you still don’t understand something, take a look at AN-1018.pdf, Mr. Shao’s book and <>.

Keywords:ucosii Reference address:Detailed explanation of ucosii transplantation on stm32 3

Previous article:Detailed explanation of ucosii transplantation on stm32 2
Next article:Detailed explanation of ucosii transplantation on stm32 5

Recommended ReadingLatest update time:2024-11-16 14:44

STM32—— AHB, APB detailed explanation
STM32—— AHB, APB detailed explanation 2016-07-14 20:35 590 people read  Comments (0)  Collection   Report This article has been included in: Copyright Statement: This article is an original article by the blogger and may not be reproduced without the blogger's permission. First , let me say something unreliable. APB a
[Microcontroller]
STM32—— AHB, APB detailed explanation
How to release pa15, pb3, pb4 as gpio ports in stm32
    When the STM32 pins are not enough, the JTAG/SWD pins can be allocated to be used as GPIO ports.     Looking at the pin definitions in the data sheet, we can see that the main function of the PA15 pin after reset is JTDI, PB3 is JTDO, and PB4 is JNTRST. If these pins are used as normal pins, they need to be rema
[Microcontroller]
How to release pa15, pb3, pb4 as gpio ports in stm32
The story of STM32 Atomic Brother
Mentioning Guangzhou Xingyi Electronics, people in the STM32 circle may feel unfamiliar, but when it comes to Zhengdian Atom and "Atom Teaches You to Play STM32", almost all enthusiasts who have come into contact with STM32 or Arm MCU know it. Recently, Atom, the technical director of Guangzhou Xingyi Electronics, as
[Microcontroller]
The story of STM32 Atomic Brother
Use of STM32 counter
Because stm32f103c8 is used as the main controller to control the car, the speed of the car is input by two photoelectric encoders (one on the left and one on the right). Therefore, the external clock trigger mode (TIM-ETRClockMode2Config) is considered.     After trying for a long time, I found that TIM1 could not co
[Microcontroller]
STM32 processor RTC analysis
Preface:  1. This blog is based on the STM32F103ZET6 and the standard 3.5.0 library of the ARM Cortex-M3 core;  2. If there are any deficiencies, please give me more advice. What is RTC?  1. Structurally, it is an independent timer.  2. Functionally, it provides the system with calendar time that will not be reset whe
[Microcontroller]
STM32 processor RTC analysis
stm32 PWM output
Here are some problems that occurred when making a quadrotor. PWM timer initialization First, the code: (the code does not include port initialization) void Tim2_init(void) {     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;     TIM_OCInitTypeDef TIM_OCInitStructure;     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,
[Microcontroller]
stm32 software reset
According to the CM3 Authoritative Guide, there are two methods for software reset: 1. By setting the VECTRESET bit in the Application Interrupt and Reset Control Register (AIRCR) in the NVIC: LDR R0, =0xE000ED0C; NVIC AIRCR address LDR R1, =0x05FA0001 ; Set VECTRESET bit, the previous 0x05FA is the access key STR R1,
[Microcontroller]
C source code for TMP101 temperature sensor based on STM32 I2C
       It took me almost a weekend to do this process. A small TMP101 really made me rack my brains. In the end, I even used an oscilloscope to directly observe the waveforms of SDA SCL. However, the use of the oscilloscope did correct a serious and low-level mistake of mine. During this period, I also searched for STM
[Microcontroller]
C source code for TMP101 temperature sensor based on STM32 I2C
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号