Files
mkrtos-real/mkrtos_knl/knl/misc.c
2023-09-29 01:03:19 +08:00

181 lines
4.8 KiB
C

/**
* @file misc.c
* @author zhangzheng (1358745329@qq.com)
* @brief
* @version 0.1
* @date 2023-09-29
*
* @copyright Copyright (c) 2023
*
*/
#include "types.h"
#include "mm_wrap.h"
#include "mm.h"
#include "mm_space.h"
#include "util.h"
#include "mpu.h"
#include "printk.h"
static bool_t mpu_calc(
mm_space_t *ms,
umword_t mem_start_addr,
int size,
umword_t *ret_align_size,
umword_t *alloc_addr)
{
int ffs_t_;
int ffs_t;
region_info_t *region[2];
region[0] = mm_space_alloc_pt_region(ms);
region[1] = mm_space_alloc_pt_region(ms);
if (!region[0] || !region[1])
{
if (!region[0])
{
mm_space_free_pt_region(ms, region[0]);
}
if (!region[1])
{
mm_space_free_pt_region(ms, region[1]);
}
return FALSE;
}
ffs_t_ = ffs(size);
if (!is_power_of_2(size))
{
ffs_t_++;
}
ffs_t = 1 << ffs_t_;
int sub_region_t = ffs_t >> 3;
int align_sub_size = ALIGN(size, sub_region_t);
umword_t mem_align_sub_mem_addr = ALIGN((umword_t)mem_start_addr, sub_region_t);
umword_t mem_align_up_mem_addr = ALIGN((umword_t)mem_start_addr, ffs_t);
umword_t mem_align_down_mem_addr = ALIGN_DOWN((umword_t)mem_start_addr, ffs_t);
region[0]->start_addr = mem_align_sub_mem_addr;
region[0]->size = mem_align_up_mem_addr - mem_align_sub_mem_addr;
region[0]->block_size = ffs_t;
region[0]->block_start_addr = mem_align_down_mem_addr;
if (alloc_addr)
{
*alloc_addr = region[0]->start_addr;
}
region[0]->region = 0xff;
for (umword_t i = mem_align_down_mem_addr; i < mem_align_up_mem_addr; i += sub_region_t)
{
if (i < mem_align_sub_mem_addr)
{
region[0]->region |= 1 << ((i - mem_align_down_mem_addr) / sub_region_t);
}
else
{
region[0]->region &= ~(1 << ((i - mem_align_down_mem_addr) / sub_region_t));
}
}
region[1]->region = 0x00;
for (umword_t i = mem_align_up_mem_addr; i < mem_align_up_mem_addr + ffs_t; i += sub_region_t)
{
if (i < mem_align_sub_mem_addr + align_sub_size)
{
region[1]->region &= ~(1 << ((i - mem_align_up_mem_addr) / sub_region_t));
}
else
{
region[1]->region |= (1 << ((i - mem_align_up_mem_addr) / sub_region_t));
}
}
region[1]->start_addr = mem_align_up_mem_addr;
region[1]->size = (mem_align_sub_mem_addr + align_sub_size) - mem_align_up_mem_addr;
region[1]->block_size = ffs_t;
region[1]->block_start_addr = mem_align_up_mem_addr;
*ret_align_size = sub_region_t;
#if 1
printk("st:0x%x re:0x%x sub:0x%x\n region:[", region[0]->block_start_addr, region[0]->region, sub_region_t);
for (int i = 0; i < 8; i++)
{
if (region[0]->region & (1 << i))
{
printk("x");
}
else
{
printk("o");
}
}
printk("]\n");
printk("st:0x%x re:0x%x sub:0x%x\n region:[", region[1]->block_start_addr, region[1]->region, sub_region_t);
for (int i = 0; i < 8; i++)
{
if (region[1]->region & (1 << i))
{
printk("x");
}
else
{
printk("o");
}
}
printk("]\n");
#endif
mpu_calc_regs(region[0], region[0]->block_start_addr, ffs_t_, REGION_RWX, region[0]->region);
mpu_calc_regs(region[1], region[1]->block_start_addr, ffs_t_, REGION_RWX, region[1]->region);
// region_i[2].rbar = ARM_MPU_RBAR(2, 0x20010000/*TODO:*/);
// region_i[2].rasr = ARM_MPU_RASR(0UL, ARM_MPU_AP_URO, 0UL
// , 0UL, 1UL, 1UL, 0x0/*TODO:*/, 16-1/*TODO:*/);
// region_i[2].rbar = ARM_MPU_RBAR(2, 0x8000000 /*TODO:*/);
// region_i[2].rasr = ARM_MPU_RASR(0UL, ARM_MPU_AP_URO, 0UL, 0UL, 1UL, 1UL, 0x0 /*TODO:*/, ffs(1024 * 1024) - 1 /*TODO:*/);
return TRUE;
}
void *mpu_ram_alloc(mm_space_t *ms, ram_limit_t *r_limit, size_t ram_size)
{
umword_t pre_alloc_addr;
struct mem_heap *heap = NULL;
/*TODO:临界区保护*/
again_alloc:
heap = mm_get_free(heap, ram_size, &pre_alloc_addr);
if (!heap)
{
printk("The system is low on memory.\n");
mm_trace();
return NULL;
}
umword_t need_align;
umword_t alloc_addr;
if (mpu_calc(ms, pre_alloc_addr, ram_size,
&need_align, &alloc_addr) == FALSE)
{
printk("The MPU area is exhausted.");
return NULL;
}
void *ram = mm_limit_alloc_align(r_limit, ram_size, need_align);
if (!ram)
{
printk("The system is low on memory.\n");
return NULL;
}
//!< 申请的地址与预分配的地址不同
if (ram != (void *)alloc_addr)
{
printk("Again.\n");
mm_limit_free_align(r_limit, ram, need_align);
heap = heap->next;
goto again_alloc;
}
return ram;
}