VSF然并卵 -- 动态加载

[复制链接]
1853|2
 楼主| Simon21ic 发表于 2015-8-6 11:09 | 显示全部楼层 |阅读模式
本帖最后由 Simon21ic 于 2015-8-6 11:23 编辑

最近有人提起了动态加载,自己也抽空评估了一下这个技术,虽然并没有什么卵用,不过还是玩了一下。

动态加载,顾名思义,就是动态加载应用,应用程序可以不在芯片内部的flash里,比如外接的U盘里,然后载入到内存中运行。然而,一般的嵌入式操作系统,都不具备这种能力。
由于编译器具备ropi选项,所以程序部分,比较容易实现地址无关(不管程序在哪个地址,都可以正常运行)。但是,即便编译器具备rwpi,也一般是通过R9寄存器,来设置rw段的基地址。这样虽然可行,但是会非常麻烦,所有应用中的函数,被调用时,都需要保证R9被正确设置。

VSF构架,由于给应用层的接口都是面向对象的,使得能够非常容易的解决这个问题,就是应用程序不需要静态内存,应用需要的内存资源都使用动态分配。VSF的进程,以及回调函数等等,都可以设置一个用户定义的指针,正好可以用来指向这个分配的内存。

系统代码:
  1. #include "vsf.h"
  2. #include "app_hw_cfg.h"

  3. struct vsfapp_t
  4. {
  5.         struct app_hwcfg_t hwcfg;
  6.         
  7.         uint8_t bufmgr_buffer[64 * 1024];
  8. } static app =
  9. {
  10.         {
  11.                 {
  12.                         {
  13.                                 2,                                        // uint8_t port;
  14.                                 13,                                        // uint8_t pin;
  15.                         },                                                // struct usb_pullup;
  16.                 },                                                        // struct usbd;
  17.         {
  18.             {3, 4, 3, 6},
  19.             {4, 1, 4, 0},
  20.             {3, 5, 3, 3},
  21.             {3, 9, 3, 10},
  22.             {4, 15, 3, 8},
  23.             {4, 13, 4, 14},
  24.             {4, 11, 4, 12},
  25.             {4, 9, 4, 10},
  26.             {4, 7, 4, 8},
  27.             {3, 0, 3, 1},
  28.             {3, 14, 3, 15},
  29.             {6, 13, 6, 14},
  30.             {4, 6, 4, 2},
  31.             {4, 4, 4, 5},
  32.             {3, 13, 4, 3},
  33.             {3, 11, 3, 12},
  34.             {6, 4, 6, 5},
  35.             {6, 2, 6, 3},
  36.             {6, 0, 6, 1},
  37.             {5, 14, 5, 15},
  38.             {5, 12, 6, 13},
  39.             {5, 4, 5, 5},
  40.             {5, 2, 5, 3},
  41.             {5, 0, 5, 1},
  42.         },                            // struct led_t led[24];
  43.         },                                                                // struct app_hwcfg_t hwcfg;
  44. };

  45. // tickclk interrupt, simply call vsftimer_callback_int
  46. static void app_tickclk_callback_int(void *param)
  47. {
  48.         vsftimer_callback_int();
  49. }

  50. int main(void)
  51. {
  52.         int (*app_main)(const struct vsf_t *vsf, struct app_hwcfg_t *hwcfg) = NULL;
  53.         
  54.         vsf_leave_critical();
  55.         
  56.         // system initialize
  57.         vsf_bufmgr_init(app.bufmgr_buffer, sizeof(app.bufmgr_buffer));
  58.         core_interfaces.core.init(NULL);
  59.         core_interfaces.tickclk.init();
  60.         core_interfaces.tickclk.start();
  61.         vsftimer_init();
  62.         core_interfaces.tickclk.set_callback(app_tickclk_callback_int, NULL);
  63.         
  64.         // load and call application
  65.         // TODO: try to load app_main address
  66.         app_main = (int (*)(const struct vsf_t *vsf, struct app_hwcfg_t *hwcfg))0x08008000;
  67.         if (app_main != NULL)
  68.         {
  69.                 app_main(&vsf, &app.hwcfg);
  70.         }
  71.         
  72.         while (1)
  73.         {
  74.                 vsfsm_poll();
  75.                
  76.                 vsf_enter_critical();
  77.                 if (!vsfsm_get_event_pending())
  78.                 {
  79.                         // sleep, will also enable interrupt
  80.                         core_interfaces.core.sleep(SLEEP_WFI);
  81.                 }
  82.                 else
  83.                 {
  84.                         vsf_leave_critical();
  85.                 }
  86.         }
  87. }
应用层序只是做了系统初始化,包括系统初始化,定时器管理初始化,内存管理初始化后,就可以调用应用程序了,这里假定应用程序位于0x08008000的位置。当然,应用程序可以是多个,也可以不在内部flash里(这个就需要先把应用程序复制到内存中)。应用程序的第一个32位数据,是放应用程序用,main函数的偏移。应用中的main函数,参数为vsf和硬件配置。vsf提供了可以使用的系统的所有接口,包括访问硬件的接口,简单的定义如下:
  1. const struct vsf_t vsf =
  2. {
  3.         &core_interfaces,
  4.         
  5.         {
  6.                 vsfsm_init,
  7.                 vsfsm_pt_init,
  8.                 vsfsm_post_evt,
  9.                 vsfsm_post_evt_pending,
  10.                 vsfsm_enter_critical_internal,
  11.                 vsfsm_leave_critical_internal,
  12.                 vsfsm_sem_init_internal,
  13.                 vsfsm_sem_post_internal,
  14.                 vsfsm_sem_pend_internal,
  15.                 vsfsm_crit_init_internal,
  16.                 vsfsm_crit_enter_internal,
  17.                 vsfsm_crit_leave_internal,
  18.                 vsftimer_register,
  19.                 vsftimer_unregister,
  20.         },                                                // struct vsf_framework_t framework;
  21.         
  22.         {
  23.                 {
  24.                         vsf_fifo_init,
  25.                         vsf_fifo_push8,
  26.                         vsf_fifo_pop8,
  27.                         vsf_fifo_push,
  28.                         vsf_fifo_pop,
  29.                         vsf_fifo_get_data_length,
  30.                         vsf_fifo_get_avail_length,
  31.                 },                                        // struct fifo
  32.                 {
  33.                         vsf_bufmgr_malloc,
  34.                         vsf_bufmgr_malloc_aligned,
  35.                         vsf_bufmgr_free,
  36.                 },                                        // struct bufmgr;
  37.         },                                                // struct buffer;
  38. };
当然,这个还只是测试的代码,很多协议栈的接口还都没放进去。

应用部分:
应用程序,只需要知道芯片是什么类型的,用来指定编译用的指令集。比如,本例程中芯片使用stm32,所以应用程序的工程可以选择CortexM3的芯片。当然,如果选择CortexM0,那就各种CortexM的处理器都可以兼容。简单的说就是硬件可以使用stm32f1,也可以用新塘的M0,或者atmel的M4,应用程序的二进制文件都不用修改。上代码吧:
  1. #include "vsf.h"
  2. #include "app_hw_cfg.h"

  3. #define LED_EVT_CARRY                                        (VSFSM_EVT_USER_LOCAL + 0)

  4. struct vsfapp_t
  5. {
  6.         struct
  7.         {
  8.                 struct vsf_t const *vsf;
  9.         } sys;
  10.         
  11.         struct vsfsm_t sm;
  12.         struct vsftimer_timer_t timer;
  13.         
  14.         // Application
  15.         uint8_t led_num;
  16.         struct app_led_t
  17.         {
  18.                 struct led_t const *hw;
  19.                 bool on;
  20.                
  21.                 struct vsfsm_pt_t pt;
  22.                 struct vsfsm_t *sm_carry;
  23.                
  24.                 struct vsfsm_t sm;
  25.                 struct vsfapp_t *app;
  26.         } led[24];
  27. };

  28. static vsf_err_t app_led_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
  29. {
  30.         struct app_led_t *led = (struct app_led_t *)pt->user_data;
  31.         struct vsfapp_t *app = led->app;
  32.         struct interfaces_info_t const *ifs = app->sys.vsf->ifs;
  33.         struct vsf_framework_t const *framework = &app->sys.vsf->framework;
  34.         
  35.         vsfsm_pt_begin(pt);
  36.         
  37.         while (1)
  38.         {
  39.                 vsfsm_pt_wfe(pt, LED_EVT_CARRY);
  40.                
  41.                 if (led->on)
  42.                 {
  43.                         ifs->gpio.clear(led->hw->hport, 1 << led->hw->hpin);
  44.                         if (led->sm_carry != NULL)
  45.                         {
  46.                                 framework->post_evt(led->sm_carry, LED_EVT_CARRY);
  47.                         }
  48.                 }
  49.                 else
  50.                 {
  51.                         ifs->gpio.set(led->hw->hport, 1 << led->hw->hpin);
  52.                 }
  53.                 led->on = !led->on;
  54.         }
  55.         
  56.         vsfsm_pt_end(pt);
  57.         return VSFERR_NONE;
  58. }

  59. static struct vsfsm_state_t *
  60. app_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  61. {
  62.         struct vsfapp_t *app = (struct vsfapp_t *)sm->user_data;
  63.         struct interfaces_info_t const *ifs = app->sys.vsf->ifs;
  64.         struct vsf_framework_t const *framework = &app->sys.vsf->framework;
  65.         struct app_led_t *led;
  66.         struct led_t const *hwled;
  67.         uint8_t i;
  68.         
  69.         switch (evt)
  70.         {
  71.         case VSFSM_EVT_INIT:
  72.                 // Application
  73.                 for (i = 0; i < app->led_num; i++)
  74.                 {
  75.                         led = &app->led[i];
  76.                         hwled = led->hw;
  77.                         
  78.                         led->on = false;
  79.                         led->pt.thread = app_led_thread;
  80.                         led->pt.user_data = led;
  81.                         led->sm_carry = (i < (app->led_num - 1)) ? &app->led[i + 1].sm : NULL;
  82.                         led->app = app;
  83.                         
  84.                         ifs->gpio.init(hwled->lport);
  85.                         ifs->gpio.clear(hwled->lport, 1 << hwled->lpin);
  86.                         ifs->gpio.config_pin(hwled->lport, hwled->lpin, ifs->gpio.constants.OUTPP);
  87.                         ifs->gpio.init(hwled->hport);
  88.                         ifs->gpio.clear(hwled->hport, 1 << hwled->hpin);
  89.                         ifs->gpio.config_pin(hwled->hport, hwled->hpin, ifs->gpio.constants.OUTPP);
  90.                         
  91.                         framework->pt_init(&led->sm, &led->pt);
  92.                 }
  93.                
  94.                 app->timer.interval = 1;
  95.                 app->timer.evt = LED_EVT_CARRY;
  96.                 app->timer.sm = sm;
  97.                 framework->timer_register(&app->timer);
  98.                 break;
  99.         case LED_EVT_CARRY:
  100.                 framework->post_evt(&app->led[0].sm, LED_EVT_CARRY);
  101.                 break;
  102.         }
  103.         return NULL;
  104. }

  105. vsf_err_t __iar_program_start(struct vsf_t const *vsf, struct app_hwcfg_t const *hwcfg)
  106. {
  107.         int i;
  108.         struct vsfapp_t *app = vsf->buffer.bufmgr.malloc(sizeof(struct vsfapp_t));
  109.         
  110.         if (NULL == app)
  111.         {
  112.                 return VSFERR_NOT_ENOUGH_RESOURCES;
  113.         }
  114.         
  115.         memset(app, 0, sizeof(*app));
  116.         app->sys.vsf = vsf;
  117.         app->led_num = dimof(hwcfg->led);
  118.         for (i = 0; i < app->led_num; i++)
  119.         {
  120.                 app->led[i].hw = &hwcfg->led[i];
  121.         }
  122.         
  123.         app->sm.init_state.evt_handler = app_evt_handler;
  124.         app->sm.user_data = app;
  125.         vsf->framework.sm_init(&app->sm);
  126.         return VSFERR_NONE;
  127. }
应用程序里,定义了struct vsfapp_t结构,但是并没有使用静态分配的内存,所以应用程序编译后,只占用flash,不占用ram。运行应用程序的main后,调用vsf提供的内存管理接口,分配app的内存,并设置给相应的结构。应用中,并没有实现main函数,而是实现了__iar_program_start,这个是iar的程序入口,如果实现这个的话,IAR就不会自己添加调用main的代码(因为main是在系统里调用的,不需要程序自己调用),这里可以认为__iar_program_start就是应用的main函数。应用中的其他部分,都只是访问指向app内存的指针,来访问内存资源。当然,还有一个,就是编译后的镜像的第一个32为,需要是main函数的指针,IAR下可以这么实现,在startup.s文件中:
  1.         SECTION .entry:CODE:ROOT(4)
  2.         EXTERN  __iar_program_start
  3.         DATA
  4.         DCD     __iar_program_start
  5.         END
并且,在linker文件中,把这个放在地址0。

mmuuss586 发表于 2015-8-6 12:32 | 显示全部楼层

似乎和ST版块没啥关系
 楼主| Simon21ic 发表于 2015-8-6 12:39 | 显示全部楼层
mmuuss586 发表于 2015-8-6 12:32
似乎和ST版块没啥关系

不知道应该发那个板块,帮我移一下吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:www.versaloon.com --- under construction

266

主题

2597

帖子

104

粉丝
快速回复 在线客服 返回列表 返回顶部