打印

VSF MCU移植说明 -- 基本构架移植

[复制链接]
1162|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
vsfopen|  楼主 | 2018-10-5 21:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 vsfopen 于 2018-10-5 22:23 编辑

VSF的MCU移植包括2部分,1是基本构架,2是外设驱动移植。这里先讲一下基本构架的移植。

VSF的基本构架的移植,包括arch移植、编译器的移植。

1. 编译器移植
位于vsf/compiler目录下,可以参考IAR的compiler.h,需要实现如下宏/函数:
1) packed相关的宏
#define PACKED_HEAD                __packed
#define PACKED_MID               
#define PACKED_TAIL               
用例:
PACKED_HEAD struct PACKED_MID vsfip_protoport_t
{
        uint16_t src;
        uint16_t dst;
}; PACKED_TAIL
2) ROOTFUNC
#define ROOTFUNC                __root
用例:
ROOTFUNC void UART0_IRQHandler(void)
{
        uart_handler(0);
}
3) weak相关宏
#define WEAKFUNC_HEAD        __weak
#define WEAKFUNC_TAIL        
用例:
WEAKFUNC_HEAD void HardFault_Handler(void) WEAKFUNC_TAIL
{
        while (1);
}
4) 中断控制相关
#define vsf_gint_t                                                __istate_t
#define vsf_set_gint(gint)                                __set_interrupt_state(gint)
#define vsf_get_gint()                                        __get_interrupt_state()
#define vsf_enter_critical()                        __disable_interrupt()
#define vsf_leave_critical()                        __enable_interrupt()
5) heap相关
unsigned char * compiler_get_heap(void);
long compiler_get_heap_size(void);
实现:
#pragma segment="HEAP"
unsigned char * compiler_get_heap(void)
{
        return __sfb("HEAP");
}

long compiler_get_heap_size(void)
{
        return (long)__sfe("HEAP") - (long)__sfb("HEAP");
}
6) pc/lr相关,实际没有用到,做一些实验的时候加上的
#define compiler_set_pc(reg)                        asm("MOV pc, %0" : :"r"(reg))
#define compiler_get_lr(reg)                        asm("MOV %0, lr" : "=r"(reg))

2. ARCH移植位于vsf/hal/arch/XXXX
多任务核心根据需要实现的优先级数量,对MCU的中断系统会有不同的要求。
1) 只需要非实时,系统运行类似前后台
对MCU没要求,大部分MCU都可以使用,这种模式下,vsfmain.c可以非常简单,如下:
// IMPORTANT: DONOT CHANGE ANYTHING IN THIS FILE
#include "vsf.h"
#include "usrapp.h"

#if defined(APPCFG_NRT_QUEUE_LEN) && (APPCFG_NRT_QUEUE_LEN > 0)
#define APPCFG_MAINQ_EN     // 设置了NRT队列,使能MAIN_QUEUE
#endif
#if defined(APPCFG_VSFTIMER_NUM) && (APPCFG_VSFTIMER_NUM > 0)
#define APPCFG_VSFTIMER_EN  // 设置了定制器支持
#endif

struct vsfapp_t
{
        // 用户的APP结构指针
        struct usrapp_t *usrapp;

        // 如果使能了定时器,根据是否支持内存管理,来选择定时器的内存池类型(动态池和静态池)
#ifdef APPCFG_VSFTIMER_EN
#ifdef APPCFG_BUFMGR_SIZE
        struct vsf_dynpool_t vsftimer_pool;
#else
        VSFPOOL_DEFINE(vsftimer_pool, struct vsftimer_t, APPCFG_VSFTIMER_NUM);
#endif
#endif

        // 设置MAIN_QUEUE数据结构
#if VSFSM_CFG_PREMPT_EN
#ifdef APPCFG_MAINQ_EN
        struct vsfsm_evtq_t mainq;
        struct vsfsm_evtq_element_t mainq_ele[APPCFG_NRT_QUEUE_LEN];
#endif
#endif
} static app =
{
        .usrapp = (struct usrapp_t *)&usrapp,
#if VSFSM_CFG_PREMPT_EN
#ifdef APPCFG_MAINQ_EN
        .mainq.size = dimof(app.mainq_ele),
        .mainq.queue = app.mainq_ele,
        .mainq.activate = NULL,
#endif
#endif

#if defined(APPCFG_VSFTIMER_EN) && defined(APPCFG_BUFMGR_SIZE)
        .vsftimer_pool.item_size = sizeof(struct vsftimer_t),
        .vsftimer_pool.pool_size = APPCFG_VSFTIMER_NUM,
#endif
};

// 定时器分配接口
#ifdef APPCFG_VSFTIMER_EN
#ifdef APPCFG_BUFMGR_SIZE
static struct vsftimer_t* vsftimer_memop_alloc(void)
{
        return vsf_dynpool_alloc(&app.vsftimer_pool);
}

static void vsftimer_memop_free(struct vsftimer_t *timer)
{
        vsf_dynpool_free(&app.vsftimer_pool, timer);
}
#else
static struct vsftimer_t* vsftimer_memop_alloc(void)
{
        return VSFPOOL_ALLOC(&app.vsftimer_pool, struct vsftimer_t);
}

static void vsftimer_memop_free(struct vsftimer_t *timer)
{
        VSFPOOL_FREE(&app.vsftimer_pool, timer);
}
#endif

const struct vsftimer_mem_op_t vsftimer_memop =
{
        .alloc                        = vsftimer_memop_alloc,
        .free                        = vsftimer_memop_free,
};

// 定时器回调
// tickclk interrupt, simply call vsftimer_callback_int
static void app_tickclk_callback_int(void *param)
{
        vsftimer_callback_int();
}
#endif

static void vsfapp_init(struct vsfapp_t *app)
{
#if VSFSM_CFG_PREMPT_EN
        vsfsm_evtq_set(&app->mainq);
#endif

        // 初始化MCU内核、tickclk(系统滴答)
        vsfhal_core_init(NULL);
        vsfhal_tickclk_init(APPCFG_TICKCLK_PRIORITY);
        vsfhal_tickclk_start();

        // 初始化定时器内存池
#ifdef APPCFG_VSFTIMER_EN
#ifdef APPCFG_BUFMGR_SIZE
        vsf_dynpool_init(&app->vsftimer_pool);
#else
        VSFPOOL_INIT(&app->vsftimer_pool, struct vsftimer_t, APPCFG_VSFTIMER_NUM);
#endif
        vsftimer_init((struct vsftimer_mem_op_t *)&vsftimer_memop);
        vsfhal_tickclk_config_cb(app_tickclk_callback_int, NULL);
#endif

        // 初始化内存管理
#ifdef APPCFG_BUFMGR_SIZE
        vsf_bufmgr_init(compiler_get_heap(), APPCFG_BUFMGR_SIZE);
#endif

        // 用户非实时部分初始化
#ifdef APPCFG_NRT_QUEUE_LEN
        usrapp_nrt_init(app->usrapp);
#endif
}

int main(void)
{
        // 关中断
        vsf_enter_critical();

#ifdef APPCFG_INITIAL_INIT
        usrapp_initial_init(app.usrapp);
#endif

        // MAIN_QUEUE初始化
#ifdef APPCFG_MAINQ_EN
        vsfsm_evtq_init(&app.mainq);
#endif

        // 应用初始化
        vsfapp_init(&app);
        // 开中断
        vsf_leave_critical();

        while (1)
        {
#if defined(APPCFG_USR_POLL) && !defined(APPCFG_MAINQ_EN)
                // 轮询模式
                vsfhal_tickclk_poll();
                usrapp_nrt_poll(app.usrapp);
#elif defined(APPCFG_USR_POLL_SLEEP)
                // 带休眠轮询
                usrapp_nrt_poll(app.usrapp);
                vsfhal_core_sleep(VSFHAL_SLEEP_WFI);
#elif defined(APPCFG_MAINQ_EN)
                // 事件队列模式
                vsfsm_poll();
#ifdef APPCFG_USR_POLL
                usrapp_nrt_poll(app.usrapp);
#endif
                vsf_enter_critical();
                if (!vsfsm_get_event_pending()
#ifdef APPCFG_USR_CANSLEEP
                        && usrapp_cansleep(app.usrapp)
#endif
                        )
                {
                        vsfhal_core_sleep(VSFHAL_SLEEP_WFI);        // will enable interrupt
                }
                else
                        vsf_leave_critical();
#else
                // 无非实时任务
                vsfhal_core_sleep(VSFHAL_SLEEP_WFI);
#endif
        }
}
vsfhal中内核层需要实现的基本接口:vsfhal_core_init: MCU内核初始化,初始化时钟、复位、调试口、等等核心功能
tickclk相关: 用于实现系统滴答,可选
vsfhal_core_sleep: 内核休眠,可选

2) 非实时+软实时+硬实时
在1) 的基础上,需要MCU支持可控的、可屏蔽的、可设置优先级的软件中断。比如CortexM的PendSV,CortexA的SGI。



使用特权

评论回复

相关帖子

沙发
aEs3sgeKl| | 2020-2-22 19:56 | 只看该作者
怎么就没人拜我为偶像那??

使用特权

评论回复
发新帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

90

主题

325

帖子

8

粉丝