VSF MCU的基本架构移植技巧浅析

控制/MCU

1811人已加入

描述

  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。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分