当前位置:首页 > 汽车电子 > 糖果Autosar
[导读]点 击 上 方 蓝 字     关 注 我 们 引言 记得年轻的时候去面试一家大厂的嵌入式软件工程师的职位,面试官让很多候选人三人一组讨论去设计一款ATM机,当时我们那组讨论的热火朝天,什么把Linux操作系统内核移植过来,加入互锁机制确保取钱的安全性,什么多线

   




引言

记得年轻的时候去面试一家大厂的嵌入式软件工程师的职位,面试官让很多候选人三人一组讨论去设计一款ATM机,当时我们那组讨论的热火朝天,什么把Linux操作系统内核移植过来,加入互锁机制确保取钱的安全性,什么多线程加快速度等等天马行空的方案。最终默默地在等待Offer,就一直默默而无下文了。现在站在大厂的角度想一想,可能是通过一些试题想考察你对一个项目的软件思维能力。啥叫软件思维能力。就是从软件的角度去解读需求。别囫囵吞枣,大而空地泛泛之谈。你能想得越细,设计的代码覆盖的case越多,设计的代码简单且RAM,ROM越节省,执行效率越高,这才是去做嵌入式软件工程师的正确解法。我们从状态机的角度去分析一下解题步骤:

  • 全面详尽的弄清楚客户的需求,分解成相应的功能或多个子功能需求
  • 弄清楚这些功能中的状态,并确定状态的转移条件(及状态的进入和退出条件或事件),设计出系统的状态骨架
  • 测试每个转移的有效性
  • 针对每个状态,结合功能需求细化状态中需要做哪些事情
  • 集成进行系统的集成测试

ATM状态机

当您设计ATM 的功能时,设想一下你是小明。小明走到ATM机面前,一系列的事件(事件是指在某个时刻发生的事情 )发生了,插入卡片(Card_Insert_Event),输入密码(Pin_Enter_Even),选择办理事项(Option_Selection_Event:取钱/存钱/查询余额),输入数额(Amount_Enter_Event)并按确认,ATM吐出所需钱财(Amount_Dispatch_Event)。如下图为从ATM取钱的一个状态机模型, 描述了ATM状态及转移条件。

状态作为系统的一种特定阶段的状态,则会持续一段时间,直到特定的触发事件导致状态的转移的特定点为止。例如夜深人静的时候ATM大概率处于空闲状态。过节的时候(是蛮多和女生相关的且需要花钱的节日的),你走到ATM插入卡片后的那个时间点,ATM从空闲状态切换到了检测到卡片插入状态。

对事件发生所执行的事件处理是当前状态和输入事件的一个函数。此处的名字叫做EventHandle, 还可叫做Action(有三类:entry,during,exit)。其可存在转移的分支上,或者是位于状态的进入或退出动作或during标签中,如下图所示。

  • entry: 当进入一个状态的时候执行该标签下的action,该action在状态中其它任何action之前执行。
  • during: 当状态处于激活时执行during 标签下的action , during活动在进入活动之后执行,并且—直运行到它本身完成为止(同步执行的动作)。
  • exit: 当离开—个状态的时候触发执行该标签下的action,该活动在该状态结束之前并且所有其它action都完成后触发执行。

一般状态之间的转换不仅依赖于Event的发生,还需要[Condition Expression]这个门控条件成立,才能发生转移。如下图中的转移的方式:转移条件分别为Condition和Event。

状态机实现方式

如果你用C语言建模的话,一般推荐下面两种方式

  • 实现方式1:switch-case结构。
    实现方式简单,Case变多的时候不易维护,并且圈复杂度较高。
#include <stdio.h>
//Different state of ATM machine
typedef enum
{
    Idle_State,
    Card_Inserted_State,
    Pin_Eentered_State,
    Option_Selected_State,
    Amount_Entered_State,
} eSystemState;
//Different type events
typedef enum
{
    Card_Insert_Event,
    Pin_Enter_Event,
    Option_Selection_Event,
    Amount_Enter_Event,
    Amount_Dispatch_Event
} eSystemEvent;
//Prototype of eventhandlers
eSystemState AmountDispatchHandler(void)
{
    return Idle_State;
}
eSystemState EnterAmountHandler(void)
{
    return Amount_Entered_State;
}
eSystemState OptionSelectionHandler(void)
{
    return Option_Selected_State;
}
eSystemState EnterPinHandler(void)
{
    return Pin_Eentered_State;
}
eSystemState InsertCardHandler(void)
{
    return Card_Inserted_State;
}
int main(int argc, char *argv[])
{
    eSystemState eNextState = Idle_State;
    eSystemEvent eNewEvent;
    while(1)
    {
        //Read system Events
        eSystemEvent eNewEvent = ReadEvent();
        switch(eNextState)
        {
        case Idle_State:
        {
            if(Card_Insert_Event == eNewEvent)
            {
                eNextState = InsertCardHandler();
            }
        }
        break;
        case Card_Inserted_State:
        {
            if(Pin_Enter_Event == eNewEvent)
            {
                eNextState = EnterPinHandler();
            }
        }
        break;
        case Pin_Eentered_State:
        {
            if(Option_Selection_Event == eNewEvent)
            {
                eNextState = OptionSelectionHandler();
            }
        }
        break;
        case Option_Selected_State:
        {
            if(Amount_Enter_Event == eNewEvent)
            {
                eNextState = EnterAmountHandler();
            }
        }
        break;
        case Amount_Entered_State:
        {
            if(Amount_Dispatch_Event == eNewEvent)
            {
                eNextState = AmountDispatchHandler();
            }
        }
        break;
        default:
            break;
        }
    }
    return 0;
}

  • 实现方式2:查表方式
    易于维护,可以方便你增加新的状态或事件。减少代码的长度,通过函数指针和事件及状态进行绑定,非要说个缺点就是使用了指针,在汽车Misra C标准中不太推荐使用指针。
#include <stdio.h>
//Different state of ATM machine
typedef enum
{
    Idle_State,
    Card_Inserted_State,
    Pin_Eentered_State,
    Option_Selected_State,
    Amount_Entered_State,
    last_State
} eSystemState;
//Different type events
typedef enum
{
    Card_Insert_Event,
    Pin_Enter_Event,
    Option_Selection_Event,
    Amount_Enter_Event,
    Amount_Dispatch_Event,
    last_Event
} eSystemEvent;
//typedef of function pointer
typedef eSystemState (*pfEventHandler)(void);
//structure of state and event with event handler
typedef struct
{

    eSystemState eStateMachine;
    eSystemEvent eStateMachineEvent;
    pfEventHandler pfStateMachineEvnentHandler;
} sStateMachine;
//function call to dispatch the amount and return the ideal state
eSystemState AmountDispatchHandler(void)
{
    return Idle_State;
}
//function call to Enter amount and return amount entered state
eSystemState EnterAmountHandler(void)
{
    return Amount_Entered_State;
}
//function call to option select and return the option selected state
eSystemState OptionSelectionHandler(void)
{
    return Option_Selected_State;
}
//function call to enter the pin and return pin entered state
eSystemState EnterPinHandler(void)
{
    return Pin_Eentered_State;
}
//function call to processing track data and return card inserted state
eSystemState InsertCardHandler(void)
{
    return Card_Inserted_State;
}
//Initialize array of structure with states and event with proper handler
sStateMachine asStateMachine [] =
{
    {Idle_State,Card_Insert_Event,InsertCardHandler},
    {Card_Inserted_State,Pin_Enter_Event,EnterPinHandler},
    {Pin_Eentered_State,Option_Selection_Event,OptionSelectionHandler},
    {Option_Selected_State,Amount_Enter_Event,EnterAmountHandler},
    {Amount_Entered_State,Amount_Dispatch_Event,AmountDispatchHandler}
};
//main function
int main(int argc, char *argv[])
{
    eSystemState eNextState = Idle_State;
    while(1)
    {
        //Api read the event
        eSystemEvent eNewEvent = read_event();
        if((eNextState < last_State) && (eNewEvent < last_Event)&& (asStateMachine[eNextState].eStateMachineEvent == eNewEvent) && (asStateMachine[eNextState].pfStateMachineEvnentHandler != NULL))
        {
            // function call as per the state and event and return the next state of the finite state machine
            eNextState = (*asStateMachine[eNextState].pfStateMachineEvnentHandler)();
        }
        else
        {
            //Invalid
        }
    }
    return 0;
}


往期链接:

UDS诊断看这篇就够了,吐血整理

AUTOSAR诊断通信栈简介

Diagnosis about DEM module

Memory 的介绍1

功能安全之看门狗WDGM 介绍

AUTOSAR ASILD级别安全软件模块的安全机制介绍

基于Autosar软件的功能安全开发的介绍

AUTOSAR模式管理经验总结

AURIX GTM 输出模块(TOM)

使用AURIX TOM模块生成交流电机的PWM驱动

AUTOSAR OS分析概述

OS-Protection   -Timing Protection

Autosar OS (2)

Autosar OS 介绍


关注微信公众号『糖果Autosar』,后台回复“资料”查看更多内容,回复“加群”加入汽车电子与AUTOSAR技术交流群。

                      


免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭