嵌入式设计中,
一个完整的程序,由大量的函数构成。这些函数,可能分为不同的组,每个组的函数,可能只关注于一些相关的数据对象,对它们进行读写。
从嵌入式工程设计的角度来看,
大体上,分为数据设计和处理设计两大块。
数据设计的目的,是为了更方便的进行处理设计。
本文重点讨论处理设计。
处理设计,具体而言,就是函数的设计。
一个完整的程序,被按照结构化设计的要求,划分为大量的函数。
这些函数被划分的依据原则,就是之前所述的数据交易。
而决定这些函数被划分的考虑的出发点,是函数的职能定位。
基于函数的职能定位,划分出函数后,才能更明确的界定出数据交易。
从函数布局的角度看来,由于每个函数具有自己的职能定位,所以才有了程序的组织架构的概念。
++++++++++++++++++++++++++++++++++++++++++
程序架构设计,有多种方法。
在嵌入式设计中,最常用的有几种架构,
例如,前后台架构,分层架构,散集架构,等等。
在SOD设计或者OOD设计中,内聚已经是最基本的要求,所以,现在已经不把散集架构作为单独的架构来考虑,默认,所有模块都是使用了内聚的。
如果是SOD,则将stuct和对应的操作集内聚为一个模块。
如果是OOD,则直接内聚为一个class。
本文重点从职能定位的角度,看待程序的架构问题。
首先来看看分层架构的职能定位,
不同层的函数,职能定位的侧重点不同,同层的函数,职能定位类似。
分层架构,最常见于协议栈的处理程序中,
每一层的函数,对应于协议栈的某一个层。
再来看看前后台架构的职能定位,
大体上,分为前台函数和后台函数,前台函数,通常是由interrupt触发后,才会执行,所以,前台函数,也经常被称为前台ISR函数。后台函数,则是在main中调用的函数。
在一个较简单的嵌入式程序中,
在ISR中直接处理前台需要的业务代码。
在一个较复杂的嵌入式程序中,一般则是在init时注册callback,在ISR中,找到event对应的callback来调用处理。
通常会存在一些机制类的响应框架级ISR函数,完成一些ISR相关的通用处理,例如查表,优先级调度,ISR排序等,之后,会轮询调用注册的callback,来处理对应的event。
在这个背景下,callback就是我们实际需要关注的前台函数。
当callback被调用时,就表明对应的event被触发了。
在SOD或者OOD设计中,
前台callback函数,其职能定位就是,依据触发event,更新相关的数据对象,例如flag,buffer等。
后台函数,会轮询相关的数据对象,例如flag,buffer等,进行后续的处理。
前台函数,只完成短平快的工作,例如事件响应,接口收发。
后台函数对数据对象的处理,是最主要的处理设计。
+++++++++++++++++++++++++++++++++++++++++
本文对职能定位的讨论,重点在于后台函数。
从职能上看,大体上可以分为,流程框架级函数,业务级函数,功能级函数,操作级函数,IO级函数。
流程框架级函数,并不包含特定的处理代码,而只是包含对于业务级函数的调用。
常见的框架级函数,是一个轮询函数。使用永续循环体作为函数的主体。
业务级函数,包含一些特定的业务处理代码,更主要的是,通过调用功能级函数,来完成业务逻辑的数据处理工作。
功能级函数,包含一些特定的功能运算代码,通过调用操作级函数,来读取或者写入系统内的硬件资源,获取数据后,进行运算处理。
操作级函数,包含一些特定的时序操作代码,通过调用IO级函数,对硬件资源的REG进行读取或者写入,从而完成从硬件资源中获取数据的任务。
IO级函数,是最小颗粒度的函数划分,它的职能定位很明确,代码也很简短,就是使用合适的指令代码,完成对硬件资源的REG的读取或者写入。