liteOS-A学习笔记-2.移植串口和MMU

1.移植串口

(1)追踪串口打印函数

《kernel/liteos_a/platform》

LITE_OS_SEC_TEXT_INIT INT32 main(VOID)
{
    ...
    PRINT_RELEASE("\nmain core booting up...\n");
    ...

(2)最终调用函数

《liteos_a\platform\uart\amba_pl011\amba_pl011.c》

VOID UartPuts(const CHAR *s, UINT32 len, BOOL isLock)

应当按照HISI这个文件中定义的函数接口进行移植形成NXPimx6ull的代码文件

《OpenharmonyFor6ull\vendor\nxp\imx6ull\driver\imx6ull-uart\uart_imx6ull.c》

->

STATIC INLINE UINTPTR uart_to_ptr(UINTPTR n)
{
    (VOID)n;
    return UART_REG_BASE;
}

(3)uart的基地址:此时已经启动MMU,应当为虚拟地址

《OpenharmonyFor6ull\vendor\nxp\imx6ull\board\include\uart.h》


#if (CONSOLE_UART == UART0)
    #define TTY_DEVICE                "/dev/uartdev-0"
    #define UART_REG_BASE             UART0_REG_BASE
    #define NUM_HAL_INTERRUPT_UART    NUM_HAL_INTERRUPT_UART0
#elif (CONSOLE_UART == UART1)
    #define TTY_DEVICE                "/dev/uartdev-1"
    #define UART_REG_BASE             UART1_REG_BASE
    #define NUM_HAL_INTERRUPT_UART    NUM_HAL_INTERRUPT_UART1
#elif (CONSOLE_UART == UART2)
    #define TTY_DEVICE                "/dev/uartdev-2"
    #define UART_REG_BASE             UART2_REG_BASE
    #define NUM_HAL_INTERRUPT_UART    NUM_HAL_INTERRUPT_UART2
#endif

《OpenharmonyFor6ull\vendor\nxp\imx6ull\board\include\asm\platform.h》

#define UART0_REG_PBASE           0x02020000
 /* 建立物理地址和虚拟地址之间的映射关系函数 */
#define UART0_REG_BASE            IO_DEVICE_ADDR(UART0_REG_PBASE)
#define UART1_REG_BASE            IO_DEVICE_ADDR(0x12041000)
#define UART2_REG_BASE            IO_DEVICE_ADDR(0x12042000)

//#define UART0_REG_PBASE           0x12040000
#define UART1_REG_PBASE           0x12041000
#define UART2_REG_PBASE           0x12042000

#if (CONSOLE_UART == UART0)
    #define UART_BASE             UART0_REG_BASE
    #define UART0_INT_NUM    NUM_HAL_INTERRUPT_UART0
#elif (CONSOLE_UART == UART1)
    #define UART_BASE             UART1_REG_BASE
    #define UART0_INT_NUM    NUM_HAL_INTERRUPT_UART1
#elif (CONSOLE_UART == UART2)
    #define UART_BASE             UART2_REG_BASE
    #define UART0_INT_NUM    NUM_HAL_INTERRUPT_UART2
#endif

(4)建立物理地址和虚拟地址的映射函数
开始移植MMU啦

2.移植MMU

虚拟地址排列顺序:

1.KERNEL_VMM_BASE:页表1
2.DDR_RAMFS_VBASE
3.LCD_FB_VBASE
4.UNCACHED_VMM_BASE:页表2
5.VMALLOC
6.PERIPH_DEVICE_BASE      
7.PERIPH_CACHED
8.PERIPH_UNCACHED
    PAGE_TABLE_SET SYS_MEM_BASE, UNCACHED_VMM_BASE, UNCACHED_VMM_SIZE, MMU_INITIAL_MAP_STRONGLY_ORDERED
#ifdef LOSCFG_PLATFORM_IMX6ULL
    PAGE_TABLE_SET DDR_RAMFS_ADDR, DDR_RAMFS_VBASE, DDR_RAMFS_SIZE, MMU_INITIAL_MAP_DEVICE
    PAGE_TABLE_SET LCD_FB_BASE, LCD_FB_VBASE, LCD_FB_SIZE, MMU_INITIAL_MAP_DEVICE
#endif
    PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
    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

其中,PAGE_TABLE_SET 为宏定义,其定义在reset_vector_up.s为:

/* param0 is physical address, 物理地址
   param1 virtual address, 虚拟地址
   param2 is sizes, 大小
   param3 is flag 标志
   */
.macro PAGE_TABLE_SET param0, param1, param2, param3
    ldr     r6, =\param0
    ldr     r7, =\param1
    ldr     r8, =\param2
    ldr     r10, =\param3
    bl      page_table_build
.endm

/*
 * r4: page table base address
 * r6: physical address
 * r7: virtual address
 * r8: sizes
 * r10: flags
 * r9 and r12 will be used as variable
 */
page_table_build:
    mov     r9, r6								//r9=r6:物理地址
    bfc     r9, #20, #12                        /* r9: pa % MB */
    add     r8, r8, r9                          //r8:末地址
    add     r8, r8, #(1 << 20)                  //
    sub     r8, r8, #1
    /*lsr 右移指令*/
    lsr     r6, #20                             /* r6 = physical address / MB */
    lsr     r7, #20                             /* r7 = virtual address / MB */
    lsr     r8, #20                             /* r8 = roundup(size, MB) */
/*r6 physAddr右移20位之后的值
  r7 virtual address
  r8 sizes
  r10: flags
*/
page_table_build_loop:
	/*lsl 左移指令,r12 = r10 | r6<<20 
	  orr 位或指令
	  r12 = r10 | r6<<20
	一级描述符的内容:r12 = r10存储的本段的flags | 本段实际的物理地址的基地址*/
    orr     r12, r10, r6, lsl #20               /* r12: flags | physAddr */
    /*一级描述符的地址: r4为基地址 + r7虚拟地址的bit31~bit20 + 0b00 ,参见[liteOS-A学习笔记-2.移植串口和MMU预备知识] FIGURE 3.3*/
    str     r12, [r4, r7, lsl #2]               /* gPgTable[l1Index] = physAddr | flags */
    /* r6物理地址基址指向下一个段 */
    add     r6, #1                              /* physAddr+ */
    /* r7虚拟地址基址也指向下一个段 */
    add     r7, #1                              /* l1Index++ */
    /* r8剩余段的数量减小一个 */
    subs    r8, #1                              /* sizes-- */
    bne     page_table_build_loop
    bx      lr

2.1 代码分析-初始化页表1:物理地址和不使用cache时的地址之间转换

//            系统内存的物理地址,系统内存的虚拟地址,系统内存的大小,内存的类型
//             0x80000000,                       相当于DDR内存的大小,
PAGE_TABLE_SET SYS_MEM_BASE, UNCACHED_VMM_BASE, UNCACHED_VMM_SIZE, MMU_INITIAL_MAP_STRONGLY_ORDERED

(1)SYS_MEM_BASE:系统内存的物理地址

《OpenharmonyFor6ull\vendor\nxp\imx6ull\board\include\board.h》

在这里插入图片描述
(2)UNCACHED_VMM_BASE:系统内存的虚拟地址

《OpenharmonyFor6ull\kernel\liteos_a\kernel\base\include\los_vm_zone.h》

在这里插入图片描述
在这里插入图片描述

其中,KERNEL_VADDR_BASEKERNEL_VADDR_SIZE

《OpenharmonyFor6ull\vendor\nxp\imx6ull\board\include\board.h》

在这里插入图片描述

(3)UNCACHED_VMM_SIZE:系统内存的大小

《OpenharmonyFor6ull\kernel\liteos_a\kernel\base\include\los_vm_zone.h》

在这里插入图片描述
(4)MMU_INITIAL_MAP_STRONGLY_ORDERED:

《OpenharmonyFor6ull\kernel\liteos_a\arch\arm\arm\include\los_mmu_descriptor_v6.h》

#define MMU_INITIAL_MAP_STRONGLY_ORDERED                                    \
    (MMU_DESCRIPTOR_L1_TYPE_SECTION |                                       \
    MMU_DESCRIPTOR_L1_TYPE_STRONGLY_ORDERED |                               \
    MMU_DESCRIPTOR_L1_SMALL_DOMAIN_CLIENT |                                 \
    MMU_DESCRIPTOR_L1_AP_P_RW_U_NA)

宏定义,规定了内存的类型

2.2 代码分析-初始化页表2:物理地址和使用cache时的地址之间转换

//            系统内存的物理地址,系统内存的虚拟地址,系统内存的大小,内存的类型
//             0x80000000,                       相当于DDR内存的大小,
PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS

2.3 代码分析-初始化页表3:外设的基地址和它的虚拟地址之间转换

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

(1)PERIPH_PMM_BASE:

《OpenharmonyFor6ull\vendor\nxp\imx6ull\board\include\board.h》

/* Peripheral register address base and size */
#define PERIPH_PMM_BASE         0x00a00000
#define PERIPH_PMM_SIZE         0x02300000

(2)PERIPH_DEVICE_BASE
PERIPH_CACHED_BASE
PERIPH_UNCACHED_BASE

《OpenharmonyFor6ull\kernel\liteos_a\kernel\base\include\los_vm_zone.h》


#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

(3)外围物理地址和虚拟地址转换

#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)

3.启动MMU后虚拟地址和物理地址转换

OpenharmonyFor6ull\kernel\liteos_a\kernel\base\include\los_vm_zone.h

虚拟地址和物理地址之间只是起始地址有变化,目前是按照一级页表进行映射的

#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)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值