Files
2026-06-12 14:22:53 +08:00

149 lines
4.7 KiB
C

/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-12-14 WangXiaoyao the first version
* 2023-03-20 WangXiaoyao Format & add more testcases for API under mm_aspace.h
* 2025-12-14 ChuanN-sudo Add standardized utest documentation block
*/
/**
* Test Case Name: MM API Test
*
* Test Objectives:
* - Verify I/O remapping functionality with cached memory access.
* - Test memory mapping flag creation and extraction mechanisms.
* - Validate address space management operations.
* - Test core APIs: rt_pages_alloc(), rt_ioremap_cached(), rt_iounmap(), rt_pages_free(),
* rt_pages_free(), MMF_CREATE(), MMF_GET_CNTL(), MMF_GET_ALIGN().
*
* Test Scenarios:
* - Address Space Test (aspace_tc): Tests memory address space management APIs.
* - I/O Remap Test (ioremap_tc): Allocates physical pages, maps to virtual address with cache, verifies data consistency, and cleans up resources.
* - Flag Test (flag_tc): Creates memory mapping flags with different parameters and validates control bits and alignment values extraction.
*
* Verification Metrics:
* - I/O remapping should correctly map physical to virtual addresses.
* - Cached memory access should maintain data consistency between physical and virtual addresses.
* - Memory mapping flags should correctly encode and decode control bits and alignment values.
* - Flag creation with alignment should set MMF_REQUEST_ALIGN bit and store alignment value.
* - Flag creation without alignment should not set alignment-related bits.
*
Dependencies:
* - Hardware requirements: QEMU emulator or any hardware platform that supports RT-Thread with MMU.
* - Software configuration:
* - RT_UTEST_MM_API must be enabled (enable via: RT-Thread Utestcases -> RT-Thread Utestcases -> Memory Management Subsystem Testcase -> Enable Utest for MM API).
* - RT_USING_SMART must be enabled (enable via: Enable RT-Thread Kernel -> RT-Thread Smart (microkernel on kernel/userland)).
* - Environmental Assumptions: MMU support must be available on the target platform.
* Expected Results:
* - Final output: "[ PASSED ] [ result ] testcase (testcases.mm.api_tc)"
* - No assertion failures during test execution.
*/
#include "common.h"
/**
* @brief Testing all APIs under components/mm
*/
void ioremap_tc(void);
void flag_tc(void);
#ifdef STANDALONE_TC
#define TC_ASSERT(expr) \
((expr) \
? 0 \
: rt_kprintf("AssertFault(%d): %s\n", __LINE__, RT_STRINGIFY(expr)))
#else
#define TC_ASSERT(expr) uassert_true(expr)
#endif
static rt_err_t utest_tc_init(void)
{
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
return RT_EOK;
}
#include "test_aspace_api.h"
static void testcase(void)
{
aspace_tc();
ioremap_tc();
flag_tc();
}
UTEST_TC_EXPORT(testcase, "testcases.mm.api_tc", utest_tc_init, utest_tc_cleanup, 20);
void ioremap_tc(void)
{
const size_t bufsz = 0x1000;
void *paddr = (void *)rt_pages_alloc(rt_page_bits(bufsz)) + PV_OFFSET;
int *vaddr;
vaddr = rt_ioremap_cached(paddr, bufsz);
if (vaddr)
{
TC_ASSERT(*vaddr == *(int *)(paddr - PV_OFFSET));
rt_iounmap(vaddr);
rt_pages_free(paddr - PV_OFFSET, 0);
}
}
void flag_tc(void)
{
size_t flags;
flags = MMF_CREATE(MMF_MAP_FIXED, 0x4000);
TC_ASSERT(MMF_GET_CNTL(flags) == (MMF_MAP_FIXED | MMF_REQUEST_ALIGN));
TC_ASSERT((1 << MMF_GET_ALIGN(flags)) == 0x4000);
flags = MMF_CREATE(MMF_MAP_FIXED, 0);
TC_ASSERT(MMF_GET_CNTL(flags) == MMF_MAP_FIXED);
TC_ASSERT(MMF_GET_ALIGN(flags) == 0);
}
#if 0
#define BUF_SIZE (4ul << 20)
static char ALIGN(BUF_SIZE) buf[BUF_SIZE];
void buddy_tc(void)
{
size_t total, free;
rt_page_get_info(&total, &free);
rt_region_t region = {
.start = (size_t)buf,
.end = (size_t)buf + BUF_SIZE,
};
size_t new_total, new_free;
rt_page_install(region);
rt_page_get_info(&new_total, &new_free);
TC_ASSERT(new_total - total == (BUF_SIZE >> ARCH_PAGE_SHIFT));
TC_ASSERT(new_free > free);
}
void mmu_page_tc()
{
mm_aspace_t aspace = ASPACE_NEW();
size_t total, free;
rt_page_get_info(&total, &free);
rt_hw_mmu_map(aspace, (void *)0x3fffffffff, 0, ARCH_PAGE_SIZE,
MMU_MAP_K_RWCB);
rt_hw_mmu_unmap(aspace, (void *)0x3fffffffff, ARCH_PAGE_SIZE);
size_t new_total, new_free;
rt_page_get_info(&new_total, &new_free);
TC_ASSERT(new_free == free);
mm_aspace_delete(aspace);
}
#endif