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

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

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭