U-Boot porting and code analysis on 44B0X development board

Publisher:BlissfulCharmLatest update time:2016-08-14 Source: eefocusKeywords:U-Boot  44B0X  open  port Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
1. Introduction to u-boot
       u-boot is an open source bootloader, the current version is 1.1.2. u-boot is developed on the basis of ppcboot and armboot, it is quite mature and stable, and has been adopted in many embedded system development processes. Due to its development source code, it supports many development boards.
       Why do we need u-boot? Obviously, uClinux can be burned directly into flash, so there is no need for an additional bootloader. However, from the perspective of software upgrades and program patches, automatic software updates are very important. In fact, the use of bootloaders is not only that, but the need for automatic software updates alone shows that our development is necessary. At the same time, the process of u-boot porting is also a process of deepening the understanding of embedded systems, including hardware, software and operating systems.

2. Framework of u-boot porting
Porting u-boot to a new development board only requires modifying the hardware-related parts. In terms of code structure:
1) Create a gold44b directory under the board directory, and create gold44b.c, flash.c, memsetup.S, u-boot.lds, etc. You don't need to start from scratch, you can choose a similar directory, copy it directly, and modify the file name and content. When I was porting u-boot, I chose the Dave/B2 directory. Since u-boot already contains a development board directory based on s3c24b0, you can also copy the corresponding directory as a reference.
2) Create a s3c44b0x directory under the cpu directory, which mainly contains start.S, interrupts.c, cpu.c, and serial.c files. There is also no need to create files from scratch, just copy them from arm720t, and then modify the corresponding content.
3) Add gold44b.h to the include/configs directory, and put global macro definitions here.
4) Find the Makefile in the u-boot root directory and modify it to add
gold44b_config: unconfig
@./mkconfig $(@:_config=) arm s3c44b0 gold44b
5) Run make ev44bii_config. If there is no error, you can start the hardware-related code porting work

. 3. u-boot architecture
1) Overall structure
u-boot is a hierarchical structure. Software personnel doing porting work should provide serial port drivers (UART Driver), Ethernet drivers (Ethernet Driver), Flash drivers (Flash Driver), and USB drivers (USB Driver). At present, it is not very necessary to download programs through the USB port, and there is no USB interface on the development board, so the USB driver has not been ported for the time being. Above the driver layer is the u-boot application, and command provides a human-machine interface through the serial port. We can use some commands to do some common tasks, such as the memory viewing command md. The
Kermit application is mainly used to support the use of the serial port to download applications through the hyperterminal. TFTP is used to download applications through the network, such as the uClinux operating system.
2) Memory distribution
The flash size of gold44b is 2M (8 bits). Now 0-40000, a total of 256k, is used as the storage space for u-boot. Since there are some environment variables in u-boot, such as IP address, boot file name, etc., they can be configured through setenv in the command line and saved in the space of 40000-50000 (a total of 64k) through saveenv. If there are saved environment variables, u-boot will directly use these environment variables. As can be seen from the code analysis, we will move the flash boot code to DRAM for operation. The location of the u-boot code in DRAM is configured as follows in u-boot-1.1.2/board/gold44b/config.mk: TEXT_BASE = 0x0C700000. In this way, the boot code u-boot will be moved from 0x0000 0000 to 0x0C700000. Special attention should be paid to the fact that the interrupt vector program address of gold44b uClinux is at 0x0c000 0000, so the program cannot be downloaded to 0x0c000 0000, but usually downloaded to 0x0c008 0000.

4. start.S code structure
1) Define entry point An executable image must have an entry point and can only have one unique global entry point, which is usually placed at the 0x0 address of Rom (flash). For example , .globl _start _start
in start.S : It is worth noting that you must tell the compiler to know this entry point, and this work mainly involves modifying the connector script file (lds). The u-boot.lds on the development board is as follows: OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { . = 0x00000000; . = ALIGN(4); .text : { cpu/s3c44b0/start.o (.text) *( . text) } . = ALIGN( 4); .rodata: { * (.rodata) } . .; armboot_end_data = .; . = ALIGN(4); __bss_start = .; .bss : { *(.bss) } _end = .; }








































2) Set the exception vector.
The exception vector table is one of the key points for the connection between u-boot and uClinux kernel. Even if the uClinux kernel has obtained the control of the processor, once an interrupt occurs, the processor will automatically jump to a certain table entry (based on the interrupt type) in the first-level exception vector table starting from address 0x0 to read the instruction and run. The
exception vector table must be stored continuously starting from address 0. The following includes reset, undefined processing (undef), software interrupt (SWI), pre-instruction error (Pabort), data error (Dabort), reserved, and IRQ, FIQ, etc. Note that the value here must be consistent with the vector_base of uClinux. That is to say, if vector_base (include/armnommu/proc-armv/system.h) in uClinux is defined as 0x0c00 0000, then HandleUndef should be
0x0c00 0004.
.globl _start
_start: b reset
/*Modfied by zl 2005-2-21 */
/* add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000 000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000 
*/
ldr pc, =0x0c000004
ldr pc, =0x0c000008
ldr pc, =0x0c00000c
ldr pc, =0x0c000010
ldr pc, =0x0c000014
ldr pc, =0x0c000018
ldr pc, =0x0c00001c

.balignl 16,0xdeadbeefHere
, the first-level exception interrupt vector table at address 0x0 simply contains the jump instruction to the second-level exception interrupt vector table. In this way, the event that occurred can be correctly handed over to the uClinux interrupt handler for processing. This design is because interrupts are not used in this u-boot transplantation. Both 8019 and Timer are polling interrupts. If u-boot wants to use interrupts (such as using USB devices), it is necessary to establish a second-level exception interrupt vector table. 0x000000 add pc, pc, #0x0c000000 add pc, pc, #0x0c000000 add pc
, pc, #0x0c000000 add pc, pc, #0x0c000000 add pc, pc, #0x0c000000 add pc, pc, #0x0c000000 add pc, pc, #0x0c000000  .balignl 16,0xdeadbeef  .... At Reset is to copy the interrupt vector table /* now copy to sram the interrupt vector */ adr r0, real_vectors add r2, r0, #1024 ldr r1, =0x0c000000 add r1, r1, #0x08 vector_copy_loop: ldmia r0!, {r3-r10} stmia r1!, {r3-r10} cmp r0, r2 ble vector_copy_loop  .... Create a three-level interrupt jump /******************************************************/ /* interrupt vectors */ /*************************************************/ /* real_vectors: b reset b undefined_instruction b software_interrupt b prefetch_abort b data_abort b not_used b irq b fiq  */ /***********************************************/ undefined_instruction: mov r6, #3 b reset software_interrupt: mov r6, #4 b reset prefetch_abort: mov r6, #5 b reset data_abort: mov r6, #6 b reset not_used: /* we *should* never reach this */





























































mov r6, #7
b reset

irq:
mov r6, #8
b reset

fiq:
mov r6, #9
b reset

3) Initialize CPU related pll, clock, interrupt control registers
In order to turn off the watch dog timer, turn off the interrupt, set LockTime, PLL (phase lock loop), and clock.
These values ​​(except LOCKTIME) can be found in the manual of Samsung 44b0.
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*******************************************************************
*/

#define INTCON (0x01c00000+0x200000)
#define INTMSK (0x01c00000+0x20000c)
#define LOCKTIME (0x01c0000 0+0x18000c)
#define PLLCON (0x01c00000+0x180000)
#define CLKCON (0x01c00000+0x180004)
#define WTCON (0x01c00000+0x130000)
cpu_init_crit:
/* disable watch dog */
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]

/*
* mask all IRQs by clearing all bits in the INTMRs
*/
ldr r1,=INTMSK
ldr r0, =0x03ffffeff
str r0, [r1]

ldr r1, =INTCON
ldr r0, =0x05
str r0, [r1]

/* Set Clock Control Register */
ldr r1, =LOCKTIME
ldrb r0 , =800
strb r0, [r1]

ldr r1, =PLLCON

#if CONFIG_S3C44B0_CLOCK_SPEED==64
ldr r0, =0x38021 /* smdk4110: Xtal=8MHz Fclk=64MHz */
#elif CONFIG_S3C44B0_CLOCK_SPEED==66
ldr r0, =0x34031 /* 66MHz (Quartz=11MHz) */
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif

str r0, [r1]

ldr r1,=CLKCON
ldr r0, =0x7ff8
str r0, [r1]

mov pc, lr

4) Initialize SDRAM controller
The memory controller (mainly SDRAM controller) is mainly configured by setting 13 registers starting from 1c80000, including bus width, 8 memory banks, bank size, sclk, and two bank modes.
#ifdef CONFIG_INIT_CRITICAL
bl cpu_init_crit
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a memsetup.S in your board directory.
*/
bl memsetup
#endif
The code to initialize the memory controller is stored in u-boot-1.1.2/board/gold44b/memsetup.S
It is consistent with the boot code (memcfg.s and 44binit.s) under ADS or SDT, but the assembly format is slightly different.
5) Copy the program in rom to RAM
First, use the PC to obtain the starting address of the bootloader in flash, and then calculate
the size of the program code by the difference in the label. The compiler will generate the correct distribution value for these labels when linking.
After obtaining the correct information, copy the code to RAM through registers (r3 to r10) as the intermediate medium for copying.

relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don 't reloc during debug */
beq stack_setup

ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */

copy_loop :
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
6) Initialize stack
Enter each mode and set the corresponding mode stack.
/* Set up the stack */
stack_setup:
ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */

7) Go to RAM Using
the instruction ldr,pc, the C function address in RAM can be transferred to RAM for execution.
ldr pc, _start_armboot

5. System initialization
1) Serial port part (u-boot-1.1.2/cpu/s3c44b0/serial.c)
The serial port settings mainly include initializing the serial port. It is worth noting that the Baudrate of the serial port has a lot to do with the clock MCLK. The relationship is calculated by: rUBRDIV0=( (int)(MCLK/16./(gd ->baudrate) + 0.5) -1 ). This can be found in the manual. Since u-boot supports variable Baud rate, so use macro definition to set the default baud rate (64Mhz, 115200bps) and other baud rates. The code is as follows:
void serial_setbrg (void)
{
DECLARE_GLOBAL_DATA_PTR;

u32 divisor = 0;

/* get correct divisor */
switch(gd->baudrate) {

case 1200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 3124;
#elif CONFIG_S3C44B0_CLOCK_SPEED==7 5
divisor = 3905;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /default
divisor = 3332;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;

case 9600:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 390;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 487;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /default
divisor = 416;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;

case 19200:
#if CONFIG_S3C44B0_CLOCK _SPEED==66
divisor = 194;
#elif CONFIG_S3C44B0_CLOCK_SPEED== 75
divisor = 243;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /Default
divisor = 207;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif
break;

case 38400:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 97;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 121;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /Default
divisor = 103;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;

case 57600:
#if CONFIG_S3C 44B0_CLOCK_SPEED==66
divisor = 64;
# elif CONFIG_S3C44B0_CLOCK_SPEED==75
divisor = 80;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64 /default
divisor = 68;
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif break;

case 115200:
#if CONFIG_S3C44B0_CLOCK_SPEED==66
divisor = 32;
#elif CONFIG_S3C44B0_CLOCK_SPEED==64
divisor = 34;
#elif CONFIG_S3C44B0_CLOCK_SPEED==75 /default
divisor = 40;
#else
# error CONFIG_S 3C44B0_CLOCK_SPEED undefined
#endif break;
}

serial_flush_output();
serial_flush_input();
UFCON0 = 0x0;
ULCON0 = 0x03;
UCON0 = 0x05;
UBRDIV0 = divisor;

UFCON1 = 0x0;
ULCON1 = 0x03;
UCON1 = 0x05;
UBRDIV1 = divisor;

for(divisor=0; divisor<100; divisor++) {
/* NOP */
}
}
Other functions include sending and receiving. There is no interrupt at this time, and the loop waits to determine whether the action is completed.
For example, the receiving function :
static int serial_flush_input(void)
{
volatile u32 tmp;

/* keep on reading as long as the receiver is not empty */
while(UTRSTAT0&0x01) {
tmp = REGB(URXH0);
}

return 0;
}
2) Clock part (u -boot-1.1.2/cpu/s3c44b0/interrupt.c)
implements the delay function udelay.
Since get_timer here does not use interrupts, it uses global variables to accumulate.
void udelay (unsigned long usec)
{
ulong tmo;

tmo = usec / 1000;
tmo *= CFG_HZ;
tmo /= 8;

tmo += get_timer (0);

while (get_timer_masked () < tmo)
/*NOP*/;
}

3) Flash part (u-boot-1.1.2/board/gold44b.c)
As part of the memory, flash can be read without any problem. The key is the writing part of flash.
Flash must be erased first and then written.
flash_init The initialization part is completed. The main purpose here is to check whether the flash model is correct.

unsigned long flash_init (void)
{
#ifdef __DEBUG_START_FROM_SRAM__
return CFG_DUMMY_FLASH_SIZE;
#else
unsigned long size_b0;
int i;

/* Init: no FLASHes known */
for (i=0; i flash_info[i] .flash_id = FLASH_UNKNOWN;
}

/* Static FLASH Bank configuration here - FIXME XXX */

size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);

if (flash_info[0].flash_id == FLASH_UNKNOWN) {
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
size_b0, size_b0<<20);
}

/* Setup offsets */
flash_get_offsets (0, &flash_info[0]);

/* Monitor protection ON by default */
(void)flash_protect(FLAG_PROTECT_SET,
-CFG_MONITOR_LEN,
0xffffffff,
&flash_info[0]);

flash_info[0].size = size_b0;

return (size_b0);
#endif
}


flash_erase 擦除flash,BlankCheck 则检查该部分内容是否擦除成功。

int flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *addr2;
int flag, prot, sect, l_sect;
ulong start, now, last;
int i;

if ((s_first < 0) || (s_first > s_last)) {
if (info->flash_id == FLASH_UNKNOWN) {
printf ("- missing\n");
} else {
printf ("- no sectors to erase\n");
}
return 1;
}

if (info->flash_id == FLASH_UNKNOWN) {
printf ("Can't erase unknown flash type - aborted\n");
return 1;
}

prot = 0;
for (sect=s_first; sect<=s_last; ++sect) {
if (info->protect[sect]) {
prot++;
}
}

if (prot) {
printf ("- Warning: %d protected sectors will not be erased!\n",
prot);
} else {
printf ("\n");
}

l_sect = -1;

/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();

/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]);
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00500050; /* block erase */
for (i=0; i<50; i++)
udelay(1000); /* wait 1 ms */
} else {
if (sect == s_first) {
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080;
addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
}
addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */
}
l_sect = sect;
}
}

/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();

/* wait at least 80us - let's wait 1 ms */
udelay (1000);

/*
* We wait for the last triggered sector
*/
if (l_sect < 0)
goto DONE;

start = get_timer (0);
last = start;
addr = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]);
while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_FLASH_WORD_SIZE)0x00800080) {
if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
printf ("Timeout\n");
return 1;
}
/* show that we're waiting */
if ((now - last) > 50000000) { /* every second */
putc ('.');
last = now;
}
}

DONE:
/* reset to read mode */
addr = (CFG_FLASH_WORD_SIZE *)info->start[0];
addr[0] = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */

printf (" done\n");
return 0;
}


wirte_word 则想flash 里面写入unsigned long 类型的data,因为flash 一次只能写入16bits,所以这里分两次写入。
/*-----------------------------------------------------------------------
* Write a word to Flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
static int write_word (flash_info_t *info, ulong dest, ulong data)
{
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]);
volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest;
volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data;
ulong start;
int flag;
int i;

/* Check if Flash is (sufficiently) erased */
if ((*((volatile ulong *)dest) & data) != data) {
return (2);
}
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();

for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++)
{
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA;
addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00A000A0;

dest2[i] = data2[i];

/* re-enable interrupts if necessary */
if (flag)
enable_interrupts();

/* data polling for D7 */
start = get_timer (0);
while ((dest2[i] & (CFG_FLASH_WORD_SIZE)0x00800080) !=
(data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) {
if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
return (1);
}
}
}

return (0);
}
Keywords:U-Boot  44B0X  open  port Reference address:U-Boot porting and code analysis on 44B0X development board

Previous article:S3C2440 external interrupt key interrupt
Next article:Experience of porting uboot to S3C44B0X development board

Recommended ReadingLatest update time:2024-11-16 22:23

u-boot transplantation (6)---code modification---serial port
1. Code process 1.1 Serial port code   The program flow chart is as follows;      The code executed by default_serial_console is as follows:         There is the following definition in JZ2440.H:       Then execute the structure s3c24xx_serial0_device, thereby executing INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0"):   
[Microcontroller]
u-boot transplantation (6)---code modification---serial port
Chapter 7: Tiny4412 U-BOOT transplantation DDR memory configuration
Last time, we finished talking about the low-level initialization of Nand Flash. The operation of Nand Flash is mainly in board_init_f_nand(), which involves copying the code from Nand Flash to DDR. This will be analyzed in the actual transplantation process later in combination with the source code flow. Normally, DD
[Microcontroller]
Chapter 7: Tiny4412 U-BOOT transplantation DDR memory configuration
Embedded U-BOOT Gigabit Network Design Using S3C2440A
U-BOOT supports network functions. When downloading operating system kernels and large file systems, it is faster and more convenient than other boot loaders that do not support the network. At present, U-BOOT only supports 10M/100M network functions. With the development of science and technology, gigabit network
[Microcontroller]
Embedded U-BOOT Gigabit Network Design Using S3C2440A
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号