LiteOS Raspberry Pi Porting Guide (Part 2)

LiteOS Raspberry Pi Porting Guide (Part 2)

This document describes the porting process of the LiteOS open-source version for the Raspberry Pi 3 Model B development board, for reference and learning exchange among developers and testers.

Porting Introduction

For embedded devices, due to the large differences in chip models and peripherals, and limited resources, IoT operating systems cannot adapt and integrate all drivers like Windows/Linux. Therefore, typically, only part of the chips/development boards are adapted first. To run the operating system on other chips/development boards, porting is necessary.

Hardware Information

Development Board:Raspberry Pi 3 Model B
CPU:Broadcom BCM2837
Clock Frequency:1.2GHz
Memory:1GB
GPU: VideoCore IV GPU

Porting Preparation

Since armv8-A AArch32 is fully backward compatible with armv7, the adaptation for Raspberry Pi 3B can refer to the “LiteOS Raspberry Pi Porting Guide” for Raspberry Pi 2B.
Hardware Environment

This porting used the Raspberry Pi 3 Model B development board, USB to TTL module, SD card and card reader.

Software Environment

This porting requires setting up the Linux development environment (make, arm-none-eabi toolchain) according to the LiteOS tutorial on Gitee. The environment setup tutorial can be found at: https://gitee.com/LiteOS/LiteOS/blob/master/doc/LiteOS_Build_and_IDE.md.

This porting requires downloading the official Raspberry Pi imaging tool (Raspberry Pi Imager),

Download link: https://www.raspberrypi.org/software/.

Porting Steps

The main steps to port LiteOS on the Raspberry Pi 3B development board are as follows:
Create Directory Structure
Copy the Raspberry Pi 2B directory under the targets directory and rename it to Raspberry32_Pi3B. Copy the targets\qemu-virt-a53\include\asm\dma.h file to the Raspberry32_Pi3B\include\asm directory:
The new directory structure for the development board is as follows:
Directory/File Description
Inc Header files for chip peripheral configuration
include System-related configuration header files
os_adapt Adaptation interface files
Src Source files for chip peripheral configuration
liteos.ld Link file for the current development board project
Makefile Makefile for the current development board project
los_startup_gcc.S Chip startup file
Table 1 Directory Structure
Set Exception Vector Table

In los_startup_gcc.S, set the 13th bit of the System Control Register to 0, indicating that the base address of the exception vector table starts from 0. The code is as follows:

    /* set vector base 0x00000000 */    mrc p15, 0, r0, c1, c0, 0            bic r0, #(1 << 13)    mcr p15, 0, r0, c1, c0, 0
The 13th bit of the System Control Register is as follows:
[13] V

V Vectors bit. This bit selects the base address of the exception vectors:

0Normal exception vectors, base address 0x00000000. Software can remap this base address using the VBAR.

1High exception vectors, base address 0xFFFF0000. This base address is never remapped. The primary input VINITHI defines the reset value of the V bit.

Add MMU Functionality
MMU (Memory Management Unit): Mainly used for the translation of virtual addresses to physical addresses and access control. For more MMU functionalities, please refer to the links at the end of this document.
  • Set L1 Page Table Entries

Add the following code to main.c to set L1 page table entries (this MMU only involves L1 page table), mapping 4G virtual memory linearly to physical addresses.

VOID MmuSectionInit(VOID){    UINT32 ttbBase = (UINTPTR)g_firstPageTable;     /* First clear all TT entries - ie Set them to Faulting */    (VOID)memset_s((VOID *)(UINTPTR)ttbBase, MMU_16K, 0, MMU_16K);    /* Set all mem 4G as uncacheable & rw first */    X_MMU_SECTION(0, 0, (MMU_4G >> SHIFT_1M),                  UNCACHEABLE, UNBUFFERABLE, ACCESS_RW, NON_EXECUTABLE, D_CLIENT);    X_MMU_SECTION(0, 0, ((AUX_BASE - 1) >> SHIFT_1M),                  CACHEABLE, BUFFERABLE, ACCESS_RW, EXECUTABLE, D_CLIENT);}

(Swipe left to see more)

  • Add the following code in los_startup_gcc.S to enable MMU

    1. Invalidate all TLB entries

    mcr     p15, #0, r0, c8, c7, #0
NoteTLB (Translation Lookaside Buffer) is equivalent to the cache of the page table.

2. Set access permissions for DOMAIN0 and DOMAIN01

    mov r0, #(DOMAIN0 | (DOMAIN1 << 2))    mcr p15, 0, r0, c3, c0

Note:Register C3 in CP15 defines the access permissions for the 16 domains of the ARM processor. (For details, please refer to the relevant documents at the end)

3. Set MMU L1 page table base address

    ldr r0, =g_firstPageTable    mcr     p15, #0, r0, c2, c0, #0

4. Enable MMU and cache

    /* enable mmu */    mrc     p15, #0, r0, c1, c0, #0    orr     r0, r0, #1    mcr     p15, #0, r0, c1, c0, #0     /* enable icache */    mrc     p15, #0, r0, c1, c0, #0    orr     r0,  r0, #(1 << ICACHE_BIT)    mcr     p15, #0, r0, c1, c0, #0    mrc     p15, #0, r0, c1, c0, #0    orr     r0,  r0, #(1 << DCACHE_BIT)    mcr     p15, #0, r0, c1, c0, #0
(Swipe left to see more)
Note:For more coprocessor references, please see the link: https://developer.arm.com/documentation/ddi0464/f?lang=en.
Add SMP Functionality
  • Add the following code in los_startup_gcc.S:

1. Add code to get CPU ID
    mrc     p15, 0, r11, c0, c0, 5    and     r11, r11, #MPIDR_CPUID_MASK
The MPIDR register bit[1:0] is as follows:
[1:0] CPU ID

Indicates the processor number in the Cortex-A7 MPCore processor. For:

• One processor, the CPU ID is 0x0.

• Two processors, the CPU IDs are 0x0 and 0x1.

• Three processors, the CPU IDs are 0x0, 0x1, and 0x2.

• Four processors, the CPU IDs are 0x0, 0x1, 0x2, and 0x3.

2. Add the following judgment (to avoid duplicate initialization of global resources):
    cmp     r11, #0    bne     excstatck_loop_done
3. Add entry for other cores (the specific implementation of the secondary_cpu_start function can be found in main.c):
cpu_start:    #ifdef LOSCFG_APC_ENABLE    bl      setup_mmu    #ifdef LOSCFG_KERNEL_SMP    bl      secondary_cpu_start    #endif    #endif    b       .
  • Add the following code in main.c:

for (coreId = 1; coreId < LOSCFG_KERNEL_CORE_NUM; coreId++) {    /* per cpu 4 mailbox */    mailbox->writeSet[coreId * 4 + MAILBOX3_IRQ - MAILBOX0_IRQ] = (UINT32)reset_vector;    asm volatile ("sev");}while (LOS_AtomicRead(&g_cpuNum) < LOSCFG_KERNEL_CORE_NUM) {    asm volatile("wfe");}

(Swipe left to see more)

Note:The main core wakes up other cores through the mailbox mechanism and waits for other cores to start.

  • Add IPI interrupt code in drivers/interrupt/arm_control.c. Refer to the mailbox mechanism in the official Raspberry Pi chip manual to implement the HalIrqSendIpi function and HalSmpIrqInit function.

Adapt Compilation Configuration
  • Add the following code in targets/kconfig.raspberry:

config LOSCFG_PLATFORM_RASPBERRY32_PI3B    bool "Raspberry32_Pi3B"    select LOSCFG_ARCH_CORTEX_A53_AARCH32    select LOSCFG_USING_BOARD_LD    select LOSCFG_PLATFORM_ARM_CONTROL    select LOSCFG_RASPBERRY_PI_SYSTICK
  • Modify the following Makefile:

driver/timer/Makefiledriver/interrupt/Makefiletargets/Raspberry32_Pi3B/Makefile
Note:After enabling SMP functionality on Raspberry Pi 3B, systick uses generic time; otherwise, it uses arm side timer.
Create Boot SD Card

Use the Raspberry Pi Imager tool to create the Raspberry Pi system.

LiteOS Raspberry Pi Porting Guide (Part 2)

Raspberry Pi Imager Download link:https://www.raspberrypi.org/software/
  • Replace the kernel7.img file generated by the compilation with the kernel7.img file on the SD card.

  • Insert the SD card with the written image file into the Raspberry Pi 3B and power it on, the Raspberry Pi 3B can run the LiteOS system.

The running result is as follows:

********Hello Huawei LiteOS********LiteOS Kernel Version : 5.1.0Processor : Cortex-A53 * 4Run Mode : SMPbuild time : Aug 21 2021 10:15:24**********************************OsAppInitcpu 0 entering schedulercpu 1 entering schedulercpu 2 entering schedulercpu 3 entering schedulerHuawei LiteOS #
Thus, the LiteOS system successfully started and ran. This porting project has been launched in the Gitee LiteOS community,
The related code link is: https://gitee.com/LiteOS/LiteOS/tree/master/targets/Raspberry32_Pi3B.

Related Document Links

MMU Access Control:https://blog.csdn.net/llf021421/article/details/6330102

MMU Access Control:https://blog.csdn.net/llf021421/article/details/6330102

MMU Cache and Write Buffer:https://blog.csdn.net/fcglx/article/details/87924578

MMU Page Table:https://blog.csdn.net/czg13548930186/article/details/74979222

Official Raspberry Pi Chip Manual:

https://datasheets.raspberrypi.org/bcm2835/bcm2835-peripherals.pdf

Conclusion

Thank you for reading,If you have any questions or suggestions, please leave a message for us, let’s improve together:

https://gitee.com/LiteOS/LiteOS/issues

To make it easier to find the “LiteOS” code repository, it is recommended to visithttps://gitee.com/LiteOS/LiteOS, follow “ Watch”, like “Star”, and “Fork to your account, as shown in the figure below.

LiteOS Raspberry Pi Porting Guide (Part 2)

LiteOS Raspberry Pi Porting Guide (Part 2)

– End –

LiteOS Raspberry Pi Porting Guide (Part 2)

Leave a Comment

Your email address will not be published. Required fields are marked *