嵌入式应用软件架构设计(下)

简介: 嵌入式应用软件架构设计

有时候为了测试卡片消费,不能每次都重新编译进来吧,这时候可以利用LUA脚本。选择第11项。把需要测试卡片的指令写进LUA脚本,然后执行,


如图所示:



执行结果:



封装的功能模块,即各种库如下:


liblua.a         执行lua脚本使用


libblkfile.a    黑名单查找与存储


libmaycalc.a 算法库,如SHA,DES算法


libmycard.a  卡库,提供操作卡片的APDU


libmyfile.a    文件库,提供文件存储与读取


libmycom.a  通信库,提供socket通信


libmyup.a     银联库,银联卡处理逻辑与银联后台通信业务



其中,libmyblkfile库的makefile文件如下:


########################################
#makefile
########################################
BINARY= libmyblkfile
CC= gcc
LD= ld
CFLAGS= -std=c99 -g
LDSCRIPT=
LDFLAGS= -Llib
OBJS= AH_BlackList.o AH_BlkDirFileLib.o APP_Blacklist.o
#CFLAGS=-std=c99
.PHONY: clean
all:images
images: $(BINARY).a
$(OBJS):%.o:%.c
        $(CC) -c $(CFLAGS) $< -o $@
%.a: $(OBJS)
        ar crv $(*).a $(OBJS)
        cp libmyblkfile.a ../
clean:
        rm -f *.o



主程序的makefile文件如下:


########################################
#makefile
########################################
#编译指定子目录
SUBDIRS := .\\lib\\NC_Com\
                   .\\lib\\NC_FileSys\
           .\\lib\\NC_BlkFile\
           .\\lib\\NC_Card\\NC_Card_Lib\
           .\\lib\\NC_UPCash\\NC_UPCash_Lib
define make_subdir
@ for subdir in $(SUBDIRS) ; do \
( cd $$subdir && make $1) \
done;
endef
#编译主程序
BINARY  := ./bin/bus
OBJ_DIR := ./obj/
CC= gcc
LD= ld
CFLAGS= -std=c99 -Wall -g
LDSCRIPT= -lmycom -lws2_32 -liconv -lmyfile  -lmycard -lmyup -lmycalc -lmyblkfile -llua
LDFLAGS= -Llib
SRC  = $(wildcard *.c)
DIR  = $(notdir $(SRC))
OBJS = $(patsubst %.c,$(OBJ_DIR)%.o,$(DIR))
#OBJS=  main.o myutils.o  inirw.o  cmdpboc.o cputest.o bustcp.o ansrec.o m1cmd.o m1api.o m1test.o upcash.o myother.o getsys.o
#CFLAGS=-std=c99
#@echo Building lib...
#$(call make_subdir)
.PHONY: clean lib
all:  prebuild  $(BINARY).exe
prebuild:
        @echo Building app...
$(BINARY).exe : $(OBJS)
        @echo Generating ...
        $(CC) -o $(BINARY).exe $(OBJS) $(LDFLAGS) $(LDSCRIPT)
        @echo OK!
$(OBJ_DIR)%.o : %.c
        $(CC) -c $(CFLAGS) $< -o  $@
lib:
        @echo Building lib...
        $(call make_subdir)
clean:
        rm -f $(OBJ_DIR)*.o
        @echo Removed!


各个功能模块,又可以进一步细分为子模块。


拿通信库举例:


嵌入式设备都需要支持各种不同的通讯模块。比如硬件设备有A701、A801、B502等,通讯模块有GL868、MG323、MC8630、N710、ZIGBEE等,这些设备分别支持全部或部分通讯模块。


整体架构分为如下:



驱动大致分为三层:


1、接口层:为用户提供统一的接口,比如:Connect、TxData、RxData、Disconnect等。


2、驱动层:向接口层暴露统一的接口,这些接口用于完成实际的连接断开和数据收发等,比如:DevConnect、DevTxData、RxData、Disconnect等。该层只会和支持的通讯模块相关,不会直接访问任何硬件功能,包括串口通讯、GPIO控制全部通过底层的设备层实现。


3、设备层:向驱动层提供统一的接口,这些接口通过访问物理硬件来实现和模块的通讯,比如:XXXPowerOn、SerialSend、SerialReceive等,并定义该设备支持哪些模块。


三层之间通过标准的接口进行互相访问。


1、接口层对外接口(用户操作通讯模块使用的API):


uint32_t Com_Dev_Start(void);
//设备重新上电,并和网络建立连接
uint32_t Com_Dev_Restart(void);
//设备断网断电
uint32_t Com_Dev_Stop(void);
//连接远端服务器
uint32_t Com_Dev_Connect(uint8_t *ip, uint16_t port, uint32_t timeout, uint32_t channel);
//断开连接
uint32_t Com_Dev_Disconnect(uint32_t channel);
//发送数据
uint32_t Com_Dev_TxData(uint8_t *buf, uint32_t len, uint32_t timeout, uint32_t channel);
//接收数据
uint32_t Com_Dev_RxData(uint8_t *buf, uint32_t *rxlen, uint32_t len, uint32_t timeout, uint32_t channel);
//获取信号质量
uint32_t Com_Dev_GetSQ(uint8_t *csq);


2、驱动层对接口层的接口(对接口层屏蔽各通讯模块的差异):


struct ComDevFunc{
         uint32_t (*start)(ComDevDesc *dev);
         uint32_t (*restart)(ComDevDesc *dev);
         uint32_t (*stop)(ComDevDesc *dev);
         uint32_t (*connect)(ComDevDesc *dev, uint8_t *ip, uint16_t port, uint32_t timeout, uint32_t channel);
         uint32_t (*disconnect)(ComDevDesc *dev, uint32_t channel);
         uint32_t (*txData)(ComDevDesc *dev, uint8_t *buf, uint32_t len, uint32_t timeout, uint32_t channel);
         uint32_t (*rxData)(ComDevDesc *dev, uint8_t *buf, uint32_t *rxlen, uint32_t len, uint32_t timeout, uint32_t channel);
         uint32_t (*getVer)(ComDevDesc *dev, uint8_t *buf, uint32_t versize);
         uint32_t (*getCSQ)(ComDevDesc *dev, uint8_t *csq);
};


3、设备层对驱动层提供的接口(屏蔽串口号、GPIO引脚等平台相关的内容):


int Com_PortOpen(uint32_t baud);
int Com_PortClose(void);
int Com_PortSend(uint8_t *buf, int len);
int Com_PortRecv(uint8_t *buf, int len, int timeout);
int Com_PortGetLen(void);
int Com_PortFlush(void);
//具体硬件相关函数,在Model_XXXXX.h中实现
//仅需实现平台支持的模块即可
void COM_GL868Power(int state);
void COM_MC8332Power(int state);
void COM_MG323Power(int state);
void COM_EMV3081Power(int state);
void COM_CC2530Power(int state);
void COM_N710Power(int state);


4.   目录结构


│  ComAPI.c              -----通讯库API实现
│  ComAPI.h              -----通讯库API声明(接口层API)
│  ComDevs.c                                -----供驱动使用的公共定义和工具函数
│  ComDevs.h                                -----供驱动使用的公共定义和工具函数(驱动层API)
│  Readme.txt
├─Devices                -----存放各种模块的驱动程序
│      Dev_CDMA_MC8332.c
│      Dev_CDMA_MC8332.h
│      Dev_GPRS_GL868.C
│      Dev_GPRS_GL868.h
│      Dev_WIFI_EMV3081.c
│      Dev_WIFI_EMV3081.h
└─Models                                          -----存放适配各种设备型号的目录
        Model.h          -----设备层API
        Model_A701.c
        Model_B502.c


5.   支持新模块的方法


比如A701设备要新增支持SUPER123模块


1、在Devices目录中增加一个文件Dev_6G_SUPER123.c并实现ComDevFunc结构中定义的各函数


2、在设备文件Model_A701.c中增加电源控制函数COM_SUPER123Power。


3、在设备文件Model_A701.c中添加驱动函数到gComFuncs数组中。


4.   适配新设备的方法


1、在Models目录新增加一个文件Model_XXXX.c


2、实现串口通讯函数(Com_PortXXXX系列,参考Model.h中的定义)


3、实现支持的通讯模块的上下电函数COM_XXXXPower(int state);


4、实现gComFuncs数组,其中引用所有支持模块的驱动函数。


5.   对部分系统函数的引用


对于部分系统相关函数,比如延时、调试信息的打印等,全部提供默认实现,并将默认实现声明为弱函数。这样当用户需要进行自定义的时候可以进行自定义,如果不需要可以直接忽略不会造成编译错误。


这样的函数有如下三个:

void Com_Hook_Printf(char* fmt, ...);
void Com_Hook_PrintHex(uint8_t* buf, int len);
//重定义延时功能,如果使用操作系统的话可以充分利用操作系统的调度特性,避免死等造成的浪费
void Com_Hook_DelayMs(uint32_t ms);


6.   驱动中普遍使用的功能


对于部分编写通讯模块驱动常用的功能,模块中提供了一系列的辅助函数,避免重复劳动

相关文章
|
3月前
|
监控 Java 持续交付
深入理解微服务架构及其在现代应用开发中的应用
深入理解微服务架构及其在现代应用开发中的应用
79 1
|
2月前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
3月前
|
机器学习/深度学习 自然语言处理 分布式计算
大规模语言模型与生成模型:技术原理、架构与应用
本文深入探讨了大规模语言模型(LLMs)和生成模型的技术原理、经典架构及应用。介绍了LLMs的关键特点,如海量数据训练、深层架构和自监督学习,以及常见模型如GPT、BERT和T5。同时,文章详细解析了生成模型的工作原理,包括自回归模型、自编码器和GANs,并讨论了这些模型在自然语言生成、机器翻译、对话系统和数据增强等领域的应用。最后,文章展望了未来的发展趋势,如模型压缩、跨模态生成和多语言多任务学习。
429 3
|
1月前
|
容灾 网络协议 数据库
云卓越架构:云上网络稳定性建设和应用稳定性治理最佳实践
本文介绍了云上网络稳定性体系建设的关键内容,包括面向失败的架构设计、可观测性与应急恢复、客户案例及阿里巴巴的核心电商架构演进。首先强调了网络稳定性的挑战及其应对策略,如责任共担模型和冗余设计。接着详细探讨了多可用区部署、弹性架构规划及跨地域容灾设计的最佳实践,特别是阿里云的产品和技术如何助力实现高可用性和快速故障恢复。最后通过具体案例展示了秒级故障转移的效果,以及同城多活架构下的实际应用。这些措施共同确保了业务在面对网络故障时的持续稳定运行。
|
3月前
|
Cloud Native 安全 持续交付
深入理解微服务架构及其在现代软件开发中的应用
深入理解微服务架构及其在现代软件开发中的应用
110 32
|
3月前
|
存储 监控 API
深入解析微服务架构及其在现代应用中的实践
深入解析微服务架构及其在现代应用中的实践
99 12
|
3月前
|
运维 监控 安全
自动化运维的利剑:Ansible在现代IT架构中的应用
在数字化浪潮中,企业对IT系统的敏捷性和可靠性要求日益提高。Ansible,一种简单但强大的自动化运维工具,正成为现代IT架构中不可或缺的一部分。它通过声明式编程语言YAM,简化了系统配置、应用部署和任务自动化的过程,显著提升了运维效率和准确性。本文将深入探讨Ansible的核心特性、应用场景以及如何有效整合进现有IT环境,为读者揭示其在自动化运维中的实用价值和未来发展潜力。
|
3月前
|
监控 持续交付 API
深入理解微服务架构及其在现代应用开发中的应用
深入理解微服务架构及其在现代应用开发中的应用
47 4
|
3月前
|
运维 Kubernetes Docker
深入理解容器化技术及其在微服务架构中的应用
深入理解容器化技术及其在微服务架构中的应用
105 1
|
3月前
|
监控 持续交付 API
深入理解微服务架构及其在现代软件开发中的应用
深入理解微服务架构及其在现代软件开发中的应用
78 3