[文章]

【HarmonyOS HiSpark AI Camera试用连载 】第四篇 韦东山移植最小系统视频笔记

2020-11-27 09:39:32  214 HarmonyOS HiSpark AI Camera Hi3516DV300
分享
本帖最后由 jf_59342929 于 2020-11-27 10:40 编辑

移植一个最小系统要做的事情:
串口驱动:方便调试
地址映射:虚拟地址-物理地址
完善中断子系统:至少提供tick中断
实现存储设备驱动
实现根文件系统

1、移植串口和MMU,参考UBOOT来设置CPU
kernel\liteos_a\platform\main.c
//主入口main 函数
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)

...
    /* system and chip info */
    OsSystemInfo();

    PRINT_RELEASE("\nmain core booting up...\n");//串口OK,MMU内存映射OK

    uwRet = OsMain();
...

W:\harmony\code\yzx\kernel\liteos_a\kernel\common\los_config.c
LITE_OS_SEC_TEXT_INIT INT32 OsMain(VOID)
{
...
#ifdef LOSCFG_EXC_INTERACTION
#ifdef LOSCFG_ARCH_CORTEX_M7
    /* 4096: 4K space for Stack */
    ret = OsMemExcInteractionInit((UINT32)&__bss_end + 4096);
#else
    ret = OsMemExcInteractionInit((UINTPTR)&__bss_end);
#endif
...
#if (LOSCFG_PLATFORM_HWI == YES)
    OsHwiInit();
#endif

}

\kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_mp.S
//配置内存映射关系
    PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE,

MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
    PAGE_TABLE_SET SYS_MEM_BASE, UNCACHED_VMM_BASE, UNCACHED_VMM_SIZE,

MMU_INITIAL_MAP_STRONGLY_ORDERED
    PAGE_TABLE_SET PERIPH_PMM_BASE, PERIPH_DEVICE_BASE, PERIPH_DEVICE_SIZE,

MMU_INITIAL_MAP_DEVICE
    PAGE_TABLE_SET PERIPH_PMM_BASE, PERIPH_CACHED_BASE, PERIPH_CACHED_SIZE,

MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
    PAGE_TABLE_SET PERIPH_PMM_BASE, PERIPH_UNCACHED_BASE, PERIPH_UNCACHED_SIZE,

MMU_INITIAL_MAP_STRONGLY_ORDERED

\kernel\liteos_a\kernel\base\include\los_vm_zone.h
//内存转换关系
#include "board.h"
#define DEFINE_(X)  X##U
#define DEFINE(X)   DEFINE_(X)

#define KERNEL_VMM_BASE         DEFINE(KERNEL_VADDR_BASE)
#define KERNEL_VMM_SIZE         DEFINE(KERNEL_VADDR_SIZE)

#define KERNEL_ASPACE_BASE      KERNEL_VMM_BASE
#define KERNEL_ASPACE_SIZE      KERNEL_VMM_SIZE

/* Uncached vmm aspace */
#define UNCACHED_VMM_BASE       (KERNEL_VMM_BASE + KERNEL_VMM_SIZE)
#define UNCACHED_VMM_SIZE       DDR_MEM_SIZE

#define VMALLOC_START           (UNCACHED_VMM_BASE + UNCACHED_VMM_SIZE)
#define VMALLOC_SIZE            0x08000000

#define PERIPH_DEVICE_BASE      (VMALLOC_START + VMALLOC_SIZE)
#define PERIPH_DEVICE_SIZE      PERIPH_PMM_SIZE
#define PERIPH_CACHED_BASE      (PERIPH_DEVICE_BASE + PERIPH_DEVICE_SIZE)
#define PERIPH_CACHED_SIZE      PERIPH_PMM_SIZE
#define PERIPH_UNCACHED_BASE    (PERIPH_CACHED_BASE + PERIPH_CACHED_SIZE)
#define PERIPH_UNCACHED_SIZE    PERIPH_PMM_SIZE

#define IO_DEVICE_ADDR(paddr)        (paddr - PERIPH_PMM_BASE + PERIPH_DEVICE_BASE)
#define IO_CACHED_ADDR(paddr)        (paddr - PERIPH_PMM_BASE + PERIPH_CACHED_BASE)
#define IO_UNCACHED_ADDR(paddr)      (paddr - PERIPH_PMM_BASE + PERIPH_UNCACHED_BASE)

#define MEM_CACHED_ADDR(paddr)       (paddr - DDR_MEM_ADDR + KERNEL_VMM_BASE)
#define MEM_UNCACHED_ADDR(paddr)     (paddr - DDR_MEM_ADDR + UNCACHED_VMM_BASE)

#define VMM_TO_UNCACHED_ADDR(vaddr)  (vaddr - KERNEL_VMM_BASE + UNCACHED_VMM_BASE)
#define UNCACHED_TO_VMM_ADDR(vaddr)  (vaddr - UNCACHED_VMM_BASE + KERNEL_VMM_BASE)

#define VMM_TO_DMA_ADDR(vaddr)  (vaddr - KERNEL_VMM_BASE + SYS_MEM_BASE)
#define DMA_TO_VMM_ADDR(vaddr)  (vaddr - SYS_MEM_BASE + KERNEL_VMM_BASE)

#if (PERIPH_UNCACHED_BASE >= (0xFFFFFFFFU - PERIPH_UNCACHED_SIZE))
#error "Kernel virtual memory space has oveRFlowed!"
#endif

\vendor\hisi\hi35xx\hi3516dv300\config\board\include\board.h
//内存地址分布
/* Physical memory address base and size */
#ifdef LOSCFG_TEE_ENABLE
#define DDR_MEM_ADDR            0x81000000  //weidongshan 0x80000000
#define DDR_MEM_SIZE            0x1f000000  //weidongshan 0x20000000 不能用(512*1024*1024)
//因为连词符号,#define DEFINE(X)  X##U  0x20000000U这样正确,但是(512*1024*1024)U则表达错


#else
#define DDR_MEM_ADDR            0x80000000
#define DDR_MEM_SIZE            0x20000000
#endif

/* Peripheral register address base and size */
#define PERIPH_PMM_BASE         0x10000000   //weidongshan 0x02020000 //段地址,要1M的倍数

,会导致映射不成功,可以改为0x02000000

#define PERIPH_PMM_SIZE         0x10000000   //0x100//区域大小也要是1M的倍数,可以改为

0x100000

#ifdef LOSCFG_TEE_ENABLE
#define KERNEL_VADDR_BASE       0x41000000
#else
#define KERNEL_VADDR_BASE       0x40000000
#endif
#define KERNEL_VADDR_SIZE       DDR_MEM_SIZE

#define SYS_MEM_BASE            DDR_MEM_ADDR
#define SYS_MEM_SIZE_DEFAULT    0x07f00000
#define SYS_MEM_END             (SYS_MEM_BASE + SYS_MEM_SIZE_DEFAULT)

#define EXC_INTERACT_MEM_SIZE        0x100000

\vendor\hisi\hi35xx\hi3516dv300\config\board\include\platform_config.h
//硬中个数和时钟
#define LOSCFG_PLATFORM_HWI_LIMIT       96
#define OS_SYS_clock                    (50000000)

\vendor\hisi\hi35xx\hi3516dv300\config\board\include\asm\platform.h
\\寄存器地址
/*------------------------------------------------
* GIC reg base address
*------------------------------------------------*/
#define GIC_BASE_ADDR             IO_DEVICE_ADDR(0x10300000)
#define GICD_OFFSET               0x1000                          /* interrupt distributor

offset */
#define GICC_OFFSET               0x2000                          /* CPU interface register

offset */

#define DDR_MEM_BASE              0x80000000

#define FMC_MEM_PBASE             0x14000000
#define FMC_MEM_OFFSIZE           0x8

#define IO_CTL_REG_BASE           IO_DEVICE_ADDR(0x10FF0000)

#define GPIO_REG_ADDR             0x120d0000
#define GPIO11_REG_BASE           IO_DEVICE_ADDR(GPIO_REG_ADDR + 0xb000)
...
#define SPI_REG_ADDR              IO_DEVICE_ADDR(0x120c0000)
#define SPI2_REG_BASE             (SPI_REG_ADDR + 0x2000)
...
#define I2C_REG_ADDR              0x120b0000
#define I2C7_REG_PBASE            (I2C_REG_ADDR + 0x7000)
...
#define I2C7_REG_BASE             IO_DEVICE_ADDR(I2C7_REG_PBASE)
...

#define UART_REG_ADDR             0x120a0000
#define UART4_REG_PBASE           (UART_REG_ADDR + 0x4000)
...
#define UART4_REG_BASE            IO_DEVICE_ADDR(UART4_REG_PBASE)
#define UART3_REG_BASE            IO_DEVICE_ADDR(UART3_REG_PBASE)
...
#define MISC_REG_BASE             IO_DEVICE_ADDR(0x12030000)
#define SYS_CTRL_REG_BASE         IO_DEVICE_ADDR(0x12020000)
#define CRG_REG_ADDR              0x12010000
#define CRG_REG_BASE              IO_DEVICE_ADDR(CRG_REG_ADDR)
#define PERI_CRG30_BASE           IO_DEVICE_ADDR(CRG_REG_ADDR + 0x0078)  /* cpu freq-mode &

reset CRG */

#define GSF_REG_BASE              IO_DEVICE_ADDR(0x12050000)
#define SDIO0_REG_PBASE           0x100f0000
#define SDIO1_REG_PBASE           0x10020000
#define EMMC_REG_PBASE            0x10100000
#define MMC_REG_OFFSIZE           0x118

#define ETH_REG_BASE              IO_DEVICE_ADDR(0x10010000)
#define ETH_REG_OFFSIZE           0x2000

#define VIC_REG_BASE              IO_DEVICE_ADDR(0x10040000)
#define IRQ_REG_BASE              VIC_REG_BASE

#define DMAC_REG_BASE             IO_DEVICE_ADDR(0x10060000)
#define IO_MUX_REG_BASE           IO_DEVICE_ADDR(0x12040000)
#define FMC_REG_PBASE             0x10000000
#define FMC_REG_OFFSIZE           0xdc

#define TIMER0_ENABLE             BIT(16)
...
#define TIMER7_ENABLE             BIT(23)

#define TIMER7_REG_BASE           IO_DEVICE_ADDR(0x12003020)
...
#define TIMER0_REG_BASE           IO_DEVICE_ADDR(0x12000000)

#define TIMER_TICK_REG_BASE       TIMER4_REG_BASE   /* timer for tick */
#define TIMER_TICK_ENABLE         TIMER4_ENABLE
#define TIMER_TIME_REG_BASE       TIMER5_REG_BASE   /* timer for time */
#define TIMER_TIME_ENABLE         TIMER5_ENABLE
#define HRTIMER_TIMER_REG_BASE    TIMER7_REG_BASE /* timer for hrtimer */
#define HRTIMER_TIMER_ENABLE      TIMER7_ENABLE

#define CACHE_ALIGNED_SIZE        64

#define ARM_REG_BASE              IO_DEVICE_ADDR(0x10300000)

\kernel\liteos_a\platform\uart\amba_pl011\amba_pl011.c
读UART寄存器
UART_Type *uart1 = IO_DEVICE_ADDR(0x02020000) //weidongshan uart0的基地址(虚拟地址)
STATIC VOID UartPutcReg(UINTPTR base, CHAR c)
{
    /* Spin while fifo is full */
    while (UARTREG(base, UART_FR) & UART_FR_TXFF) {}
    UARTREG(base, UART_DR) = c;
   
    /*
    while (!((uart1->USR2) & (1<<3)));//等待上个字节发送完毕
    uart1->UTXD = (unsigned char)c;
    */
}

//打印不出任何串口信息后,定位一下哪里出了问题,是MMU还是串口没改对?用物理地址去控制串口试


UART_Type * uart1_phy = (UART_Type)(0x02020000)
VOID uart_putc_phy(CHAR c)
{
    while (!uart1_phy->USR2) & (1<<3)));//等待上个字节发送完毕
    uart1_phy->UTXD = (unsigned char)c;
}

VOID uart_putc_virt(CHAR c)
{
    while (!uart1->USR2) & (1<<3)));//等待上个字节发送完毕
    uart1->UTXD = (unsigned char)c;
}

//为了调用C函数(uart_putc_phy),必须先设置栈
\kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_mp.S

    /* Startup code which will get the machine into supervisor mode */
    .global reset_vector
    .type   reset_vector,function
reset_vector:
    //设置栈,weidongshan
    ldr sp, = 0x82000000
    //把字符'A'传给第一个参数
    mov ro, #'A'
    //调用uart_putc_phy
    bl uart_putc_phy

    /* clear register TPIDRPRW */
    mov     r0, #0
    mcr     p15, 0, r0, c13, c0, 4
    /* do some early cpu setup: i/d cache disable, mmu disabLED */
    mrc     p15, 0, r0, c1, c0, 0
    bic     r0, #(1<<12)
    bic     r0, #(1<<2 | 1<<0)
    mcr     p15, 0, r0, c1, c0, 0

    /* r11: delta of physical address and virtual address */

    //可以一直用uart_putc_phy跟踪,遇到问题解决
    ...
    bl      _bootaddr_setup

    //看能否跑到MMU使能之前 weidongshan
    mov ro, #'E'
    bl uart_putc_phy

    bl      mmu_setup                           /* set up the mmu */
    //看能否跑到MMU使能之后 weidongshan
    mov ro, #'F'
    bl uart_putc_virt

/* clear out the interrupt and exception stack and set magic num to check the overflow */
    ldr     r0, =__undef_stack
    ldr     r1, =__exc_stack_top
    bl      stack_init

    STACK_MAGIC_SET __undef_stack, #OS_EXC_UNDEF_STACK_SIZE, OS_STACK_MAGIC_WORD
    STACK_MAGIC_SET __abt_stack, #OS_EXC_ABT_STACK_SIZE, OS_STACK_MAGIC_WORD
    STACK_MAGIC_SET __irq_stack, #OS_EXC_IRQ_STACK_SIZE, OS_STACK_MAGIC_WORD
    STACK_MAGIC_SET __fiq_stack, #OS_EXC_FIQ_STACK_SIZE, OS_STACK_MAGIC_WORD
    STACK_MAGIC_SET __svc_stack, #OS_EXC_SVC_STACK_SIZE, OS_STACK_MAGIC_WORD
    STACK_MAGIC_SET __exc_stack, #OS_EXC_STACK_SIZE, OS_STACK_MAGIC_WORD
    ....
#ifdef LOSCFG_GDB_debug
    /* GDB_START - generate a compiled_breadk,This function will get GDB stubs started,

with a proper environment */
    bl     GDB_START
    .word  0xe7ffdeff
#endif

    //看能否跑到main函数之前 weidongshan
    mov ro, #'F'
    bl uart_putc_virt
    bl     main

_start_hang:
    b      _start_hang
    ...

//最后跳转到main函数 weidongshan,继续用PRINT_RELEASE跟踪
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)
{
    UINT32 uwRet = LOS_OK;

    PRINT_RELEASE("%s %s %d\n",_FILE_, _FUNCTION_, _LINE_);
    OsSetMainTask();
    PRINT_RELEASE("%s %s %d\n",_FILE_, _FUNCTION_, _LINE_);
    OsCurrTaskSet(OsGetMainTask());

    PRINT_RELEASE("%s %s %d\n",_FILE_, _FUNCTION_, _LINE_);
    /* set smp system counter freq */
#if (LOSCFG_KERNEL_SMP == YES)
#ifndef LOSCFG_TEE_ENABLE
    HalClockFreqWrite(OS_SYS_CLOCK);
#endif
#endif

    PRINT_RELEASE("%s %s %d\n",_FILE_, _FUNCTION_, _LINE_);
    /* system and chip info */
    OsSystemInfo();
    PRINT_RELEASE("%s %s %d\n",_FILE_, _FUNCTION_, _LINE_);
0
2020-11-27 09:39:32   评论 分享淘帖
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发表新帖