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

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

image.png

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

image.png
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.
image.png

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:
image.png

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,
};

image.png

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.
image.png

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.
    image.png

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~


华为云开发者联盟
1.4k 声望1.8k 粉丝

生于云,长于云,让开发者成为决定性力量