Abstract: The Raspberry Pi is an arm-based microcomputer motherboard developed by the British charity "Raspberry Pi Foundation". This article introduces the transplantation process of Raspberry Pi based on LiteOS.
This article is shared from the Huawei Cloud Community "2021 LiteOS Raspberry Pi Porting Guide (1)", author: Lionlace.
Raspberry Pi is an arm-based microcomputer motherboard developed by the British charity organization "Raspberry Pi Foundation". This article introduces the transplantation process of Raspberry Pi based on LiteOS.
hardware information
development board: Raspberry Pi 2 Model B (Raspberry Pi 2B)
CPU:Broadcom BCM2836
frequency: 900MHz
memory: 1GB
GPU:VideoCore IV GPU
Preparation for transplantation
Hardware environment
This experiment uses Raspberry Pi 2 Model B development board, USB to TTL module, SDcard and card reader.
Software Environment
- In this experiment, you need to build the Linux environment (make, arm-none-eabi compilation tool chain) according to the LiteOS tutorial on Code Cloud. Environment building tutorial: https://gitee.com/LiteOS/LiteOS/blob/master/doc/LiteOS_Build_and_IDE.md
- This experiment needs to download the official image creation tool (Raspberry Pi Imager), download address: https://www.raspberrypi.org/software/
Porting steps
Create directory structure
Add the Raspberry_Pi2B directory under the targets directory, and refer to the startup process of realview-pbx-a9, which is less different from the cortex-A7 architecture, for migration.
Copy reset_vector.S and main.c in the realview-pbx-a9 directory to the Raspberry_Pi2B directory and rename reset_vector.S to los_startup_gcc.S.
Merge the contents of board.ld and liteos.ld in the realview-pbx-a9 directory into the liteos.ld file in the Raspberry_Pi2B directory.
Copy the include and os_adapt folders in the realview-pbx-a9 directory to the Raspberry_Pi2B directory, and delete the unnecessary dma-related header files include/asm/dma.h.
Turn off SMP and MMU
Add code to close SMP and MMU in the los_startup_gcc.S file.
- Turn off the SMP function
mrc p15, 0, r0, c1, c0, 1
bic r0, r0, #0x40
mcr p15, 0, r0, c1, c0, 1
The above table is the function description information of ACTLR (Auxiliary Control Register) register bit6. For more register related information, please refer to Cortex-A7 MPCore Technical Reference Manual.
- Turn off the MMU function
mrc p15, #0, r0, c1, c0, #0
bic r0, r0, #1
mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit
The above table is the SCTLR (System Control Register) register bit0 function description information. For more register related information, please refer to the Cortex-A7MPCore Technical Reference Manual.
- delete calling SMP related functions
Delete enable_scu and secondary_cpu_start in los_startup_gcc.S.
Enable FPU/ENON
Configure FPU/NEON:
/* enable fpu+neon */
LDR r0, =(0xF << 20)
MCR p15, 0, r0, c1, c0, 2
MOV r3, #0x40000000
VMSR FPEXC, r3
The first two lines of code above are used to set the access authority of CP10 and CP11, and the latter two lines are used to set the EN bit of the register FPEXC to enable FPU.
Note: can support up to 16 coprocessors in the arm coprocessor design, usually named cp0~cp15.
The above table is the function description information of register CPACR bit20-23. For more register related information, please refer to Cortex-A7 MPCore Technical Reference Manual.
Modify the link script
When the Raspberry Pi starts, it first loads the start.elf file in the SD card. The program will read the content of the config.txt file in the SD card, which records some configuration information. If the startup address and startup file are not set, the kernel8.img file will be loaded by default, which is a program compiled by aarch64 and the startup address is 0x80000. If there is no kernel8.img image file in the SD card, the kernel7.img image file will be loaded, which is a program compiled by a 32-bit compiler and the startup address is 0x8000. The cpu of the Raspberry Pi 2B is a 32-bit architecture, so set the startup address in the liteos.ld file to 0x8000.
Stack initialization
In the Raspberry Pi 2B startup file los_startup_gcc.S, only the sp register of the SVC mode is set, and the cpuInit function is added to initialize the sp pointer of other modes. As follows:
VOID cpuInit(VOID)
{
__asm__ (
"msr cpsr_c, %1\n\t"
"mov sp, %0\n\t"
"msr cpsr_c, %3\n\t"
"mov sp, %2\n\t"
"msr cpsr_c, %5\n\t"
"mov sp, %4\n\t"
"msr cpsr_c, %7\n\t"
"mov sp, %6\n\t"
"msr cpsr_c, %8\n\t"
:
: "r" (__irq_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_IRQ_MODE),
"r" (__abt_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_ABT_MODE),
"r" (__undef_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_UNDEF_MODE),
"r" (__fiq_stack_top),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_FIQ_MODE),
"I" (PSR_F_BIT | PSR_I_BIT | CPSR_SVC_MODE)
: "r14");
}
Configure dynamic memory address
#define OS_SYS_MEM_ADDR ((void *)(&__bss_end))
#define LOS_HEAP_ADDR_END (void*)(0x0 + 4 * 1024 * 1024)
#define OS_SYS_MEM_SIZE (UINT32)(((UINT32)LOS_HEAP_ADDR_END - (UINT32)OS_SYS_MEM_ADDR + (64 - 1)) & ~(64 - 1))
The above code defines OS_SYS_MEM_ADDR as the start address of the dynamic memory, LOS_HEAP_ADDR_END as the end address of the dynamic memory, and OS_SYS_MEM_SIZE as the size of the dynamic memory.
Serial port implementation
The Raspberry Pi 2B schematic leads to the mini_uart serial ports TXD0 and RXD0, and the corresponding pins are GPIO14 and GPIO15, as shown in the following figure:
Create the usart.c and usart.h files, write the serial port initialization function UartInit in usart.c, and implement the uart_getc, uart_hwiCreate, and uart_write interfaces in the uart_debug.c file to realize the printf function to output from the serial port.
Adaptation interrupt
The interrupt of the Raspberry Pi 2B belongs to the bcm specific interrupt controller. Add the arm_control.c file in the drivers/interrupt directory, and implement the callback function in the HwiControllerOps structure in this file.
STATIC const HwiControllerOps g_armControlOps = {
.enableIrq = HalIrqUnmask,
.disableIrq = HalIrqMask,
.getCurIrqNum = HalCurIrqGet,
.getIrqVersion = HalIrqVersion,
.getHandleForm = HalIrqGetHandleForm,
.handleIrq = IrqEntryArmControl,
.clearIrq = HalIrqClear,
.triggerIrq = HalIrqPending,
};
The above table is the offset address of the interrupt register. For readers who want to know the detailed register information, please refer to the official chip manual.
Adapt to Zhongduan
Raspberry Pi 2B triggers the systick interrupt via Timer (arm side). For specific operation details, please refer to the file: drivers\timer\rasp_systick.c.
/* systime=250000000 */
timer->preDivider = (OS_SYS_CLOCK / OS_SYS_US_PER_SECOND - 1);
timer->reload = 0;
timer->load = 0;
timer->IRQClear = 0;
timer->control = 0;
timer->reload = LOSCFG_BASE_CORE_TICK_PER_SECOND;
timer->load = LOSCFG_BASE_CORE_TICK_PER_SECOND;
/* 23-bit counter, enable interrupt, enable timer */ timer->control = (1 << 1) | (1 << 5) | (1 << 7);
UINT32 ret = LOS_HwiEnable(ARM_TIMER_INI);
The above code configures the timer Timer to trigger a systick interrupt every 1ms.
The above is the offset address of the Timer register. For readers who want to know the detailed register information, please refer to the official chip manual.
Configuration compilation
Add the kconfig.raspberry file in the targets directory:
ConfigLOSCFG_PLATFORM
config LOSCFG_PLATFORM
string
default "Raspberry_Pi2B" if LOSCFG_PLATFORM_Raspberry_Pi2B
choice
prompt "Board"
depends on LOSCFG_FAMILY_RASPBERRY
default LOSCFG_PLATFORM_Raspberry_Pi2B
help
Raspberry_Pi2B
config LOSCFG_PLATFORM_Raspberry_Pi2B
bool "Raspberry_Pi2B"
select LOSCFG_ARCH_CORTEX_A7
select LOSCFG_USING_BOARD_LD
select LOSCFG_PLATFORM_ARM_CONTROL
select LOSCFG_Raspberry_Pi2B_SYSTICK
endchoice
Modify the Makefile
Modify the Makefile in the following path (for details, please refer to the corresponding file in the gitee warehouse): driver/timer/Makefiledriver/interrupt/Makefiletargets/Raspberry_Pi2B/Makefile
Add .img generation instruction
Add the command $(OBJCOPY) -O binary $(OUT)/$@.elf $(OUT)/kernel7.img to the Makefile in the root directory to convert the generated elf file into a kernel7.img file.
Make boot SDcard
- Use Raspberry Pi Imager tool to make Raspberry Pi system.
Raspberry Pi Imager download link: https://www.raspberrypi.org/software/
- Replace the kernel7.img file generated by the compilation with the kernel7.img file in the SDcard.
Insert the SDcard written into the image file into the Raspberry Pi 2B and power on, and the Raspberry Pi 2B can run the LiteOS system. The results of the operation are as follows:
********Hello Huawei LiteOS******** LiteOS Kernel Version : 5.1.0 build data : Jul 13 2021 16:40:42 ********************************** OsAppInit cpu 0 entering scheduler app init! Hello, welcome to liteos demo! Huawei LiteOS #
At this point, the LiteOS system has successfully started and run. The transplantation project has been launched in the Gitee LiteOS community, and the relevant code link address is: https://gitee.com/LiteOS/LiteOS/tree/master/targets/Raspberry_Pi2B
Reference link
[1] Raspberry Pihardware - Raspberry Pi Documentation:https://www.raspberrypi.org/documentation/hardware/raspberrypi/README.md
[2] Raspberry Pi official chip manual:
https://datasheets.raspberrypi.org/bcm2835/bcm2835-peripherals.pdf
[3] Cortex-A7 MPCore Technical Reference Manual:
https://developer.arm.com/documentation/ddi0464/f?lang=en
Click to follow and learn about Huawei Cloud's fresh technology for the first time~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。