当前位置:首页 > 公众号精选 > 糖果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获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

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

ADSL是什么?ADSL是一种异步传输模式(ATM)。ADSL是指使用电话线接入互联网,这需要一个专用的调制解调器。上网时高频和低频分开,上网没有延迟,速度比普通拨号快很多。

关键字: ADSL技术 ATM 互联网

日前,广发银行发布公告称,9月3日起停止ATM二维码存款功能。8月以来,除广发银行外,建设银行、中国银行也发布了类似公告,招商银行部分分支机构也关闭了相关功能。业内人士认为,此项功能调整主要是为了落实监管要求,保护客户的...

关键字: ATM 二维码 存款功能

弗吉尼亚州赫恩登2022年6月8日 /美通社/ -- 空中交通管理(ATM)和空中交通流量管理系统(ATFM)软件解决方案领域的全球领先企业之一Metron Avi...

关键字: METRO VIA ATM FM

(全球TMT2022年5月9日讯)高效运行的物流运输是当今商业运作重要的一环,这其中能确实地掌握货品、车辆、人员的位置及动态,做好资源调派与整合是企业成功的关键因素。为此,环旭电子推出全球立即寻址资产追踪器UT-1,利...

关键字: 电子 寻址 低功耗 ATM

摘要:基于传统直角坐标机器人控制技术,以蓄电池极板连续生产线的码垛机器人为应用案例,根据设备需求、机器人控制原理和系统状态机的设计,介绍了一种通用的、灵活的、开发周期短的多轴直角坐标机器人控制方法。该机器人经过实践,验证...

关键字: 直角坐标机器人 状态机 控制系统

分组交换技术分组交换技术的广泛应用和发展,出现了传送话音业务的电路交换网络和传送数据业务的分组交换网络两大网络共存的局面,语音业务和数据业务的分网传送,促使人们思考一种新的技术来同时提供电路交换和分组交换的优点,并且同时...

关键字: 分组交换 ATM IP电话

异步转移模式(ATM)是一种以固定长度的分组方式,并以异步时分复用方式,传送任意速率的宽带信号和数字等级系列信息的交换设备。异步转移模式是用于实现宽带综合业务数字网( B-ISDN )的基础技术。它可综合任意速率的话音、...

关键字: ATM 数据 图像

▼点击下方名片,关注公众号▼欢迎关注【玩转单片机与嵌入式】公众号,回复关键字获取更多免费资料。回复【加群】,限时免费进入知识共享群;回复【3D封装库】,常用元器件的3D封装库;回复【电容】,获取电容、元器件选型相关的内容...

关键字: 单片机 状态机 传感器中

城市传输网是配置在一个城市地域内(包括市区、郊区和辖区)的传输网。它是支持一个城市地域内的各种业务网的传输平台。以前中国的城市传输网主要是以话音业务为主, 承担着交换机之间的互联, 所以又叫做市话网, 传输设备也基本由各...

关键字: 城市传输网 接入层 ATM

数据链路层定义了在单个链路上如何传输数据。这些协议与被讨论的各种介质有关。

关键字: 数据链路层 介质 ATM
关闭
关闭