VSOA AUTOSAR 简介

更新时间:
2024-02-01
下载文档

VSOA AUTOSAR 简介

VSOA AUTOSAR 是 VSOA 针对汽车开放系统架构 AUTOSAR Classic Platform 推出的专用版本。

开发须知

AUTOSAR CP 使用的是非标准 socket 接口,采用标准 socket 接口开发的 VSOA 不能在 AUTOSAR CP 中运行,因此翼辉推出了 AUTOSAR CP 专用的 VSOA 版本。

基于 AUTOSAR CP 版本开发的 VSOA 服务端、客户端等可以与标准版本 VSOA 实现的客户端、服务端互联互通。在 VSOA AUTOSAR 中,也可支持客户端机器人、Stream、Datagram 等 VSOA 特有的高级功能。

环境搭建

本节以开源的 Tramponline AUTOSARopen in new window 为例,讲解 VSOA AUTOSAR 的使用。

AUTOSAR 对象

为了方便 VSOA AUTOSAR 在不同 AUTOSAR 版本上的使用,VSOA AUTOSAR 提供了便于移植的 vsoa_as_porting 实现,该实现可方便的将 VSOA AUTOSAR 使用的对象与 AUTOSAR 系统资源关联。

Task

在 VSOA AUTOSAR 中,需要新建至少两个 Task。其中一个用于执行 VSOA AUTOSAR 所需的定时器循环,另一个用于执行 VSOA 服务端或客户端的业务逻辑。

注意:

VSOA AUTOSAR 使用的 Task 因使用到了 Event,所以必须配置为 Extend Task。

Resource

在 VSOA AUTOSAR 中,使用 Resource 进行互斥访问,在 AUTOSAR 中提供了如下的接口进行 Resource 的获取和释放:

FUNC(StatusType, OS_CODE) GetResource(CONST(ResourceType, AUTOMATIC) res_id);
FUNC(StatusType, OS_CODE) ReleaseResource(CONST(ResourceType, AUTOMATIC) res_id);

访问临界区前调用 GetResource 获取该资源,临界区访问结束后调用 ReleaseResource 释放该资源。

Alarm

在 VSOA AUTOSAR 中,使用到 Alarm 作为定时器以及超时触发 Event 的功能。

Event

在 VSOA AUTOSAR 中,使用 Event 实现信号量功能。Event 会配合 Alarm 使用,相关函数如下:

函数功能
ClearEvent清空 Event
SetRelAlarm设定一个 Alarm 到期时设置 Event
WaitEvent等待 Event
CancelAlarm取消 Alarm

因为 WaitEvent 结束等待的情况有如下两种:

  1. 其他 Task 调用 SetEvent 设置该 Event;
  2. Alarm 到期设置该 Event。

基于以上的逻辑,相当于使用 Alarm 搭配 Event 实现了一个信号量超时等待的功能。

VSOA 初始化

初始化函数

VSOA AUTOSAR 提供了一个统一的系统初始化函数 vsoa_init,该函数应当在任何 VSOA 函数被调用前优先执行。需注意该初始化函数只能被调用一次,该函数原型如下:

vsoa_init_res_t *vsoa_init(vsoa_init_arg_t *arg);

该初始化函数传入的参数类型如下,其中每一个变量都是 VSOA 运行所需 AUTOSAR 提供的一类系统资源,包括内存、事件管理、定时器、错误号等。

typedef struct {
    /* cannot be less than VSOA_MIN_MEM_POOL_SZ */
    void *mem_start;
    size_t mem_length;

    /* The following members must valid */
    vsoa_mem_osl_t *mem_osl;
    vsoa_event_osl_t *event_osl;
    vsoa_timer_osl_t *timer_osl;
    vsoa_server_svc_osl_t *server_osl;
    vsoa_client_svc_osl_t *client_osl;

    /* The following members are optional */
    vsoa_errno_osl_t *errno_osl;
} vsoa_init_arg_t;

当初始化函数执行成功时,其将返回一个非空的函数指针,该函数指针需要放入一个独立的 Task 中运行,返回值类型如下:

typedef struct {
    void (*timer_loop)(void);
} vsoa_init_res_t;

初始化示例

  1. 在 AUTOSAR 系统中建立一个名为 demo_task 的 Task,其 ID 指定为 demo_task_id。该 Task 同时需要关联 ID 为 demo_task_alarm_id 的 Alarm 和 demo_task_timeout_mask 的Alarm Event,该 Alarm 到期后触发 demo_task_timeout_mask 的 Event 唤醒 demo_task。在该 Task 中调用 vsoa_as_porting 实现的 vsoa_as_task_register 接口,注册该 Task。

    说明:

    Task ID、Alarm ID 和 Event Mask 的定义方式不同的 AUTOSAR 版本略有差异,通常通过工具或脚本的方式自动生成。

    /*
     * 使用 VSOA 的任务需要定义一个 vsoa_as_task_t, 并使用 vsoa_as_task_register 注册
     */
    static vsoa_as_task_t vsoa_as_demo_task = {
        .task_id     = demo_task_id,
        .alarm       = demo_task_alarm_id,
        .alarm_event = demo_task_timeout_mask
    };
    
    TASK(demo_task) {
      /*
       * 注册任务
       */
      vsoa_as_task_register(&vsoa_as_demo_task);
    }
    
  2. 在该 Task 中调用 vsoa_init 进行 VSOA AUTOSAR 的初始化。

    /*
     * VSOA 初始化参数与返回值
     */
    static vsoa_init_arg_t vsoa_init_arg = {
        .mem_start  = vsoa_mem,
        .mem_length = VSOA_MEM_SIZE,
        .mem_osl    = &vsoa_mem_osl,
        .timer_osl  = &vsoa_as_timer_osl,
        .event_osl  = &vsoa_as_event_osl,
        .server_osl = &vsoa_server_svc_osl,
        .client_osl = &vsoa_client_svc_osl,
        .errno_osl  = &vsoa_errno_osl
    };
    
    static vsoa_init_res_t *vsoa_init_res = NULL;
    
    /*
     * 使用 VSOA 的任务需要定义一个 vsoa_as_task_t, 并使用 vsoa_as_task_register 注册
     */
    static vsoa_as_task_t vsoa_as_demo_task = {
        .task_id     = demo_task_id,
        .alarm       = demo_task_alarm_id,
        .alarm_event = demo_task_timeout_mask
    };
    
    TASK(demo_task) {
        /*
         * 注册任务
         */
        vsoa_as_task_register(&vsoa_as_demo_task);
    
        /*
         * 初始化 VSOA
         */
        vsoa_init_res = vsoa_init(&vsoa_init_arg);
    
        while (1) {
            vsoa_init_res->timer_loop();
        }
    
        TerminateTask();
    }
    
  3. 完成 vsoa_init_arg 中内存资源的定义。其中 vsoa_mem_osl 需要关联一个 ID 为 vsoa_mem_lock_id 的 Resource 作为内存资源访问时的互斥控制。

    /*
     * VSOA 内存大小
     */
    #define VSOA_MEM_SIZE       256 * 1024
    
    /*
     * 一个 vsoa_mem_osl_t 实现, 需要一个 Resource 作为 mutex
     */
    static vsoa_mem_osl_t vsoa_mem_osl = {
        .ctx    = (void *)(long)vsoa_mem_lock_id,
        .lock   = vsoa_as_mem_lock,
        .unlock = vsoa_as_mem_unlock
    };
    
    /*
     * VSOA memory
     */
    static uint8_t vsoa_mem[VSOA_MEM_SIZE];
    
  4. 完成 vsoa_init_arg 中定时器资源的定义。其中 vsoa_as_timer_ctx 需要关联一个 ID 为 vsoa_timer_lock_id 的 Resource 作为定时器资源访问时的互斥控制,需要关联一个名为 vsoa_timer_sem_event_mask 的 Event Mask 作为信号量使用。

    /*
     * 一个 vsoa_timer_osl_t 实现, 需要一个 vsoa_as_timer_ctx_t,
     * vsoa_as_timer_ctx_t 需要一个 Resource 和 Event 分别作 mutex 和 semaphore
     */
    static vsoa_as_timer_ctx_t vsoa_as_timer_ctx = {
        .mutex = vsoa_timer_lock_id,
        .event = vsoa_timer_sem_event_mask,
    };
    
    static vsoa_timer_osl_t vsoa_as_timer_osl = {
        .ctx     = &vsoa_as_timer_ctx,
        .lock    = vsoa_as_timer_lock,
        .unlock  = vsoa_as_timer_unlock,
        .wait    = vsoa_as_timer_wait,
        .post    = vsoa_as_timer_post,
        .curtime = vsoa_as_timer_curtime
    };
    
  5. 完成 vsoa_init_arg 中事件管理资源的定义。其中 vsoa_as_event_ctx 需要关联一个 ID 为 vsoa_event_lock_id 的 Resource 作为事件管理资源访问时的互斥控制,需要关联一个名为 vsoa_event_sem_event_mask 的 Event Mask 作为信号量使用。

    /*
     * 一个 vsoa_event_osl_t 实现, 需要一个 vsoa_as_event_ctx_t,
     * vsoa_as_event_ctx_t 需要一个 Resource 和 Event 分别作 mutex 和 semaphore
     */
    static vsoa_as_event_ctx_t vsoa_as_event_ctx = {
        .mutex = vsoa_event_lock_id,
        .event = vsoa_event_sem_event_mask
    };
    
    static vsoa_event_osl_t vsoa_as_event_osl = {
        .ctx    = &vsoa_as_event_ctx,
        .lock   = vsoa_as_event_lock,
        .unlock = vsoa_as_event_unlock,
        .wait   = vsoa_as_event_wait,
        .post   = vsoa_as_event_post,
    };
    
  6. 完成 vsoa_init_arg 中内建服务器管理资源的定义,该内建服务器管理结构用于管理 VSOA AUTOSAR 创建的服务器。其中 vsoa_server_svc_osl 需要关联一个 ID 为 vsoa_server_svc_lock_id 的 Resource 作为内建服务器管理资源访问时的互斥控制。

    /*
     * 一个 vsoa_server_svc_osl_t 实现, 需要一个 Resource 作为 mutex
     */
    static vsoa_server_svc_osl_t vsoa_server_svc_osl = {
        .ctx    = (void *)(long)vsoa_server_svc_lock_id,
        .lock   = vsoa_as_server_svc_lock,
        .unlock = vsoa_as_server_svc_unlock
    };
    
  7. 完成 vsoa_init_arg 中内建客户端管理资源的定义,该内建客户端管理结构用于管理 VSOA AUTOSAR 创建的客户端。其中 vsoa_client_svc_osl 需要关联一个 ID 为 vsoa_client_svc_lock_id 的 Resource 作为内建客户端管理资源访问时的互斥控制。

    /*
     * 一个 vsoa_client_svc_osl 实现, 需要一个 Resource 作为 mutex
     */
    static vsoa_client_svc_osl_t vsoa_client_svc_osl = {
        .ctx    = (void *)(long)vsoa_client_svc_lock_id,
        .lock   = vsoa_as_client_svc_lock,
        .unlock = vsoa_as_client_svc_unlock
    };
    
  8. 完成 vsoa_init_arg 中错误码管理资源的定义。

    /*
     * 一个 vsoa_errno_osl_t 实现
     */
    static vsoa_errno_osl_t vsoa_errno_osl = {
        .get = vsoa_as_errno_get,
        .set = vsoa_as_errno_set
    };
    

说明:

以上 vsoa_as_mem_lock 等接口实现,可参考 VSOA AUTOSAR 资料中的 "vsoa_as_porting.c" 等文件。

文档内容是否对您有所帮助?
有帮助
没帮助