-
如下图所示,线程创建后进行校时,校时成功后就会主动退出,但是去查看后台线程发现线程还在,只是状态变成了 invalid,不知道这是怎么回事
-
liteos是不是只可以用c语言去搞?不懂C语言没法入门了么?还要移植,学习成本好像有点高...看到说支持js,不知能否用js去完呢?
-
-
Liteos如何实现实现us级延时呢?用个定时器,不停查询更新位吗?还是改节拍设置
-
小白想咨询以下各位大佬,下面是否有问题,希望不吝赐教!创建一个信号量,信号量包含6个元素。然后post该信号量6次然后再次一直pend该信号量那么是否会出现 pend 12次后才会pend失败?看了下信号量的源码:信号量创建2.创建的时候MaxCount 是0xffff;3.信号量释放:申请6个元素的信号量。所以post 6个是时候不会达到MaxSemCount. 如下图1.。所以一直会进入下图2. usSemCount一直在增加。4.pend。如下图1所示,如果usSemCount只要大于0,就可以一直取。由post导致usSemCount增加,所以可以获取的信号量,不是创建的时候的信号量的数量。
-
问题:关于移植Liteos(非接管中断)到STM32F4上后,原来裸机外设驱动的延时如何处理呢,小白的疑惑 1.之前没学过OS,直接从Liteos开始的。 2.因为使用的HAL库,移植成功Liteos后,有些硬件有严格的时序要求,之前裸机用的都是HAL_Delay()延时,移植了系统后,需要换成什么呢, LOS_TaskDelay()延时不是会可以发生任务调度的吗,原来的HAL_Delay(),也是systick实现,不会冲突吗?没有实际案例看,想不明白 有经验的前辈能指点下吗? 3. HAL_Delay(),程序跑死
-
摘要:本文介绍使用野火开发板通过Agent Tiny SDK的端云互通组件,使用LWm2m协议快速接入华为云平台。通过平台侧、设备侧的开发以及调测过程来了解经BS接入物联网平台模式的具体流程,希望对你有所帮助。1 前言本文档主要通过实例讲述如何通过Agent Tiny SDK的端云互通组件,使用LwM2M协议快速接入华为物联网平台。2 Agent Tiny SDK简介Agent Tiny是部署在具备广域网能力、对功耗/存储/计算资源有苛刻限制的终端设备上的轻量级互联互通中间件,您只需调用API接口,便可实现设备快速接入到物联网平台以及数据上报和命令接收等功能。 Agent Tiny SDK是Huawei Agent Tiny软件开发工具包(Software Development Kit),通过Agent Tiny SDK端云互通组件,简单快速地实现与华为物联网平台安全可靠连接,可以大大减少开发周期, 快速构建IoT产品。端云互通组件可以采用MQTT、CoAP和LwM2W协议接入物联网平台。IOT SDK 架构图 图2-013接入物联网平台流程本章分别从 IoT 平台侧和端侧阐述通过端云互通组件接入物联网平台的开发流程,旨在帮助开发者在 IoT 设备上集成端云互通组件,进行IoT应用开发和调测。 端云互通组件接入华为 OceanConnect IoT 云平台默认采用的是以太网方式(即以太网口驱动+LwIP网络协议栈+LwM2M协议+Agent Tiny SDK 对接云平台), 同时也支持WIFI、GSM、NB-IoT等无线方式。OceanConnect 即华为IoT联接管理平台(IoT Connection Management Platform)是面向运营商和企业/行业领域的统一开放云平台, 支持SIM和非SIM场景的各种联接和联接管理。通过开放的APIs,向上集成各种行业应用,向下接入各种传感器、终端和网关,帮助运营商和企业/行业客户实现多种行业终端的快速接入, 多种行业应用的快速集成。华为IoT联接管理平台提供安全可控的全联接管理,使能行业革新,构建IoT生态(本章中提到的IoT平台指OceanConnect)。平台对接信息图3-01设备接入云端可分为直连接入和BS引导接入,如下示意图 图3-02直连接入物联网平台示意图图3-03 BS引导接入物联网平台示意图4直连接入实例(https://bbs.huaweicloud.com/blogs/148751)5经 BS 接入实例(参考)LINUX设备平台接入实例图5.0-015.1平台侧开发BS引导模式平台侧开发包括:产品导入,设备导入,配置发放策略,发放设备。 1 环境准备在开发之前,需要提前获取如下信息:物联网平台的访问账号/密码,需要向OceanConnect IoT平台申请2 产品导入产品导入用于导入用户已开发和定义的产品模型。产品模型是指接入平台的设备的类型,产品信息包括产品名称、厂商、协议等信息。如果使用设备接入和设备管理服务,需要提前在开发中心完成产品模型定义并发布到产品中心,选择“从产品中心导入”。 如果仅使用设备接入服务,则选择“创建产品”。创建产品仅支持创建MQTT协议产品。(1)登录IoT云平台。IoT云平台的访问账号和密码需要向IoT平台服务商申请。(2)进入设备发放服务,点击“从产品中心导入”。图5.1-01 产品导入在新弹出界面中,产品名称输入“EVB”,协议类型选择“LwM2M”,点击“搜索”,在搜索结果列表中选择产品点击“导入”。图 5.1-02 选择产品说明:如上产品选择仅为参考举例,具体配置请以实际产品模型为准。图 5.1-03 产品导入成功3 设备导入设备导入用于将设备基本信息导入设备发放平台中,用于后续发放至不同的物联网平台,支持批量导入和单个导入。设备导入成功后,可在设备仓库中查看设备的详细信息。登录IoT平台的开发者中心。进入设备发放服务页面,选择“设备导入”,点击页面右上角“单个导入”。图 5.1-04 设备导入(3)在配置设备基本信息界面中,产品信息选择上一步导入的产品、设置好设置设备标识码、设备名称、访问方式选择“IP”,点击“确认导入”图5.1-05配置设备基本信息说明:如上配置仅为参考举例,具体配置请以现网需求为准。4 配置发放策略发放策略用于控制设备按照指定策略或规则发放至不同的物联网平台。当前支持按照设备名称中的关键字设置发放示例,最多可添加20个发放实例。在设备发放服务页面选择“发放策略”,点击“设备名称筛选”,添加实例。图5.1-06添加实例在添加实例配置框内填写关键字,关键字为设备导入中的设备名称、选择发放区域、点击“确定”。图5.1-07配置发放策略5 发放设备发放设备会将设备发放到指定站点的物联网平台(设备接入),对于首次发放的设备,设备上电后会自动引导设备接入指定的物联网平台。选择“设备仓库”,在设备列表选择要发放的设备,点击“发放设备”,弹出对话框点击“确定”,点击“立即启动”。图5.1-08发放设备图5.1-09 立即启动5.2设备侧开发BS引导模式设备侧开发包括: 配置Demo中对接云端设备的信息、编译、运行SDK、数据上报功能调测。设备侧开发环境准备在开发之前,需要提前进行如下操作:在虚拟机中搭建好Ubuntu操作系统获取端云互通组件代码:https://github.com/LiteOS/LiteOS/tree/iot_link配置Demo中对接云端设备的信息(1)将组件代码源文件复制到Ubuntu用户目录下图5.2-01复制组件代码源文件到用户目录(2)在Demo源文件中设置云平台IP以及设备EP Name。oc_lwm2m_bs_demo.c位于 LiteOS-iot_link/demos。这些参数将作为入参传入oc_lwm2m_config()以对LiteOS端云互通组件进行初始化。EP Name就是在云平台上注册设备时开发者设定的验证码,必须保证是唯一的;oc_lwm2m_bs_demo.c中示例如下:#define cn_app_server "iot-bs.cn-north-4.myhuaweicloud.com" #define cn_app_server "119.3.251.30" #define cn_endpoint_id "test_lwm2m10" #define cn_app_port "5683"(3)修改编译配置文件。config.mk位于 LiteOS-iot_link/targets/LINUX/GCC。参考如下配置:CONFIG_OS_TYPE := "linux" CONFIG_ARCH_CPU_TYPE := "x86-64" CONFIG_SHELL_ENABLE := n CONFIG_STIMER_ENABLE := y CONFIG_DRIVER_ENABLE := n CONFIG_AT_ENABLE := n CONFIG_CJSON_ENABLE := y CONFIG_TCPIP_ENABLE := y CONFIG_TCPIP_TYPE := "linux_socket" CONFIG_DTLS_ENABLE := n CONFIG_DTLS_TYPE := "mbedtls_psk" CONFIG_MQTT_ENABLE := n CONFIG_MQTT_TYPE := "lite_mqtt" CONFIG_LWM2M_ENABLE := y CONFIG_LWM2M_TYPE := "wakaama_lwm2m" CONFIG_COAP_ENABLE := n CONFIG_COAP_TYPE := "lite_coap" CONFIG_OC_COAP_ENABLE := n CONFIG_OC_COAP_TYPE := "soft" CONFIG_OC_MQTT_ENABLE := n CONFIG_OC_MQTT_TYPE := "soft" CONFIG_OC_LWM2M_ENABLE := y CONFIG_OC_LWM2M_TYPE := "soft" CONFIG_OTA_ENABLE := n CONFIG_PCP_ENABLE := n CONFIG_DEMO_ENABLE := y CONFIG_DEMO_TYPE := "oc_lwm2m_bs_demo" include $(TOP_DIR)/iot_link/iot.mk(4)编译并运行。进入到LiteOS-iot_link/targets/LINUX/GCC目录下执行“make”命令,编译成功后会在当前文件夹下生成"build"目录,输入“./build/Huawei_LiteOS.elf”运行。图5.2-02make图5.2-03 运行程序图5.2-04连接云平台(5)查看设备状态。登录IoT平台进入设备管理服务,选择“所有设备”,在设备列表中查看对应设备的状态。如果状态为“在线”,则表示设备已经成功接入IoT平台。图5.2-05 查看设备状态5.3调测数据上报对于开发者来说,只需在app\_report\_task\_entry\(\)中将其传递给数据上报结构体 light 即可。具体调测过程如下:(1)设备侧执行app_report_task_entry函数,使设备上报数据。oc_lwm2m_bs_demo.c中的函数app_data_report如下:static int app_report_task_entry() { int ret = -1; int lux = 0; oc_config_param_t oc_param; app_light_intensity_t light; memset(&oc_param,0,sizeof(oc_param)); oc_param.app_server.ep_id = cn_endpoint_id; oc_param.boot_server.address = cn_app_server; oc_param.boot_server.port = cn_app_port; oc_param.boot_server.ep_id = cn_endpoint_id; oc_param.boot_mode = en_oc_boot_strap_mode_client_initialize; oc_param.rcv_func = app_msg_deal; while(1) //--TODO ,you could add your own code here { if(NULL == s_lwm2m_context) { oc_lwm2m_config(&oc_param); } else if(s_lwm2m_reconnect) { s_lwm2m_reconnect = 0; oc_lwm2m_deconfig(); oc_lwm2m_config(&oc_param); } else { lux++; lux= lux%10000; light.msgid = cn_app_light; light.intensity = htons(lux); oc_lwm2m_report((char *)&light,sizeof(light),1000); ///< report the light message } osal_task_sleep(10*1000); } return ret; }oc_lwm2m_bs_demo.c位于 LiteOS-iot_link/demos。(2)查看设备状态登录IoT平台进入设备管理服务,选择“所有设备”,在设备列表中,点击上报数据的设备,查看设备信息”,验证设备数据上报的情况。图5.3-01查看数据上报结果
-
关于SDK,不知道到底该看哪里学习了?1、在官方github, LiteOS仓库源码下,有端云互通组件的代码,主要是在componets目录下 但是看使用文档 Huawei_LiteOS_SDK_Developer_Guide.md ,里面的描述还是比较旧的,跟实际代码目录不同。 本来是想看到底怎么移植SDK的,但是结果文档里面就直接根据野火的F429讲了下需要修改的代码,描述非常少(见5.6.4章节) 完全也不知道SDK怎么跑起来来的呀,有点晕2、另外还有一个代码仓,LiteOS_Lab,里面的iot_link应该也是SDK,问题就是想问下:学习SDK到底看哪个最好?我想在我自己的板子上从零移植SDK,应该怎么做,有没有具体的教程?
-
SDK更新下来后没有找到Huawei LiteOS 开发指南里介绍到的例程文件,诸如:sample_foo.csample_Dynamic_loading.c等,都没找到。。
-
我在看菊厂柴工的博客《LiteOS下的内存管理》中有写到 > 基于MMU可以玩出很多的花样,但LiteOS运行的SoC一般不具有MMU,也没有为每个应用开启单独的地址空间。关于MMU的内容这里就不深入展开了。后面有空再跟大家一起分享。 既然SoC一般不具有MMU,那么它是怎么解决内存映射的呢?我查阅了官方文档只找到了关于应用堆栈区动态内存管理的相关文档。就我个人的猜想,是通过加载时重定位解决的么?亦或者是在程序编译时就决定了其绝对地址? 可能因为本人只是初涉IoT,所以问的问题可能相对基础,希望论坛大佬可以指点迷津,十分感谢!
-
摘要:本文介绍使用野火开发板通过Agent Tiny SDK的端云互通组件,使用LWm2m协议快速接入华为云平台。通过平台侧、设备侧的开发以及调测过程来了解直接接入物联网平台模式的具体流程,希望对你有所帮助。1 前言本文档主要通过实例讲述如何通过Agent Tiny SDK的端云互通组件,使用LwM2M协议快速接入华为物联网平台。2 Agent Tiny SDK简介Agent Tiny是部署在具备广域网能力、对功耗/存储/计算资源有苛刻限制的终端设备上的轻量级互联互通中间件,您只需调用API接口,便可实现设备快速接入到物联网平台以及数据上报和命令接收等功能。 Agent Tiny SDK是Huawei Agent Tiny软件开发工具包(Software Development Kit),通过Agent Tiny SDK端云互通组件,简单快速地实现与华为物联网平台安全可靠连接,可以大大减少开发周期, 快速构建IoT产品。端云互通组件可以采用MQTT、CoAP和LwM2W协议接入物联网平台。IOT SDK 架构图 图2-013接入物联网平台流程本章分别从 IoT 平台侧和端侧阐述通过端云互通组件接入物联网平台的开发流程,旨在帮助开发者在 IoT 设备上集成端云互通组件,进行IoT应用开发和调测。 端云互通组件接入华为 OceanConnect IoT 云平台默认采用的是以太网方式(即以太网口驱动+LwIP网络协议栈+LwM2M协议+Agent Tiny SDK 对接云平台), 同时也支持WIFI、GSM、NB-IoT等无线方式。OceanConnect 即华为IoT联接管理平台(IoT Connection Management Platform)是面向运营商和企业/行业领域的统一开放云平台, 支持SIM和非SIM场景的各种联接和联接管理。通过开放的APIs,向上集成各种行业应用,向下接入各种传感器、终端和网关,帮助运营商和企业/行业客户实现多种行业终端的快速接入, 多种行业应用的快速集成。华为IoT联接管理平台提供安全可控的全联接管理,使能行业革新,构建IoT生态(本章中提到的IoT平台指OceanConnect)。平台对接信息图3-01设备接入云端可分为直连接入和BS引导接入,如下示意图 图3-02直连接入物联网平台示意图图3-03 BS引导接入物联网平台示意图4直连接入实例(参考)端云互通组件以太网接入实例- 硬件设备:野火STM32F429开发板,调试下载器(J-Link、ST-Link等)、网线、路由器、USB转串口线。说明:本章以野火STM32F429IG开发板为例进行介绍,板子的详细资料可以从http://www.firebbs.cn/forum.php下载。 4.0-01图STM32F429IG_FIRE开发板外设4.0-02 直连模式下整体配置流程4.1平台侧开发使用“开发中心”完成平台侧的开发。开发中心是基于设备管理服务提供的一站式开发工具,帮助开发者快速开发产品(Profile、编解码插件) ,并进行自动化测试,生成测试报告。平台侧配置流程包括:新建项目,新建产品、开发profile,开发编解码插件,注册设备。1环境准备在开发之前,需要提前获取如下信息:开发中心的访问账号/密码,需要向OceanConnect IoT平台申请2新建项目项目是物联网平台提供物联网应用和设备的调测空间,可以根据场景的不同创建不同项目空间分别调测。 在基于开发中心进行物联网开发时,需要根据行业属性创建独立的项目,并在该项目空间内开发物联网产品和应用。创建项目时,物联网平台会分配一个应用ID(接口调用时参数名为appId)作为项目的唯一标识。若应用服务器需要调用物联网平台的API接口进行一些业务处理, 请求中必须携带appId以接入对应的项目空间,鉴权接口携带在Body中,其他接口的appId的值一般携带在Header中。 创建项目后,可以在项目中查看应用服务器和设备的接入地址和端口信息,方便您快速对接应用服务器和设备。 项目被删除后项目内的所有资源,如设备、产品、订阅数据在平台中的信息会被全部删除,并且不可恢复,请谨慎操作。(1)登录物联网平台。(2)进入开发者中心,在我的项目中点击“新建项目”。图4.1-01新建项目(3)在新弹出窗口中,配置项目信息,点击“确定”。配置示例如下图,点击“确定”后,IoT平台会返回项目对应的应用ID和应用密钥,请妥善保存应用密钥,以便于应用服务器接入平台时使用。如果遗忘密钥,需要通过“对接信息”->"重置密钥”进行重置。图4.1-02配置项目说明:如上配置仅为参考举例,具体配置请以现网需求为准。 图4.1-03 项目创建成功3产品开发在物联网平台中,某一类具有相同能力或特征的设备的合集被称为一款产品。产品包含Profile(产品模型)、编解码插件、测试报告等资源, 其中产品信息被记录在Profile中。产品的Profile文件用来描述设备类型和设备服务能力。它定义了设备具备的服务能力,每个服务具备的属性、 命令以及命令参数。在一个项目里最多可以创建20个产品。产品开发最重要的是开发Profile,Profile用于描述设备具备的能力和特性。定义Profile,即在物联网平台构建一款设备的抽象模型,使平台理解该款设备支持的服务、属性、命令等信息。如果设备上报的数据是二进制码流格式,就需要开发对应的编解码插件,用于物联网平台完成二进制格式和JSON格式的转换。 删除产品后,该产品下的Profile、编解码插件等资源将被清空,请谨慎操作。开发中心上提供了多种创建产品的方法。图4.1-04(1)登录IoT平台的开发者中心。(2)进入项目->选择“产品开发”->点击“新建产品”->选择“自定义产品”->点击“自定义产品”。IoT平台提供了产品的Profile模板库,开发者可以根据自己需要,选择合适的模板直接使用。如果在模板库中未找到需要的Profile,再自己定义,示例如下。图4.1-05创建Profile文件说明:如上配置仅为参考举例,具体配置请以现网需求为准。(3) 选择新创建的产品,点击“新建服务”,配置设备的服务能力。可参考“产品开发”->“添加”->“基于系统模板创建”中的产品进行配置。例如新建一个名为LightControl的服务,包含一种属性light(灯亮LUX数)和一种命令(设置灯亮on或者灭off)图4.1-06新建LightControl服务(4)(可选)开发者中心提供了Profile文件的导出功能。选择“产品开发”->选择已创建的产品->点击右上角“导出Profile”,可以对线上开发的Profile文件进行导出。图4.1-07导出Profile文件4开发编解码插件IoT设备和IoT平台之间采用LwM2M协议通信,LwM2M消息的数据为应用层数据,应用层数据的格式由设备厂商自行定义。由于IoT设备对省电要求较高,所以应用层数据一般采用二进制格式。IoT平台在对应用层数据进行协议解析时,会转换成统一的json格式,以方便应用服务器使用。要实现二进制消息与json格式消息的转换,IoT平台需要使用编解码插件。(1)选择“产品开发”->选择已创建的产品->选择“编解码插件开发”,选择“在线编解码插件编辑器”。图4.1-08创建插件(2)点击“新增消息”,配置二进制码流和Profile属性/命令/命令响应的映射关系。图4.1-09开发插件(新增数据上报消息)图4.1-10开发插件(添加字段)图4.1-11开发插件(添加字段图4.1-12开发插件(新建命令下发消息)图4.1-13开发插件(添加字段)编解码插件的开发,即定义:l Profile文件定义的属性/响应在设备上报的二进制码流中的位置,以便于平台对设备上报数据和命令响应进行解码。l Profile文件定义的命令在平台下发的二进制码流中的位置,以便于平台对下发命令进行编码。图4.1-14 二进制码流和Profile文件的映射关系(3)点击右上角“部署”。点击部署后,需要先“保存”插件,之后才开始部署。部署需要等待时间小于60s。图4.1-15保存插件图4.1-16部署插件(4)(可选)开发者中心提供了编解码插件的下载功能。选择“产品开发”->选择已创建的产品->选择“编解码插件开发”,选择“插件管理”,点击“下载”可以对线上开发的编解码插件进行导出。5添加真实&虚拟设备平台通过接入真实&虚拟的设备,对开发的应用和设备进行在线调测,并进行统一的设备管理。(1)选择“设备管理”->“添加真实设备”->选择已创建的产品->输入设备名称和设备标识,并根据业务需求选择是否加密设备。最后点击“确定”。图4.1-17注册设备信息添加设备后,IoT平台会返回设备ID和PSK码,请妥善保存。新添加的设备状态为“离线”。图4.1-18 注册设备4.2设备侧开发直连模式设备侧开发包括: 配置Demo中对接云端设备的信息、编译、运行SDK、数据上报任务与命令下发调测。设备侧开发环境准备在开发之前,需要提前进行如下操作:l 搭建好Eclipse开发工具软件环境l 使用网线将野火STM32F429开发板接入互联网并使用USB转串口线连接开发版的串口1与PCl 获取端云互通组件代码:https://github.com/LiteOS/LiteOS/tree/iot_link配置Demo中对接云端设备的信息1. 开发板的网口通过网线连接到路由器。 2. 设置本地IP。在net_driver.c中修改device接入的局域网的IP地址值。目前demo程序采用的是静态IP地址的方式,如果需要使用DHCP方式,请在main.c中顶部头文件包含之后定义USE_DHCP宏即可。void net_init(void) { /* IP addresses initialization */ IP_ADDRESS[0] = 192; IP_ADDRESS[1] = 168; IP_ADDRESS[2] = 0; IP_ADDRESS[3] = 115; NETMASK_ADDRESS[0] = 255; NETMASK_ADDRESS[1] = 255; NETMASK_ADDRESS[2] = 255; NETMASK_ADDRESS[3] = 0; GATEWAY_ADDRESS[0] = 192; GATEWAY_ADDRESS[1] = 168; GATEWAY_ADDRESS[2] = 0; GATEWAY_ADDRESS[3] = 1; }接口net_init()的作用是完成lwip协议相关的初始化。net_driver.c位于 LiteOS-iot_link/targets/STM32F429IGTx_FIRE/Src。3 网口的mac地址修改。在eth.c中将MAC_ADDR0~MAC_ADDR5修改成真实的mac地址值保证不重复。static int8_t eth_init(struct netif* netif) { HAL_StatusTypeDef hal_eth_init_status; MACAddr[0] = 0x00; MACAddr[1] = 0x80; MACAddr[2] = 0xE1; MACAddr[3] = 0x00; MACAddr[4] = 0x00; MACAddr[5] = 0x00; }注意:接口eth_init()将在步骤2中的net_init()中被调用。eth.c位于 LiteOS-iot_link/targets/STM32F429IGTx_FIRE/Src。4 设置云平台IP以及设备EP Name和PSK。根据开发中心添加的设备信息修改oc_dtls_lwm2m_demo.c中参数。 /**/#define cn_endpoint_id "LedLight001" /**/#define cn_app_server "49.4.85.232" /**/#define cn_app_port "5684" const unsigned char s_app_psk[]={0xd6,0x69,0x42,0x7e,0x2d,0xd4,0x38,0xf1,0xd5,0xb5,0xed,0x32,0x96,0x29,0xe6,0x20};oc_dtls_lwm2m_demo.c位于 LiteOS-iot_link/demos。5编译并运行程序。config.mk位于 LiteOS-iot_link/targets/STM32F429IGTx_FIRE/GCC。修改配置参数为: CONFIG_OS_TYPE := "liteos" CONFIG_ARCH_CPU_TYPE := "armv7-m" CONFIG_SHELL_ENABLE := y CONFIG_STIMER_ENABLE := y CONFIG_DRIVER_ENABLE := y CONFIG_AT_ENABLE := y CONFIG_CJSON_ENABLE := y CONFIG_TCPIP_ENABLE := y CONFIG_TCPIP_TYPE := "lwip_socket" CONFIG_DTLS_ENABLE := y CONFIG_DTLS_TYPE := "mbedtls_psk" CONFIG_MQTT_ENABLE := n CONFIG_MQTT_TYPE := "lite_mqtt" CONFIG_LWM2M_ENABLE := y CONFIG_LWM2M_TYPE := "wakaama_lwm2m" CONFIG_COAP_ENABLE := n CONFIG_COAP_TYPE := "lite_coap" CONFIG_OC_COAP_ENABLE := n CONFIG_OC_COAP_TYPE := "soft" CONFIG_OC_MQTT_ENABLE := n CONFIG_OC_MQTT_TYPE := "soft" CONFIG_OC_LWM2M_ENABLE := y CONFIG_OC_LWM2M_TYPE := "soft" CONFIG_OTA_ENABLE := n CONFIG_PCP_ENABLE := n CONFIG_DEMO_ENABLE := y CONFIG_DEMO_TYPE := "oc_dtls_lwm2m_demo" include $(TOP_DIR)/iot_link/iot.mk6查看设备状态。登录IoT平台开发者中心,选择“设备管理”,在设备列表中查看对应设备的状态。如果状态为“在线”,则表示设备已经成功接入IoT平台。图4.2-01 查看设备状态4.3调测数据上报对于开发者来说,只需在app\_report\_task\_entry\(\)中将其传递给数据上报结构体 light 即可。具体调测过程如下:设备侧执行app_report_task_entry函数,使设备上报数据。oc_lwm2m_demo_dtls.c中的函数app_report_task_entry如下:static int app_report_task_entry() { int ret = -1; int lux = 0; oc_config_param_t oc_param; app_light_intensity_t light; memset(&oc_param,0,sizeof(oc_param)); oc_param.app_server.address = cn_app_server; oc_param.app_server.port = cn_app_port; oc_param.app_server.ep_id = cn_endpoint_id; oc_param.app_server.psk = (char *)s_app_psk; oc_param.app_server.psk_len = sizeof(s_app_psk); oc_param.app_server.psk_id = cn_endpoint_id; oc_param.boot_mode = en_oc_boot_strap_mode_factory; oc_param.rcv_func = app_msg_deal; ret = oc_lwm2m_config(&oc_param); if(ret == 0) //success ,so we could receive and send { //install a dealer for the led message received while(1) //--TODO ,you could add your own code here { lux++; lux= lux%10000; light.msgid = cn_app_light; light.intensity = htons(lux); oc_lwm2m_report((char *)&light,sizeof(light),1000); ///< report the light message osal_task_sleep(10*1000); } } return ret; }oc_dtls_lwm2m_demo.c位于 LiteOS-iot_link/demos。查看设备状态登录IoT平台的开发者中心,在“设备管理”界面的设备列表中,选择上报数据的设备,查看“历史数据”,验证设备数据上报的情况。图4.3-01 使用端云互通组件的IoT设备数据上报业务流程图4.3-02 查看数据上报结果命令下发命令下发一般分为两种形式:立即下发和缓存下发。立即下发: IoT平台立即发送收到的命令,如果设备不在线或者设备没收到指令则下发失败。立即下发适合对命令实时性有要求的场景,比如路灯开关灯,燃气表开关阀。使用立即下发时,应用服务器需要自己保证命令下发的时机。图4.3-03 命令立即下发流程缓存下发: 平台收到命令后放入队列。在设备上线的时候,平台依次下发命令队列中的命令。缓存下发适合对命令实时性要求不高的场景,比如配置水表的参数。缓存下发平台根据设备的省电模式进行不同处理。图4.3-04命令缓存下发流程应用服务器向IoT平台下发命令时,携带参数expireTime(简称TTL,表示最大缓存时间)。如果不带expireTime,则默认expireTime为48小时。expireTime=0:命令立即下发。expireTime>0:命令缓存下发。端云互通组件场景命令下发的调测过程,命令下发步骤如下:(1)登录IoT平台的开发者中心。开发者中心的账号和密码需要向IoT平台服务商申请。(2)在“设备管理”界面的设备列表中,点击接收命令的设备,点击“调试产品”。在弹出应用模拟器界面中选择“命令发送”,配置下发给设备的命令参数。图4.3-05 命令下发在“设备管理”界面的设备列表中,点击接收命令的设备->“历史命令”,查看“状态”栏的显示。图4.3-06 命令下发状态状态说明如下:超期: 表示命令在IoT平台缓存时间超期,未向设备下发。成功: 表示IoT平台已经将命令下发给设备,且收到设备上报的命令执行结果。失败: 表示编解码插件解析为空,或执行结果响应里面有“ERROR CODE”等。超时: 表示IoT平台等待ACK响应超时。取消: 表示应用侧已经取消命令下发。等待: 表示命令在IoT平台缓存,还未下发给设备。已发送: 表示IoT平台已经将命令下发给设备。已送达: 表示IoT平台已经将命令下发给设备,且收到设备返回的ACK消息。
-
端云互通组件-MQTT开发指南(下)摘要:本文介绍使用野火开发板通过Agent Tiny SDK的端云互通组件,使用MQTT协议快速接入华为云平台。通过平台侧、设备侧的开发以及调测过程来了解经BS接入物联网平台模式的具体流程,希望对你有所帮助。1.介绍SDK简介Agent Tiny是部署在具备广域网能力、对功耗/存储/计算资源有苛刻限制的终端设备上的轻量级互联互通中间件,您只需调用API接口,便可实现设备快速接入到物联网平台以及数据上报和命令接收等功能。Agent Tiny SDK是Huawei Agent Tiny软件开发工具包(Software Development Kit),通过Agent Tiny SDK端云互通组件,简单快速地实现与华为物联网平台安全可靠连接,可以大大减少开发周期,快速构建IoT产品。端云互通组件可以采用MQTT、CoAP和LWM2W协议接入物联网平台。Agent Tiny SDK全景图如图1所示。2. 开发环境2.1硬件需求开发计算机、运行win7及以上操作系统野火开发板STM32F429IG、数据线Jlink下载器、网线、USB转串口2.2软件需求IDE(包括GCC编译器、JDK运行环境、make工具、Jlink驱动、Eclipse)串口工具(QCOM-V1.6)实名认证的华为云账号SDK源码3.接入物联网平台流程根据设备中的接入地址,可以将接入物联网平台分为两种模式:直接接入物联网平台模式通过设备发放服务接入物联网平台模式两种接入方式的对比:直接接入物联网平台示意图通过设备发放服务接入物联网凭条示意图4. 直接接入实例 https://bbs.huaweicloud.com/blogs/1435115. 经BS接入实例本章节以LINUX平台通过以太网经BS接入物联网平台为例,详细讲述接入流程。总体操作流程参考下图. 设备发放服务信息参考下表5.1平台侧开发进入物联网平台,选择设备发放->进入设备发放服务。根据上图,依次在设备发放服务中产品导入->设备导入->发放策略->发放设备。设备导入成功后,记住设备标识(nodeid),设备id(deviceid)和密钥(password),这三个信息主要用于对接华为云时的设备鉴权。具体操作参考如下。进入设备发放平台在物联网平台选择“设备发放”,公测期间需要申请公测权限,可在设备发放页面选择申请公测权限并填写相关信息,申请权限通过后,点击“进入设备发放服务”。导入产品在设备发放服务页面选择“产品导入”->从产品中心导入->选择最后一个源机固定端设备导入设备发放服务页面选择“设备导入”->点击页面右上角“单个导入”->弹出导入设备基本信息配置,产品信息选择上一步导入的产品、设置设备标识码、设备名称、访问方式选择“域名”配置发放策略在设备发放服务页面选择“发放策略”->点击“设备名称筛选”->添加实例->在添加实例配置框内填写关键字,关键字为设备导入中的设备名称、选择发放区域、点击“确定”。发放设备选择“设备仓库”->选择“发放设备”->弹出对话框点击“确定”->立即启动启动后,发放状态为已发放5.2设备侧开发设备侧开发前准备l 下载SDK源码。l 获取接入信息(进入物联网平台,在“设备发放 > 设备引导对接信息”页面查看“接入信息”中的“MQTT接入方式”)l Linux平台(准备好GCC编译环境以及Make工具)上传源码到linux平台源码目录如下修改mk文件参考如下内容,修改targets/LINUX/GCC/config.mk CONFIG_OS_TYPE := "linux" CONFIG_ARCH_CPU_TYPE := "x86-64" CONFIG_SHELL_ENABLE := n CONFIG_STIMER_ENABLE := y CONFIG_DRIVER_ENABLE := n CONFIG_AT_ENABLE := n CONFIG_CJSON_ENABLE := y CONFIG_TCPIP_ENABLE := y CONFIG_TCPIP_TYPE := "linux_socket" CONFIG_DTLS_ENABLE := y CONFIG_DTLS_TYPE := "mbedtls_cert" CONFIG_MQTT_ENABLE := y CONFIG_MQTT_TYPE := "paho_mqtt" CONFIG_OC_MQTT_ENABLE := y CONFIG_OC_MQTT_TYPE := "soft" CONFIG_DEMO_ENABLE := y CONFIG_DEMO_TYPE := "oc_tls_mqtt_bs_demo"### 产品逻辑 ###修改接入信息修改demos/oc_tls_mqtt_bs_demo.c的对接信息 #define BS_SERVER_ADDRESS "iot-bs.cn-north-4.myhuaweicloud.com" //设备发放服务提供的MQTT对接地址 #define BS_SERVER_PORT "8883" //设备发放服务提供的MQTT对接端口 #define DEMO_WITH_BOOTSTRAP_NODEID "mqtt_test_001" //设备发放时导入设备的设备标识码 #define DEMO_WITH_BOOTSTRAP_PASSWORD "ecc8dca5dfe4686bc71b" //设备发放时导入设备成功后提供的密钥make编译生成Huawei_LiteOS.elf运行Huawei_LiteOS.elf5.3调测在设备发放服务中选择“设备仓库”,查看设备的引导状态为“引导成功”登录设备管理服务,选择“设备管理”,进入设备管理服务点击下图左下角图标,选择设备-所有设备,可以看到设备状态为“在线”点击设备名称,进入设备详情页面到此调测完成。
-
摘要:本文首先对RISC-V的架构做了简要的介绍,在此基础上实现了LiteOS在RISC-V架构上的适配过程的具体步骤,希望对你有所帮助。1 RISC-V架构简介RISC-V是一个基于精简指令集(RISC)原则的开源指令集架构(ISA)。与大多数指令集相比,RISC-V指令集可以自由地用于任何目的,允许任何人设计、制造和销售RISC-V芯片和软件而不必支付给任何公司专利费。RISC-V指令集的设计考虑了小型、快速、低功耗的现实情况来实做,但并没有对特定的微架构做过度的设计。RISC-V的Spec文档可以在RISC-C官网https://riscv.org/specifications/ 上下载。主要看riscv-privileged.pdf和riscv-spec.pdf。主要精读的内容包括:RV32ICM Instruction Set I:RV32I Base Integer Instruction Set C:Standard Extension for Compressed Instructions M:Standard Extension for Integer Multiplication and DivisionPrivilege LevelsControl and Status Registers (CSRs)Machine-Level ISA在了解通用的RV32架构之后,由于RV32是开源的ISA架构,所以实际芯片都会在此基础上做一些定制化,因此需要再读一下芯片手册,LiteOS的RISC-V架构支持使用的芯片是GD32VF103,请下载GD32VF103 的Spec进行阅览。2 LiteOS支持一种处理器RTOS支持一种新的处理器架构,最主要的修改有以下几个方面:1.启动汇编的适配2.适配系统调度汇编3.Tick的适配4.根据芯片设置系统相关参数5.适配中断管理模块6.编译链接脚本的调整那么,对应到LiteOS,主要修改的目录和文件是:LiteOS_Lab\iot_link\os\liteos\arch\riscv\src中 los_dispatch.S los_hw.c los_hw_tick.c los_hwi.c 和对应芯片target目录下的start.S启动汇编以及ld链接脚本。步骤如下:1. start.SA. 和RISC-V的异常中断处理密切相关,注意向量表的对齐 vector_base: j _start .align 2 .word 0 .word 0 .word osInterrupt #eclic_msip_handler .word 0 .word 0 .word 0 .word osInterrupt #eclic_mtip_handlerB. 设置中断,异常等的入口地址_start0800: /* Set the the NMI base to share with mtvec by setting CSR_MMISC_CTL */ li t0, 0x200 csrs CSR_MMISC_CTL, t0 /* Intial the mtvt*/ la t0, vector_base csrw CSR_MTVT, t0 /* Intial the mtvt2 and enable it*/ la t0, irq_entry csrw CSR_MTVT2, t0 csrs CSR_MTVT2, 0x1 /* Intial the CSR MTVEC for the Trap ane NMI base addr*/ la t0, trap_entry csrw CSR_MTVEC, t0C.设置gp,sp,初始化data和bss section,然后跳转到main函数 .option push .option norelax la gp, __global_pointer$ .option pop la sp, _sp /* Load data section */ la a0, _data_lma la a1, _data la a2, _edata bgeu a1, a2, 2f 1: lw t0, (a0) sw t0, (a1) addi a0, a0, 4 addi a1, a1, 4 bltu a1, a2, 1b 2: /* Clear bss section */ la a0, __bss_start la a1, _end bgeu a0, a1, 2f 1: sw zero, (a0) addi a0, a0, 4 bltu a0, a1, 1b2. 适配系统调度汇编(los_dispatch.s),主要修改函数LOS_StartToRun、LOS_IntLock、LOS_IntUnLock、TaskSwitch等;任务栈的设计,在osTskStackInit中针对RISC-V的寄存器的定义,做出context的设计: pstContext->ra = (UINT32)osTaskExit; pstContext->sp = 0x02020202L; pstContext->gp = 0x03030303L; pstContext->tp = 0x04040404L; pstContext->t0 = 0x05050505L; pstContext->t1 = 0x06060606L; pstContext->t2 = 0x07070707L; pstContext->s0 = 0x08080808L; pstContext->s1 = 0x09090909L; pstContext->a0 = pstTaskCB->uwTaskID; //a0 first argument pstContext->a1 = 0x11111111L; pstContext->a2 = 0x12121212L; pstContext->a3 = 0x13131313L; pstContext->a4 = 0x14141414L; pstContext->a5 = 0x15151515L; pstContext->a6 = 0x16161616L; pstContext->a7 = 0x17171717L; pstContext->s2 = 0x18181818L; pstContext->s3 = 0x19191919L; pstContext->s4 = 0x20202020L; pstContext->s5 = 0x21212121L; pstContext->s6 = 0x22222222L; pstContext->s7 = 0x23232323L; pstContext->s8 = 0x24242424L; pstContext->s9 = 0x25252525L; pstContext->s10 = 0x26262626L; pstContext->s11 = 0x27272727L; pstContext->t3 = 0x28282828L; pstContext->t4 = 0x29292929L; pstContext->t5 = 0x30303030L; pstContext->t6 = 0x31313131L; pstContext->mepc =(UINT32)osTaskEntry;LOS_IntLock的实现: LOS_IntLock: csrr a0, mstatus li t0, 0x08 csrrc zero, mstatus, t0 retLOS_IntUnLock的实现:LOS_IntUnLock: csrr a0, mstatus li t0, 0x08 csrrs zero, mstatus, t0 retTaskSwitch的实现:TaskSwitch: la t0, g_stLosTask lw t1, 0(t0) csrr t2, mscratch sw t2, 0(t1) //Clear the task running bit of pstRunTask. la t0, g_stLosTask lw t1, (t0) lb t2, 0x4(t1) andi t2, t2, OS_TASK_STATUS_NOT_RUNNING sb t2, 0x4(t1) //copy pstNewTask into pstRunTask la t0, g_stLosTask lw t1, 0x4(t0) sw t1, 0x0(t0) //set the task running bit=1 lh t2, 0x4(t1) ori t2, t2, OS_TASK_STATUS_RUNNING sh t2, 0x4(t1) //retireve stack pointer lw sp, (t1) //retrieve the address at which exception happened lw t0, 31 * 4(sp) csrw mepc, t0 li t0, 0x1800 csrs mstatus, t0 //retrieve the registers lw ra, 0 * 4(sp) lw t0, 4 * 4(sp) lw t1, 5 * 4(sp) lw t2, 6 * 4(sp) lw s0, 7 * 4(sp) lw s1, 8 * 4(sp) lw a0, 9 * 4(sp) lw a1, 10 * 4(sp) lw a2, 11 * 4(sp) lw a3, 12 * 4(sp) lw a4, 13 * 4(sp) lw a5, 14 * 4(sp) lw a6, 15 * 4(sp) lw a7, 16 * 4(sp) lw s2, 17 * 4(sp) lw s3, 18 * 4(sp) lw s4, 19 * 4(sp) lw s5, 20 * 4(sp) lw s6, 21 * 4(sp) lw s7, 22 * 4(sp) lw s8, 23 * 4(sp) lw s9, 24 * 4(sp) lw s10, 25 * 4(sp) lw s11, 26 * 4(sp) lw t3, 27 * 4(sp) lw t4, 28 * 4(sp) lw t5, 29 * 4(sp) lw t6, 30 * 4(sp) addi sp, sp, 4 * 32 mret3. Tick的适配osTickStart的启动:MTIMECMP和MTIME寄存器的设定,TIMER中断的使能,TIMER中断处理函数的注册 LITE_OS_SEC_TEXT_INIT UINT32 osTickStart(VOID) { UINT32 uwRet; g_uwCyclesPerTick = OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND; g_ullTickCount = 0; *(UINT64 *)(TIMER_CTRL_ADDR + TIMER_MTIMECMP) = OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND / 4; *(UINT64 *)(TIMER_CTRL_ADDR + TIMER_MTIME) = 0; eclic_irq_enable(CLIC_INT_TMR, 1, 1); LOS_HwiCreate(CLIC_INT_TMR, 3, 0, eclic_mtip_handler, 0); g_bSysTickStart = TRUE; return LOS_OK; }4. 根据芯片设置系统相关参数(时钟频率,tick中断配置,los_config.h系统参数配置(内存池大小、信号量、队列、互斥锁,软件定时器数量等));根据实际开发板的资源和实际使用需求,配置target_config.h的参数和选项。5. 适配中断管理模块,LiteOS的中断向量表由m_pstHwiForm[OS_VECTOR_CNT]数组管理,需要根据芯片配置中断使能,重定向等;A.在los_hwi.c和los_hwi.h中根据实际芯片的中断向量数目和驱动做一些调整B.在entry.S中设计irq_entry的处理,需要注意的是需要单独在irq stack中处理中断嵌套: irq_entry: // -------------> This label will be set to MTVT2 register // Allocate the stack space SAVE_CONTEXT// Save 16 regs //------This special CSR read operation, which is actually use mcause as operand to directly store it to memory csrrwi x0, CSR_PUSHMCAUSE, 17 //------This special CSR read operation, which is actually use mepc as operand to directly store it to memory csrrwi x0, CSR_PUSHMEPC, 18 //------This special CSR read operation, which is actually use Msubm as operand to directly store it to memory csrrwi x0, CSR_PUSHMSUBM, 19 la t0, g_int_cnt lw t1, 0(t0) addi t1, t1, 1 sw t1, 0(t0) li t2, 1 bgtu t1,t2,service_loop csrw mscratch, sp la sp, __irq_stack_topservice_loop://------This special CSR read/write operation, which is actually Claim the CLIC to find its pending highest // ID, if the ID is not 0, then automatically enable the mstatus.MIE, and jump to its vector-entry-label, and // update the link register csrrw ra, CSR_JALMNXTI, ra //RESTORE_CONTEXT_EXCPT_X5 la t0, g_int_cnt lw t1, 0(t0) addi t1, t1, -1 sw t1, 0(t0) bnez t1, _rfi csrr sp, mscratch DISABLE_MIE # Disable interrupts LOAD x5, 19*REGBYTES(sp) csrw CSR_MSUBM, x5 LOAD x5, 18*REGBYTES(sp) csrw CSR_MEPC, x5 LOAD x5, 17*REGBYTES(sp) csrw CSR_MCAUSE, x5 la t0, g_usLosTaskLock lw t1, 0(t0) bnez t1, _rfi la t0, g_stLosTask lw t1, 0x4(t0) lw t2, 0x0(t0) beq t1, t2, _rfi RESTORE_CONTEXT push_reg csrr t0, mepc sw t0, 31*4(sp) csrw mscratch, sp j TaskSwitch_rfi:RESTORE_CONTEXT // Return to regular code mret6. 编译链接脚本的调整几个关键的设置:irq stack内存区域: __stack_size = DEFINED(__stack_size) ? __stack_size : 2K; __irq_stack_size = DEFINED(__irq_stack_size) ? __irq_stack_size : 2K; __heap_size = DEFINED(__heap_size) ? __heap_size : 0xc00;gp初始值的设定:gp用于代码的优化,因为请合理选择__global_pointer的初值: PROVIDE( __global_pointer$ = . + 0x800);堆栈的设定: .stack : ALIGN(0x10) { . += __stack_size; PROVIDE( _sp = . ); . = ALIGN(0x10); PROVIDE( __irq_stack_bottom = . ); . += __irq_stack_size; PROVIDE( __irq_stack_top = . ); } >ram AT>ram .heap : ALIGN(0x10) { PROVIDE( __los_heap_addr_start__ = . ); . = __heap_size; . = __heap_size == 0 ? 0 : ORIGIN(ram) + LENGTH(ram); PROVIDE( __los_heap_addr_end__ = . ); PROVIDE( _heap_end = . ); } >ram AT>ram主要的步骤已经整体讲述了,顺利移植的主要前提条件是对RISC-V处理器架构的全面理解和LiteOS任务调度的设计,所以再次提醒精读riscv-privileged.pdf和riscv-spec.pdf的相关章节。在移植过程中,会遇到很多问题,建议使用IoT Studio的开发调试环境,方便的进行汇编级的单步调试,另外把串口驱动和printf打印调通,也是一种较重要的调试手段。
-
![](https://img-blog.csdnimg.cn/20200202094937735.png#pic_center) # 1. 做实验引发的思考 在学习LiteOS日志打印组件使用的时候,我记录了一篇博客:[atiny_log | LiteOS 物联网操作系统中的日志打印组件使用分享](https://blog.csdn.net/Mculover666/article/details/104076964),关于实验的具体内容,请阅读这篇博客。 在实验时我编写了如下的5行代码: ```c ATINY_LOG(LOG_DEBUG, "This is a LOG_DEBUG Test!\r\n"); ATINY_LOG(LOG_INFO, "This is a LOG_INFO Test!\r\n"); ATINY_LOG(LOG_WARNING, "This is a LOG_WARNING Test!\r\n"); ATINY_LOG(LOG_ERR,"This is a LOG_ERR Test!\r\n"); ATINY_LOG(LOG_FATAL, "This is a LOG_FATAL Test!\r\n"); ``` 串口的输出如下: ![](https://img-blog.csdnimg.cn/20200203081415169.png) 在串口输出的信息中: ① 第一个方括号是该条日志的输出等级:可以用宏定义选择Debug、INFO、WARNING、ERR、FATAL五个等级中的一个; ② 第二个方括号是RTOS在打印信息时的tick值,可以理解为系统当前的时间戳; ③ 最后一个方括号是指定的打印内容; 可让我感到非常疑惑不解的是: 第三个方括号中竟然打印的是**该条打印语句所在的函数名称和所在文件中的位置(行数),并且打印出的行号和实际对应**,这个在实际应用中用来定位问题非常方便: ![](https://img-blog.csdnimg.cn/2020020308204640.png) 经过一番查看源码,我终于探索出程序为什么可以知道并且打印出代码所在位置的~ # 2. 揭晓谜底 其实,这些RTOS系统之所以准确的打印出了代码所在函数及所在位置,不是用于了多么复杂高深的技术,同样也只是在代码里巧妙的利用了C语言的一个不常用知识点 —— **编译器内置宏定义**。 C语言编译器中内置了一些宏定义,这些内置宏定义可以巧妙地帮我们输出非常有用的调试信息,在RTOS的日志打印组件中通常用到了这三个内置宏定义: - `__FILE__`:在源文件中**当前源文件名; - `__FUNCTION__`: 在源文件中**当前函数名; - `__LINE__`:在源代码中**当前源代码行号; 利用这三个宏定义,**使用一行代码即可编写一个最简单的日志打印组件**: ```c #define DEBUG(format,...) printf("[%s:%05d][%s]"format"\r\n", __FILE__, __LINE__, __FUNCTION__) ``` 编写一个小程序测试这个仅有一行代码的日志打印组件: ```c #include #define DEBUG(format,...) printf("[%s:%05d][%s]"format"\r\n", __FILE__, __LINE__, __FUNCTION__) int main(void) { DEBUG("Hello, esay log tools."); return 0; } ``` 编译运行: ![](https://img-blog.csdnimg.cn/20200203084255980.png) 怎么样?所有的信息是不是非常准确?这个仅有一行代码的日志打印组件用起来是不是很爽? # 3. RTOS中的完整日志打印组件 当然,一个完整的日志打印组件不能仅仅靠这一行代码来实现,还需要添加很多功能,比如: - 设置日志输出等级,区分不同的日志输出; - 底层使用自己优化后的printf函数; - 添加宏定义控制输出信息是否启用; - 添加字符输出颜色控制功能,可与日志输出等级对应; - 更多功能,等你探索…… 在LiteOS中,日志打印组件底层使用了该内置宏定义功能,源码如下: ```c #define ATINY_LOG(level, fmt, ...) \ do \ { \ if ((level) >= atiny_get_log_level()) \ { \ (void)atiny_printf("[%s][%u][%s:%d] " fmt "\r\n", \ atiny_get_log_level_name((level)), (uint32_t)osal_sys_time(), __FUNCTION__, __LINE__, ##__VA_ARGS__); \ } \ } while (0) #else #define ATINY_LOG(level, fmt, ...) #endif ``` 而在更多时候,**该功能被用来迅速的输出系统断言信息**,比如在RT-Thread中有这样的一个功能源码: ```c /* assert for developer. */ #ifdef ULOG_ASSERT_ENABLE #define ULOG_ASSERT(EXPR) \ if (!(EXPR)) \ { \ ulog_output(LOG_LVL_ASSERT, LOG_TAG, RT_TRUE, "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); \ ulog_flush(); \ while (1); \ } #else #define ULOG_ASSERT(EXPR) #endif ``` 在TencentOS tiny中也有同样的断言功能源码: ```c #define TOS_ASSERT_AUX(exp, function, line) \ if (!(exp)) { \ tos_kprintln("assert failed: %s %d\n", function, line); \ tos_knl_sched_lock(); \ tos_cpu_int_disable(); \ while (K_TRUE) { \ ; \ } \ } #define TOS_ASSERT(exp) TOS_ASSERT_AUX(exp, __FUNCTION__, __LINE__) ``` **接收更多精彩文章及资源推送,欢迎订阅我的微信公众号:『mculover666』。** ![](https://img-blog.csdnimg.cn/20200202092055136.png)
-
1、如何进行环境配置以及创建工程请看上篇文章Windows10如何安装LiteOS开发环境-QEMU仿真https://bbs.huaweicloud.com/forum/thread-40152-1-1.html2、在工程中添加板子的文件stm32f429i_discovery.h/** ****************************************************************************** * @file stm32f429i_discovery.h * @author MCD Application Team * @brief This file contains definitions for STM32F429I-Discovery Kit LEDs, * push-buttons hardware resources. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32F429I_DISCOVERY_H #define __STM32F429I_DISCOVERY_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h" /** @addtogroup BSP * @{ */ /** @addtogroup STM32F429I_DISCOVERY * @{ */ /** @addtogroup STM32F429I_DISCOVERY_LOW_LEVEL * @{ */ /** @addtogroup STM32F429I_DISCOVERY_LOW_LEVEL_Exported_Types STM32F429I DISCOVERY LOW LEVEL Exported Types * @{ */ typedef enum { LED3 = 0, LED4 = 1 }Led_TypeDef; typedef enum { BUTTON_KEY = 0, }Button_TypeDef; typedef enum { BUTTON_MODE_GPIO = 0, BUTTON_MODE_EXTI = 1 }ButtonMode_TypeDef; /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Exported_Constants STM32F429I DISCOVERY LOW LEVEL Exported Constants * @{ */ /** * @brief Define for STM32F429I_DISCO board */ #if !defined (USE_STM32F429I_DISCO) #define USE_STM32F429I_DISCO #endif /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_LED STM32F429I DISCOVERY LOW LEVEL LED * @{ */ #define LEDn 2 #define LED3_PIN GPIO_PIN_13 #define LED3_GPIO_PORT GPIOG #define LED3_GPIO_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE() #define LED3_GPIO_CLK_DISABLE() __HAL_RCC_GPIOG_CLK_DISABLE() #define LED4_PIN GPIO_PIN_14 #define LED4_GPIO_PORT GPIOG #define LED4_GPIO_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE() #define LED4_GPIO_CLK_DISABLE() __HAL_RCC_GPIOG_CLK_DISABLE() #define LEDx_GPIO_CLK_ENABLE(__INDEX__) do{if((__INDEX__) == 0) LED3_GPIO_CLK_ENABLE(); else \ if((__INDEX__) == 1) LED4_GPIO_CLK_ENABLE(); \ }while(0) #define LEDx_GPIO_CLK_DISABLE(__INDEX__) do{if((__INDEX__) == 0) LED3_GPIO_CLK_DISABLE(); else \ if((__INDEX__) == 1) LED4_GPIO_CLK_DISABLE(); \ }while(0) /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_BUTTON STM32F429I DISCOVERY LOW LEVEL BUTTON * @{ */ #define BUTTONn 1 /** * @brief Wakeup push-button */ #define KEY_BUTTON_PIN GPIO_PIN_0 #define KEY_BUTTON_GPIO_PORT GPIOA #define KEY_BUTTON_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define KEY_BUTTON_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() #define KEY_BUTTON_EXTI_IRQn EXTI0_IRQn #define BUTTONx_GPIO_CLK_ENABLE(__INDEX__) do{if((__INDEX__) == 0) KEY_BUTTON_GPIO_CLK_ENABLE(); \ }while(0) #define BUTTONx_GPIO_CLK_DISABLE(__INDEX__) do{if((__INDEX__) == 0) KEY_BUTTON_GPIO_CLK_DISABLE(); \ }while(0) /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_BUS STM32F429I DISCOVERY LOW LEVEL BUS * @{ */ /* Exported constanIO --------------------------------------------------------*/ #define IO_I2C_ADDRESS 0x82 #define TS_I2C_ADDRESS 0x82 #ifdef EE_M24LR64 #define EEPROM_I2C_ADDRESS_A01 0xA0 #define EEPROM_I2C_ADDRESS_A02 0xA6 #endif /* EE_M24LR64 */ /*############################### I2Cx #######################################*/ /* User can use this section to tailor I2Cx instance used and associated resources */ #define DISCOVERY_I2Cx I2C3 #define DISCOVERY_I2Cx_CLOCK_ENABLE() __HAL_RCC_I2C3_CLK_ENABLE() #define DISCOVERY_I2Cx_FORCE_RESET() __HAL_RCC_I2C3_FORCE_RESET() #define DISCOVERY_I2Cx_RELEASE_RESET() __HAL_RCC_I2C3_RELEASE_RESET() #define DISCOVERY_I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define DISCOVERY_I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define DISCOVERY_I2Cx_SDA_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE() /* Definition for DISCO I2Cx Pins */ #define DISCOVERY_I2Cx_SCL_PIN GPIO_PIN_8 #define DISCOVERY_I2Cx_SCL_GPIO_PORT GPIOA #define DISCOVERY_I2Cx_SCL_SDA_AF GPIO_AF4_I2C3 #define DISCOVERY_I2Cx_SDA_PIN GPIO_PIN_9 #define DISCOVERY_I2Cx_SDA_GPIO_PORT GPIOC /* Definition for IOE I2Cx's NVIC */ #define DISCOVERY_I2Cx_EV_IRQn I2C3_EV_IRQn #define DISCOVERY_I2Cx_ER_IRQn I2C3_ER_IRQn /* I2C clock speed configuration (in Hz) WARNING: Make sure that this define is not already declared in other files. It can be used in parallel by other modules. */ #ifndef BSP_I2C_SPEED #define BSP_I2C_SPEED 100000 #endif /* BSP_I2C_SPEED */ #define I2Cx_TIMEOUT_MAX 0x3000 /*<! The value of the maximal timeout for I2C waiting loops */ /*############################### SPIx #######################################*/ #define DISCOVERY_SPIx SPI5 #define DISCOVERY_SPIx_CLK_ENABLE() __HAL_RCC_SPI5_CLK_ENABLE() #define DISCOVERY_SPIx_GPIO_PORT GPIOF /* GPIOF */ #define DISCOVERY_SPIx_AF GPIO_AF5_SPI5 #define DISCOVERY_SPIx_GPIO_CLK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() #define DISCOVERY_SPIx_GPIO_CLK_DISABLE() __HAL_RCC_GPIOF_CLK_DISABLE() #define DISCOVERY_SPIx_SCK_PIN GPIO_PIN_7 /* PF.07 */ #define DISCOVERY_SPIx_MISO_PIN GPIO_PIN_8 /* PF.08 */ #define DISCOVERY_SPIx_MOSI_PIN GPIO_PIN_9 /* PF.09 */ /* Maximum Timeout values for flags waiting loops. These timeouts are not based on accurate values, they just guarantee that the application will not remain stuck if the SPI communication is corrupted. You may modify these timeout values depending on CPU frequency and application conditions (interrupts routines ...). */ #define SPIx_TIMEOUT_MAX ((uint32_t)0x1000) /*################################ IOE #######################################*/ /** * @brief IOE Control pin */ /* Definition for external IT for STMPE811 */ #define STMPE811_INT_PIN GPIO_PIN_15 #define STMPE811_INT_GPIO_PORT GPIOA #define STMPE811_INT_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define STMPE811_INT_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() #define STMPE811_INT_EXTI EXTI15_10_IRQn #define STMPE811_INT_EXTIHandler EXTI15_10_IRQHandler /*################################ LCD #######################################*/ /* Chip Select macro definition */ #define LCD_CS_LOW() HAL_GPIO_WritePin(LCD_NCS_GPIO_PORT, LCD_NCS_PIN, GPIO_PIN_RESET) #define LCD_CS_HIGH() HAL_GPIO_WritePin(LCD_NCS_GPIO_PORT, LCD_NCS_PIN, GPIO_PIN_SET) /* Set WRX High to send data */ #define LCD_WRX_LOW() HAL_GPIO_WritePin(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, GPIO_PIN_RESET) #define LCD_WRX_HIGH() HAL_GPIO_WritePin(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, GPIO_PIN_SET) /* Set WRX High to send data */ #define LCD_RDX_LOW() HAL_GPIO_WritePin(LCD_RDX_GPIO_PORT, LCD_RDX_PIN, GPIO_PIN_RESET) #define LCD_RDX_HIGH() HAL_GPIO_WritePin(LCD_RDX_GPIO_PORT, LCD_RDX_PIN, GPIO_PIN_SET) /** * @brief LCD Control pin */ #define LCD_NCS_PIN GPIO_PIN_2 #define LCD_NCS_GPIO_PORT GPIOC #define LCD_NCS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define LCD_NCS_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE() /** * @} */ /** * @brief LCD Command/data pin */ #define LCD_WRX_PIN GPIO_PIN_13 #define LCD_WRX_GPIO_PORT GPIOD #define LCD_WRX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() #define LCD_WRX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOD_CLK_DISABLE() #define LCD_RDX_PIN GPIO_PIN_12 #define LCD_RDX_GPIO_PORT GPIOD #define LCD_RDX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE() #define LCD_RDX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOD_CLK_DISABLE() /*################################ GYROSCOPE #################################*/ /* Read/Write command */ #define READWRITE_CMD ((uint8_t)0x80) /* Multiple byte read/write command */ #define MULTIPLEBYTE_CMD ((uint8_t)0x40) /* Dummy Byte Send by the SPI Master device in order to generate the Clock to the Slave device */ #define DUMMY_BYTE ((uint8_t)0x00) /* Chip Select macro definition */ #define GYRO_CS_LOW() HAL_GPIO_WritePin(GYRO_CS_GPIO_PORT, GYRO_CS_PIN, GPIO_PIN_RESET) #define GYRO_CS_HIGH() HAL_GPIO_WritePin(GYRO_CS_GPIO_PORT, GYRO_CS_PIN, GPIO_PIN_SET) /** * @brief GYROSCOPE SPI Interface pins */ #define GYRO_CS_PIN GPIO_PIN_1 /* PC.01 */ #define GYRO_CS_GPIO_PORT GPIOC /* GPIOC */ #define GYRO_CS_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define GYRO_CS_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE() #define GYRO_INT_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define GYRO_INT_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() #define GYRO_INT_GPIO_PORT GPIOA /* GPIOA */ #define GYRO_INT1_PIN GPIO_PIN_1 /* PA.01 */ #define GYRO_INT1_EXTI_IRQn EXTI1_IRQn #define GYRO_INT2_PIN GPIO_PIN_2 /* PA.02 */ #define GYRO_INT2_EXTI_IRQn EXTI2_IRQn /** * @} */ #ifdef EE_M24LR64 /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_I2C_EEPROM STM32F429I DISCOVERY LOW LEVEL I2C EEPROM * @{ */ /** * @brief I2C EEPROM Interface pins */ #define EEPROM_I2C_DMA DMA1 #define EEPROM_I2C_DMA_CHANNEL DMA_CHANNEL_3 #define EEPROM_I2C_DMA_STREAM_TX DMA1_Stream4 #define EEPROM_I2C_DMA_STREAM_RX DMA1_Stream2 #define EEPROM_I2C_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE() #define EEPROM_I2C_DMA_TX_IRQn DMA1_Stream4_IRQn #define EEPROM_I2C_DMA_RX_IRQn DMA1_Stream2_IRQn #define EEPROM_I2C_DMA_TX_IRQHandler DMA1_Stream4_IRQHandler #define EEPROM_I2C_DMA_RX_IRQHandler DMA1_Stream2_IRQHandler #define EEPROM_I2C_DMA_PREPRIO 0x0F /** * @} */ #endif /* EE_M24LR64 */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Exported_Macros STM32F429I DISCOVERY LOW LEVEL Exported Macros * @{ */ /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Exported_Functions STM32F429I DISCOVERY LOW LEVEL Exported Functions * @{ */ uint32_t BSP_GetVersion(void); void BSP_LED_Init(Led_TypeDef Led); void BSP_LED_On(Led_TypeDef Led); void BSP_LED_Off(Led_TypeDef Led); void BSP_LED_Toggle(Led_TypeDef Led); void BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode); uint32_t BSP_PB_GetState(Button_TypeDef Button); /** * @} */ /** * @} */ /** * @} */ /** * @} */ #ifdef __cplusplus } #endif #endif /* __STM32F429I_DISCOVERY_H */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/stm32f429i_discovery.c/** ****************************************************************************** * @file stm32f429i_discovery.c * @author MCD Application Team * @brief This file provides set of firmware functions to manage Leds and * push-button available on STM32F429I-Discovery Kit from STMicroelectronics. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2017 STMicroelectronics</center></h2> * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f429i_discovery.h" /** @defgroup BSP BSP * @{ */ /** @defgroup STM32F429I_DISCOVERY STM32F429I DISCOVERY * @{ */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL STM32F429I DISCOVERY LOW LEVEL * @brief This file provides set of firmware functions to manage Leds and push-button * available on STM32F429I-Discovery Kit from STMicroelectronics. * @{ */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Private_TypesDefinitions STM32F429I DISCOVERY LOW LEVEL Private TypesDefinitions * @{ */ /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Private_Defines STM32F429I DISCOVERY LOW LEVEL Private Defines * @{ */ /** * @brief STM32F429I DISCO BSP Driver version number V2.1.6 */ #define __STM32F429I_DISCO_BSP_VERSION_MAIN (0x02) /*!< [31:24] main version */ #define __STM32F429I_DISCO_BSP_VERSION_SUB1 (0x01) /*!< [23:16] sub1 version */ #define __STM32F429I_DISCO_BSP_VERSION_SUB2 (0x06) /*!< [15:8] sub2 version */ #define __STM32F429I_DISCO_BSP_VERSION_RC (0x00) /*!< [7:0] release candidate */ #define __STM32F429I_DISCO_BSP_VERSION ((__STM32F429I_DISCO_BSP_VERSION_MAIN << 24)\ |(__STM32F429I_DISCO_BSP_VERSION_SUB1 << 16)\ |(__STM32F429I_DISCO_BSP_VERSION_SUB2 << 8 )\ |(__STM32F429I_DISCO_BSP_VERSION_RC)) /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Private_Macros STM32F429I DISCOVERY LOW LEVEL Private Macros * @{ */ /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Private_Variables STM32F429I DISCOVERY LOW LEVEL Private Variables * @{ */ GPIO_TypeDef* GPIO_PORT[LEDn] = {LED3_GPIO_PORT, LED4_GPIO_PORT}; const uint16_t GPIO_PIN[LEDn] = {LED3_PIN, LED4_PIN}; GPIO_TypeDef* BUTTON_PORT[BUTTONn] = {KEY_BUTTON_GPIO_PORT}; const uint16_t BUTTON_PIN[BUTTONn] = {KEY_BUTTON_PIN}; const uint8_t BUTTON_IRQn[BUTTONn] = {KEY_BUTTON_EXTI_IRQn}; uint32_t I2cxTimeout = I2Cx_TIMEOUT_MAX; /*<! Value of Timeout when I2C communication fails */ uint32_t SpixTimeout = SPIx_TIMEOUT_MAX; /*<! Value of Timeout when SPI communication fails */ I2C_HandleTypeDef I2cHandle; static SPI_HandleTypeDef SpiHandle; static uint8_t Is_LCD_IO_Initialized = 0; /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Private_FunctionPrototypes STM32F429I DISCOVERY LOW LEVEL Private FunctionPrototypes * @{ */ /* I2Cx bus function */ static void I2Cx_Init(void); static void I2Cx_ITConfig(void); static void I2Cx_WriteData(uint8_t Addr, uint8_t Reg, uint8_t Value); static void I2Cx_WriteBuffer(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length); static uint8_t I2Cx_ReadData(uint8_t Addr, uint8_t Reg); static uint8_t I2Cx_ReadBuffer(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length); static void I2Cx_Error(void); static void I2Cx_MspInit(I2C_HandleTypeDef *hi2c); #ifdef EE_M24LR64 static HAL_StatusTypeDef I2Cx_WriteBufferDMA(uint8_t Addr, uint16_t Reg, uint8_t *pBuffer, uint16_t Length); static HAL_StatusTypeDef I2Cx_ReadBufferDMA(uint8_t Addr, uint16_t Reg, uint8_t *pBuffer, uint16_t Length); static HAL_StatusTypeDef I2Cx_IsDeviceReady(uint16_t DevAddress, uint32_t Trials); #endif /* EE_M24LR64 */ /* SPIx bus function */ static void SPIx_Init(void); static void SPIx_Write(uint16_t Value); static uint32_t SPIx_Read(uint8_t ReadSize); static uint8_t SPIx_WriteRead(uint8_t Byte); static void SPIx_Error(void); static void SPIx_MspInit(SPI_HandleTypeDef *hspi); /* Link function for LCD peripheral */ void LCD_IO_Init(void); void LCD_IO_WriteData(uint16_t RegValue); void LCD_IO_WriteReg(uint8_t Reg); uint32_t LCD_IO_ReadData(uint16_t RegValue, uint8_t ReadSize); void LCD_Delay(uint32_t delay); /* IOExpander IO functions */ void IOE_Init(void); void IOE_ITConfig(void); void IOE_Delay(uint32_t Delay); void IOE_Write(uint8_t Addr, uint8_t Reg, uint8_t Value); uint8_t IOE_Read(uint8_t Addr, uint8_t Reg); uint16_t IOE_ReadMultiple(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length); void IOE_WriteMultiple(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length); /* Link function for GYRO peripheral */ void GYRO_IO_Init(void); void GYRO_IO_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite); void GYRO_IO_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead); #ifdef EE_M24LR64 /* Link function for I2C EEPROM peripheral */ void EEPROM_IO_Init(void); HAL_StatusTypeDef EEPROM_IO_WriteData(uint16_t DevAddress, uint16_t MemAddress, uint8_t* pBuffer, uint32_t BufferSize); HAL_StatusTypeDef EEPROM_IO_ReadData(uint16_t DevAddress, uint16_t MemAddress, uint8_t* pBuffer, uint32_t BufferSize); HAL_StatusTypeDef EEPROM_IO_IsDeviceReady(uint16_t DevAddress, uint32_t Trials); #endif /* EE_M24LR64 */ /** * @} */ /** @defgroup STM32F429I_DISCOVERY_LOW_LEVEL_Private_Functions STM32F429I DISCOVERY LOW LEVEL Private Functions * @{ */ /** * @brief This method returns the STM32F429I DISCO BSP Driver revision * @retval version: 0xXYZR (8bits for each decimal, R for RC) */ uint32_t BSP_GetVersion(void) { return __STM32F429I_DISCO_BSP_VERSION; } /** * @brief Configures LED GPIO. * @param Led: Specifies the Led to be configured. * This parameter can be one of following parameters: * @arg LED3 * @arg LED4 */ void BSP_LED_Init(Led_TypeDef Led) { GPIO_InitTypeDef GPIO_InitStruct; /* Enable the GPIO_LED Clock */ LEDx_GPIO_CLK_ENABLE(Led); /* Configure the GPIO_LED pin */ GPIO_InitStruct.Pin = GPIO_PIN[Led]; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(GPIO_PORT[Led], &GPIO_InitStruct); HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led], GPIO_PIN_RESET); } /** * @brief Turns selected LED On. * @param Led: Specifies the Led to be set on. * This parameter can be one of following parameters: * @arg LED3 * @arg LED4 */ void BSP_LED_On(Led_TypeDef Led) { HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led], GPIO_PIN_SET); } /** * @brief Turns selected LED Off. * @param Led: Specifies the Led to be set off. * This parameter can be one of following parameters: * @arg LED3 * @arg LED4 */ void BSP_LED_Off(Led_TypeDef Led) { HAL_GPIO_WritePin(GPIO_PORT[Led], GPIO_PIN[Led], GPIO_PIN_RESET); } /** * @brief Toggles the selected LED. * @param Led: Specifies the Led to be toggled. * This parameter can be one of following parameters: * @arg LED3 * @arg LED4 */ void BSP_LED_Toggle(Led_TypeDef Led) { HAL_GPIO_TogglePin(GPIO_PORT[Led], GPIO_PIN[Led]); } /** * @brief Configures Button GPIO and EXTI Line. * @param Button: Specifies the Button to be configured. * This parameter should be: BUTTON_KEY * @param ButtonMode: Specifies Button mode. * This parameter can be one of following parameters: * @arg BUTTON_MODE_GPIO: Button will be used as simple IO * @arg BUTTON_MODE_EXTI: Button will be connected to EXTI line with interrupt * generation capability */ void BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode) { GPIO_InitTypeDef GPIO_InitStruct; /* Enable the BUTTON Clock */ BUTTONx_GPIO_CLK_ENABLE(Button); if (ButtonMode == BUTTON_MODE_GPIO) { /* Configure Button pin as input */ GPIO_InitStruct.Pin = BUTTON_PIN[Button]; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(BUTTON_PORT[Button], &GPIO_InitStruct); } if (ButtonMode == BUTTON_MODE_EXTI) { /* Configure Button pin as input with External interrupt */ GPIO_InitStruct.Pin = BUTTON_PIN[Button]; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; HAL_GPIO_Init(BUTTON_PORT[Button], &GPIO_InitStruct); /* Enable and set Button EXTI Interrupt to the lowest priority */ HAL_NVIC_SetPriority((IRQn_Type)(BUTTON_IRQn[Button]), 0x0F, 0x00); HAL_NVIC_EnableIRQ((IRQn_Type)(BUTTON_IRQn[Button])); } } /** * @brief Returns the selected Button state. * @param Button: Specifies the Button to be checked. * This parameter should be: BUTTON_KEY * @retval The Button GPIO pin value. */ uint32_t BSP_PB_GetState(Button_TypeDef Button) { return HAL_GPIO_ReadPin(BUTTON_PORT[Button], BUTTON_PIN[Button]); } /******************************************************************************* BUS OPERATIONS *******************************************************************************/ /******************************* I2C Routines *********************************/ /** * @brief I2Cx MSP Initialization * @param hi2c: I2C handle */ static void I2Cx_MspInit(I2C_HandleTypeDef *hi2c) { GPIO_InitTypeDef GPIO_InitStruct; #ifdef EE_M24LR64 static DMA_HandleTypeDef hdma_tx; static DMA_HandleTypeDef hdma_rx; I2C_HandleTypeDef* pI2cHandle; pI2cHandle = &I2cHandle; #endif /* EE_M24LR64 */ if (hi2c->Instance == DISCOVERY_I2Cx) { /* Configure the GPIOs ---------------------------------------------------*/ /* Enable GPIO clock */ DISCOVERY_I2Cx_SDA_GPIO_CLK_ENABLE(); DISCOVERY_I2Cx_SCL_GPIO_CLK_ENABLE(); /* Configure I2C Tx as alternate function */ GPIO_InitStruct.Pin = DISCOVERY_I2Cx_SCL_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = DISCOVERY_I2Cx_SCL_SDA_AF; HAL_GPIO_Init(DISCOVERY_I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct); /* Configure I2C Rx as alternate function */ GPIO_InitStruct.Pin = DISCOVERY_I2Cx_SDA_PIN; HAL_GPIO_Init(DISCOVERY_I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct); /* Configure the Discovery I2Cx peripheral -------------------------------*/ /* Enable I2C3 clock */ DISCOVERY_I2Cx_CLOCK_ENABLE(); /* Force the I2C Peripheral Clock Reset */ DISCOVERY_I2Cx_FORCE_RESET(); /* Release the I2C Peripheral Clock Reset */ DISCOVERY_I2Cx_RELEASE_RESET(); /* Enable and set Discovery I2Cx Interrupt to the lowest priority */ HAL_NVIC_SetPriority(DISCOVERY_I2Cx_EV_IRQn, 0x0F, 0); HAL_NVIC_EnableIRQ(DISCOVERY_I2Cx_EV_IRQn); /* Enable and set Discovery I2Cx Interrupt to the lowest priority */ HAL_NVIC_SetPriority(DISCOVERY_I2Cx_ER_IRQn, 0x0F, 0); HAL_NVIC_EnableIRQ(DISCOVERY_I2Cx_ER_IRQn); #ifdef EE_M24LR64 /* I2C DMA TX and RX channels configuration */ /* Enable the DMA clock */ EEPROM_I2C_DMA_CLK_ENABLE(); /* Configure the DMA stream for the EE I2C peripheral TX direction */ /* Configure the DMA Stream */ hdma_tx.Instance = EEPROM_I2C_DMA_STREAM_TX; /* Set the parameters to be configured */ hdma_tx.Init.Channel = EEPROM_I2C_DMA_CHANNEL; hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_tx.Init.Mode = DMA_NORMAL; hdma_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH; hdma_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE; hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Associate the initilalized hdma_tx handle to the the pI2cHandle handle */ __HAL_LINKDMA(pI2cHandle, hdmatx, hdma_tx); /* Configure the DMA Stream */ HAL_DMA_Init(&hdma_tx); /* Configure and enable I2C DMA TX Channel interrupt */ HAL_NVIC_SetPriority((IRQn_Type)(EEPROM_I2C_DMA_TX_IRQn), EEPROM_I2C_DMA_PREPRIO, 0); HAL_NVIC_EnableIRQ((IRQn_Type)(EEPROM_I2C_DMA_TX_IRQn)); /* Configure the DMA stream for the EE I2C peripheral TX direction */ /* Configure the DMA Stream */ hdma_rx.Instance = EEPROM_I2C_DMA_STREAM_RX; /* Set the parameters to be configured */ hdma_rx.Init.Channel = EEPROM_I2C_DMA_CHANNEL; hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_rx.Init.Mode = DMA_NORMAL; hdma_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH; hdma_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_rx.Init.MemBurst = DMA_MBURST_SINGLE; hdma_rx.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Associate the initilalized hdma_rx handle to the the pI2cHandle handle*/ __HAL_LINKDMA(pI2cHandle, hdmarx, hdma_rx); /* Configure the DMA Stream */ HAL_DMA_Init(&hdma_rx); /* Configure and enable I2C DMA RX Channel interrupt */ HAL_NVIC_SetPriority((IRQn_Type)(EEPROM_I2C_DMA_RX_IRQn), EEPROM_I2C_DMA_PREPRIO, 0); HAL_NVIC_EnableIRQ((IRQn_Type)(EEPROM_I2C_DMA_RX_IRQn)); #endif /* EE_M24LR64 */ } } /** * @brief I2Cx Bus initialization. */ static void I2Cx_Init(void) { if(HAL_I2C_GetState(&I2cHandle) == HAL_I2C_STATE_RESET) { I2cHandle.Instance = DISCOVERY_I2Cx; I2cHandle.Init.ClockSpeed = BSP_I2C_SPEED; I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; I2cHandle.Init.OwnAddress1 = 0; I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; I2cHandle.Init.OwnAddress2 = 0; I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; /* Init the I2C */ I2Cx_MspInit(&I2cHandle); HAL_I2C_Init(&I2cHandle); } } /** * @brief Configures Interruption pin for I2C communication. */ static void I2Cx_ITConfig(void) { GPIO_InitTypeDef GPIO_InitStruct; /* Enable the GPIO EXTI Clock */ STMPE811_INT_CLK_ENABLE(); GPIO_InitStruct.Pin = STMPE811_INT_PIN; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; HAL_GPIO_Init(STMPE811_INT_GPIO_PORT, &GPIO_InitStruct); /* Enable and set GPIO EXTI Interrupt to the highest priority */ HAL_NVIC_SetPriority((IRQn_Type)(STMPE811_INT_EXTI), 0x0F, 0x00); HAL_NVIC_EnableIRQ((IRQn_Type)(STMPE811_INT_EXTI)); } /** * @brief Writes a value in a register of the device through BUS. * @param Addr: Device address on BUS Bus. * @param Reg: The target register address to write * @param Value: The target register value to be written */ static void I2Cx_WriteData(uint8_t Addr, uint8_t Reg, uint8_t Value) { HAL_StatusTypeDef status = HAL_OK; status = HAL_I2C_Mem_Write(&I2cHandle, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, &Value, 1, I2cxTimeout); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ I2Cx_Error(); } } /** * @brief Writes a value in a register of the device through BUS. * @param Addr: Device address on BUS Bus. * @param Reg: The target register address to write * @param pBuffer: The target register value to be written * @param Length: buffer size to be written */ static void I2Cx_WriteBuffer(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; status = HAL_I2C_Mem_Write(&I2cHandle, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, pBuffer, Length, I2cxTimeout); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ I2Cx_Error(); } } /** * @brief Reads a register of the device through BUS. * @param Addr: Device address on BUS Bus. * @param Reg: The target register address to write * @retval Data read at register address */ static uint8_t I2Cx_ReadData(uint8_t Addr, uint8_t Reg) { HAL_StatusTypeDef status = HAL_OK; uint8_t value = 0; status = HAL_I2C_Mem_Read(&I2cHandle, Addr, Reg, I2C_MEMADD_SIZE_8BIT, &value, 1, I2cxTimeout); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ I2Cx_Error(); } return value; } /** * @brief Reads multiple data on the BUS. * @param Addr: I2C Address * @param Reg: Reg Address * @param pBuffer: pointer to read data buffer * @param Length: length of the data * @retval 0 if no problems to read multiple data */ static uint8_t I2Cx_ReadBuffer(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; status = HAL_I2C_Mem_Read(&I2cHandle, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, pBuffer, Length, I2cxTimeout); /* Check the communication status */ if(status == HAL_OK) { return 0; } else { /* Re-Initialize the BUS */ I2Cx_Error(); return 1; } } #ifdef EE_M24LR64 /** * @brief Writes a value in a register of the device through BUS in using DMA mode. * @param Addr: Device address on BUS Bus. * @param Reg: The target register address to write * @param pBuffer: The target register value to be written * @param Length: buffer size to be written * @retval HAL status */ static HAL_StatusTypeDef I2Cx_WriteBufferDMA(uint8_t Addr, uint16_t Reg, uint8_t *pBuffer, uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; status = HAL_I2C_Mem_Write_DMA(&I2cHandle, Addr, Reg, I2C_MEMADD_SIZE_16BIT, pBuffer, Length); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ I2Cx_Error(); } return status; } /** * @brief Reads multiple data on the BUS in using DMA mode. * @param Addr: I2C Address * @param Reg: Reg Address * @param pBuffer: pointer to read data buffer * @param Length: length of the data * @retval HAL status */ static HAL_StatusTypeDef I2Cx_ReadBufferDMA(uint8_t Addr, uint16_t Reg, uint8_t *pBuffer, uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; status = HAL_I2C_Mem_Read_DMA(&I2cHandle, Addr, Reg, I2C_MEMADD_SIZE_16BIT, pBuffer, Length); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ I2Cx_Error(); } return status; } /** * @brief Checks if target device is ready for communication. * @note This function is used with Memory devices * @param DevAddress: Target device address * @param Trials: Number of trials * @retval HAL status */ static HAL_StatusTypeDef I2Cx_IsDeviceReady(uint16_t DevAddress, uint32_t Trials) { return (HAL_I2C_IsDeviceReady(&I2cHandle, DevAddress, Trials, I2cxTimeout)); } #endif /* EE_M24LR64 */ /** * @brief I2Cx error treatment function */ static void I2Cx_Error(void) { /* De-initialize the SPI communication BUS */ HAL_I2C_DeInit(&I2cHandle); /* Re-Initialize the SPI communication BUS */ I2Cx_Init(); } /******************************* SPI Routines *********************************/ /** * @brief SPIx Bus initialization */ static void SPIx_Init(void) { if(HAL_SPI_GetState(&SpiHandle) == HAL_SPI_STATE_RESET) { /* SPI configuration -----------------------------------------------------*/ SpiHandle.Instance = DISCOVERY_SPIx; /* SPI baudrate is set to 5.6 MHz (PCLK2/SPI_BaudRatePrescaler = 90/16 = 5.625 MHz) to verify these constraints: - ILI9341 LCD SPI interface max baudrate is 10MHz for write and 6.66MHz for read - l3gd20 SPI interface max baudrate is 10MHz for write/read - PCLK2 frequency is set to 90 MHz */ SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; /* On STM32F429I-Discovery, LCD ID cannot be read then keep a common configuration */ /* for LCD and GYRO (SPI_DIRECTION_2LINES) */ /* Note: To read a register a LCD, SPI_DIRECTION_1LINE should be set */ SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; SpiHandle.Init.CRCPolynomial = 7; SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; SpiHandle.Init.NSS = SPI_NSS_SOFT; SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED; SpiHandle.Init.Mode = SPI_MODE_MASTER; SPIx_MspInit(&SpiHandle); HAL_SPI_Init(&SpiHandle); } } /** * @brief Reads 4 bytes from device. * @param ReadSize: Number of bytes to read (max 4 bytes) * @retval Value read on the SPI */ static uint32_t SPIx_Read(uint8_t ReadSize) { HAL_StatusTypeDef status = HAL_OK; uint32_t readvalue; status = HAL_SPI_Receive(&SpiHandle, (uint8_t*) &readvalue, ReadSize, SpixTimeout); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ SPIx_Error(); } return readvalue; } /** * @brief Writes a byte to device. * @param Value: value to be written */ static void SPIx_Write(uint16_t Value) { HAL_StatusTypeDef status = HAL_OK; status = HAL_SPI_Transmit(&SpiHandle, (uint8_t*) &Value, 1, SpixTimeout); /* Check the communication status */ if(status != HAL_OK) { /* Re-Initialize the BUS */ SPIx_Error(); } } /** * @brief Sends a Byte through the SPI interface and return the Byte received * from the SPI bus. * @param Byte: Byte send. * @retval The received byte value */ static uint8_t SPIx_WriteRead(uint8_t Byte) { uint8_t receivedbyte = 0; /* Send a Byte through the SPI peripheral */ /* Read byte from the SPI bus */ if(HAL_SPI_TransmitReceive(&SpiHandle, (uint8_t*) &Byte, (uint8_t*) &receivedbyte, 1, SpixTimeout) != HAL_OK) { SPIx_Error(); } return receivedbyte; } /** * @brief SPIx error treatment function. */ static void SPIx_Error(void) { /* De-initialize the SPI communication BUS */ HAL_SPI_DeInit(&SpiHandle); /* Re- Initialize the SPI communication BUS */ SPIx_Init(); } /** * @brief SPI MSP Init. * @param hspi: SPI handle */ static void SPIx_MspInit(SPI_HandleTypeDef *hspi) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPIx clock */ DISCOVERY_SPIx_CLK_ENABLE(); /* Enable DISCOVERY_SPI GPIO clock */ DISCOVERY_SPIx_GPIO_CLK_ENABLE(); /* configure SPI SCK, MOSI and MISO */ GPIO_InitStructure.Pin = (DISCOVERY_SPIx_SCK_PIN | DISCOVERY_SPIx_MOSI_PIN | DISCOVERY_SPIx_MISO_PIN); GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Pull = GPIO_PULLDOWN; GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM; GPIO_InitStructure.Alternate = DISCOVERY_SPIx_AF; HAL_GPIO_Init(DISCOVERY_SPIx_GPIO_PORT, &GPIO_InitStructure); } /********************************* LINK LCD ***********************************/ /** * @brief Configures the LCD_SPI interface. */ void LCD_IO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; if(Is_LCD_IO_Initialized == 0) { Is_LCD_IO_Initialized = 1; /* Configure NCS in Output Push-Pull mode */ LCD_WRX_GPIO_CLK_ENABLE(); GPIO_InitStructure.Pin = LCD_WRX_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(LCD_WRX_GPIO_PORT, &GPIO_InitStructure); LCD_RDX_GPIO_CLK_ENABLE(); GPIO_InitStructure.Pin = LCD_RDX_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(LCD_RDX_GPIO_PORT, &GPIO_InitStructure); /* Configure the LCD Control pins ----------------------------------------*/ LCD_NCS_GPIO_CLK_ENABLE(); /* Configure NCS in Output Push-Pull mode */ GPIO_InitStructure.Pin = LCD_NCS_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(LCD_NCS_GPIO_PORT, &GPIO_InitStructure); /* Set or Reset the control line */ LCD_CS_LOW(); LCD_CS_HIGH(); SPIx_Init(); } } /** * @brief Writes register value. */ void LCD_IO_WriteData(uint16_t RegValue) { /* Set WRX to send data */ LCD_WRX_HIGH(); /* Reset LCD control line(/CS) and Send data */ LCD_CS_LOW(); SPIx_Write(RegValue); /* Deselect: Chip Select high */ LCD_CS_HIGH(); } /** * @brief Writes register address. */ void LCD_IO_WriteReg(uint8_t Reg) { /* Reset WRX to send command */ LCD_WRX_LOW(); /* Reset LCD control line(/CS) and Send command */ LCD_CS_LOW(); SPIx_Write(Reg); /* Deselect: Chip Select high */ LCD_CS_HIGH(); } /** * @brief Reads register value. * @param RegValue Address of the register to read * @param ReadSize Number of bytes to read * @retval Content of the register value */ uint32_t LCD_IO_ReadData(uint16_t RegValue, uint8_t ReadSize) { uint32_t readvalue = 0; /* Select: Chip Select low */ LCD_CS_LOW(); /* Reset WRX to send command */ LCD_WRX_LOW(); SPIx_Write(RegValue); readvalue = SPIx_Read(ReadSize); /* Set WRX to send data */ LCD_WRX_HIGH(); /* Deselect: Chip Select high */ LCD_CS_HIGH(); return readvalue; } /** * @brief Wait for loop in ms. * @param Delay in ms. */ void LCD_Delay(uint32_t Delay) { HAL_Delay(Delay); } /******************************************************************************* LINK OPERATIONS *******************************************************************************/ /********************************* LINK IOE ***********************************/ /** * @brief IOE Low Level Initialization. */ void IOE_Init(void) { I2Cx_Init(); } /** * @brief IOE Low Level Interrupt configuration. */ void IOE_ITConfig(void) { I2Cx_ITConfig(); } /** * @brief IOE Writes single data operation. * @param Addr: I2C Address * @param Reg: Reg Address * @param Value: Data to be written */ void IOE_Write(uint8_t Addr, uint8_t Reg, uint8_t Value) { I2Cx_WriteData(Addr, Reg, Value); } /** * @brief IOE Reads single data. * @param Addr: I2C Address * @param Reg: Reg Address * @retval The read data */ uint8_t IOE_Read(uint8_t Addr, uint8_t Reg) { return I2Cx_ReadData(Addr, Reg); } /** * @brief IOE Writes multiple data. * @param Addr: I2C Address * @param Reg: Reg Address * @param pBuffer: pointer to data buffer * @param Length: length of the data */ void IOE_WriteMultiple(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length) { I2Cx_WriteBuffer(Addr, Reg, pBuffer, Length); } /** * @brief IOE Reads multiple data. * @param Addr: I2C Address * @param Reg: Reg Address * @param pBuffer: pointer to data buffer * @param Length: length of the data * @retval 0 if no problems to read multiple data */ uint16_t IOE_ReadMultiple(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length) { return I2Cx_ReadBuffer(Addr, Reg, pBuffer, Length); } /** * @brief IOE Delay. * @param Delay in ms */ void IOE_Delay(uint32_t Delay) { HAL_Delay(Delay); } /********************************* LINK GYROSCOPE *****************************/ /** * @brief Configures the Gyroscope SPI interface. */ void GYRO_IO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure the Gyroscope Control pins ------------------------------------*/ /* Enable CS GPIO clock and Configure GPIO PIN for Gyroscope Chip select */ GYRO_CS_GPIO_CLK_ENABLE(); GPIO_InitStructure.Pin = GYRO_CS_PIN; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM; HAL_GPIO_Init(GYRO_CS_GPIO_PORT, &GPIO_InitStructure); /* Deselect: Chip Select high */ GYRO_CS_HIGH(); /* Enable INT1, INT2 GPIO clock and Configure GPIO PINs to detect Interrupts */ GYRO_INT_GPIO_CLK_ENABLE(); GPIO_InitStructure.Pin = GYRO_INT1_PIN | GYRO_INT2_PIN; GPIO_InitStructure.Mode = GPIO_MODE_INPUT; GPIO_InitStructure.Speed = GPIO_SPEED_FAST; GPIO_InitStructure.Pull= GPIO_NOPULL; HAL_GPIO_Init(GYRO_INT_GPIO_PORT, &GPIO_InitStructure); SPIx_Init(); } /** * @brief Writes one byte to the Gyroscope. * @param pBuffer: Pointer to the buffer containing the data to be written to the Gyroscope. * @param WriteAddr: Gyroscope's internal address to write to. * @param NumByteToWrite: Number of bytes to write. */ void GYRO_IO_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) { /* Configure the MS bit: - When 0, the address will remain unchanged in multiple read/write commands. - When 1, the address will be auto incremented in multiple read/write commands. */ if(NumByteToWrite > 0x01) { WriteAddr |= (uint8_t)MULTIPLEBYTE_CMD; } /* Set chip select Low at the start of the transmission */ GYRO_CS_LOW(); /* Send the Address of the indexed register */ SPIx_WriteRead(WriteAddr); /* Send the data that will be written into the device (MSB First) */ while(NumByteToWrite >= 0x01) { SPIx_WriteRead(*pBuffer); NumByteToWrite--; pBuffer++; } /* Set chip select High at the end of the transmission */ GYRO_CS_HIGH(); } /** * @brief Reads a block of data from the Gyroscope. * @param pBuffer: Pointer to the buffer that receives the data read from the Gyroscope. * @param ReadAddr: Gyroscope's internal address to read from. * @param NumByteToRead: Number of bytes to read from the Gyroscope. */ void GYRO_IO_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) { if(NumByteToRead > 0x01) { ReadAddr |= (uint8_t)(READWRITE_CMD | MULTIPLEBYTE_CMD); } else { ReadAddr |= (uint8_t)READWRITE_CMD; } /* Set chip select Low at the start of the transmission */ GYRO_CS_LOW(); /* Send the Address of the indexed register */ SPIx_WriteRead(ReadAddr); /* Receive the data that will be read from the device (MSB First) */ while(NumByteToRead > 0x00) { /* Send dummy byte (0x00) to generate the SPI clock to Gyroscope (Slave device) */ *pBuffer = SPIx_WriteRead(DUMMY_BYTE); NumByteToRead--; pBuffer++; } /* Set chip select High at the end of the transmission */ GYRO_CS_HIGH(); } #ifdef EE_M24LR64 /******************************** LINK I2C EEPROM *****************************/ /** * @brief Initializes peripherals used by the I2C EEPROM driver. */ void EEPROM_IO_Init(void) { I2Cx_Init(); } /** * @brief Writes data to I2C EEPROM driver in using DMA channel. * @param DevAddress: Target device address * @param MemAddress: Internal memory address * @param pBuffer: Pointer to data buffer * @param BufferSize: Amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef EEPROM_IO_WriteData(uint16_t DevAddress, uint16_t MemAddress, uint8_t* pBuffer, uint32_t BufferSize) { return (I2Cx_WriteBufferDMA(DevAddress, MemAddress, pBuffer, BufferSize)); } /** * @brief Reads data from I2C EEPROM driver in using DMA channel. * @param DevAddress: Target device address * @param MemAddress: Internal memory address * @param pBuffer: Pointer to data buffer * @param BufferSize: Amount of data to be read * @retval HAL status */ HAL_StatusTypeDef EEPROM_IO_ReadData(uint16_t DevAddress, uint16_t MemAddress, uint8_t* pBuffer, uint32_t BufferSize) { return (I2Cx_ReadBufferDMA(DevAddress, MemAddress, pBuffer, BufferSize)); } /** * @brief Checks if target device is ready for communication. * @note This function is used with Memory devices * @param DevAddress: Target device address * @param Trials: Number of trials * @retval HAL status */ HAL_StatusTypeDef EEPROM_IO_IsDeviceReady(uint16_t DevAddress, uint32_t Trials) { return (I2Cx_IsDeviceReady(DevAddress, Trials)); } #endif /* EE_M24LR64 */ /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/根据官方例程 https://liteos.github.io/quick-start/intro/a-simple-blinky-demo.html修改代码 blinky_demo.h/* * blinky_demo.h * * Created on: 2020年2月3日 * Author: hpf19 */ #ifndef INCLUDE_BLINKY_DEMO_H_ #define INCLUDE_BLINKY_DEMO_H_ #include "stm32f429i_discovery.h" #include "los_swtmr.h" #include "los_queue.h" #include "los_task.h" /**************************************MACRO DEFINES*****************************************/ #define QUEUE_LENGTH 2 #define SND_CMD1_MSG 100 #define SND_CMD2_MSG 200 #define RECV_TASK_PRIOR 8 //receive task priority #define RECV_TASK_STACK_SIZE 0x400 //receive task stack size,if you do more deal,make it bigger /**************************************GLOBAL VARS********************************************/ UINT32 g_QueueID; UINT32 g_RecvTaskID; UINT16 g_TimerID1; UINT16 g_TimerID2; UINT32 Blinky_Demo(VOID); #endif /* INCLUDE_BLINKY_DEMO_H_ */blinky_demo.c/* * blink_demo.c * * Created on: 2020年2月3日 * Author: hpf19 */ #include <blinky_demo.h> /*************************************************************************************************** function :this is the timer callback entry parameters :args,not used yet instruction :we will send message to the queue periodicly ***************************************************************************************************/ static VOID Timer_Callback(UINT32 ulArg) { UINT32 ulRet = LOS_OK; ulRet = LOS_QueueWriteCopy( g_QueueID, (VOID *)&ulArg, /* send to msg */ sizeof(UINT32), 0 ); if(ulRet != LOS_OK) { printf("send message failure,error:%x\r\n",ulRet); } return; } static UINT32 Timers_Init(UINT32 ulInterval, UINT16 ulTimerID, UINT32 ulSendMsg) { UINT32 ulRet = LOS_OK; ulRet = LOS_SwtmrCreate( ulInterval, /* interval for ulInterval tick */ LOS_SWTMR_MODE_PERIOD, /* peridic software timer */ Timer_Callback, /* software timer callback function */ &ulTimerID, /* software timer id */ ulSendMsg /* sendmsg */ #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == YES) , OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_SENSITIVE #endif ); if (LOS_OK == ulRet) { ulRet = LOS_SwtmrStart(ulTimerID); if (LOS_OK != ulRet) { printf("start software timer error:%x\r\n",ulRet); return ulRet; } } return ulRet; } static VOID Task_RecvQ(UINT32 ulArg) { UINT32 ulRecvMsg = 0; UINT32 ulRet = LOS_OK; UINT32 ulLength = 0; BSP_LED_Init(LED3); BSP_LED_Init(LED4); while (1) { ulLength = sizeof(ulRecvMsg); ulRet = LOS_QueueReadCopy(g_QueueID, &ulRecvMsg, &ulLength, LOS_WAIT_FOREVER); if (LOS_OK == ulRet) { switch(ulRecvMsg) { case SND_CMD1_MSG: HAL_GPIO_TogglePin(LED3_GPIO_PORT, LED3_PIN); break; case SND_CMD2_MSG: HAL_GPIO_TogglePin(LED4_GPIO_PORT, LED4_PIN); break; default: break; } printf("RCVMSG: OK:%d\r\n", ulRecvMsg); //valid message here ulRecvMsg = 0; //clear the received message here. } } } UINT32 Blinky_Demo(VOID) { UINT32 ulRet = LOS_OK; TSK_INIT_PARAM_S stTask = {0}; /* Create the queue. */ ulRet = LOS_QueueCreate( "MsgQueue", /* queue name */ QUEUE_LENGTH, /* queue length */ &g_QueueID, /* queue id */ 0, /* flags, not used */ sizeof(UINT32) /* message size */ ); if (ulRet != LOS_OK) { printf("create the queue error:%x\r\n", ulRet); return ulRet; } stTask.pfnTaskEntry = (TSK_ENTRY_FUNC)Task_RecvQ; stTask.uwStackSize = RECV_TASK_STACK_SIZE; stTask.pcName = "RecvTask"; stTask.usTaskPrio = RECV_TASK_PRIOR; /* Create the task. */ ulRet = LOS_TaskCreate( &g_RecvTaskID, /* receive task id */ &stTask /* task params */ ); if (ulRet != LOS_OK) { printf("create task_rcv error:%x\r\n",ulRet); return ulRet; } /* Create the software timer1. */ ulRet = Timers_Init(1000, g_TimerID1, SND_CMD1_MSG); if (ulRet != LOS_OK) { printf("create timer error:%x\r\n", ulRet); return ulRet; } ulRet = Timers_Init(500, g_TimerID2, SND_CMD2_MSG); if (ulRet != LOS_OK) { printf("create timer error:%x\r\n", ulRet); return ulRet; } return LOS_OK; }main.c/* * This file is part of the µOS++ distribution. * (https://github.com/micro-os-plus) * Copyright (c) 2014 Liviu Ionescu. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom * the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ // ---------------------------------------------------------------------------- #include "blinky_demo.h" #include <stdio.h> #include <stdlib.h> #include "diag/Trace.h" #include "los_base.h" // ---------------------------------------------------------------------------- // // Semihosting STM32F4 empty sample (trace via DEBUG). // // Trace support is enabled by adding the TRACE macro definition. // By default the trace messages are forwarded to the DEBUG output, // but can be rerouted to any device or completely suppressed, by // changing the definitions required in system/src/diag/trace_impl.c // (currently OS_USE_TRACE_ITM, OS_USE_TRACE_SEMIHOSTING_DEBUG/_STDOUT). // // ----- main() --------------------------------------------------------------- // Sample pragmas to cope with warnings. Please note the related line at // the end of this function, used to pop the compiler diagnostics status. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wmissing-declarations" #pragma GCC diagnostic ignored "-Wreturn-type" int main(int argc, char *argv[]) { // At this stage the system clock should have already been configured // at high speed. // Show the program parameters (passed via semihosting). // Output is via the semihosting output channel. trace_dump_args(argc, argv); // Send a greeting to the trace device (skipped on Release). trace_puts("Hello ARM World!"); // Send a message to the standard output. puts("Standard output message."); // Send a message to the standard error. fprintf(stderr, "Standard error message.\n"); // At this stage the system clock should have already been configured // at high speed. trace_printf("System clock: %u Hz\n", SystemCoreClock); if (LOS_OK != LOS_KernelInit()) { return LOS_NOK; } trace_printf("Hello, LiteOS!\n"); Blinky_Demo(); LOS_Start(); return 0; } #pragma GCC diagnostic pop // ----------------------------------------------------------------------------3、编译运行结果运行:可以看到红绿灯周期性的闪烁
上滑加载中
推荐直播
-
华为云AI入门课:AI发展趋势与华为愿景
2024/11/18 周一 18:20-20:20
Alex 华为云学堂技术讲师
本期直播旨在帮助开发者熟悉理解AI技术概念,AI发展趋势,AI实用化前景,了解熟悉未来主要技术栈,当前发展瓶颈等行业化知识。帮助开发者在AI领域快速构建知识体系,构建职业竞争力。
去报名 -
华为云软件开发生产线(CodeArts)10月新特性解读
2024/11/19 周二 19:00-20:00
苏柏亚培 华为云高级产品经理
不知道产品的最新特性?没法和产品团队建立直接的沟通?本期直播产品经理将为您解读华为云软件开发生产线10月发布的新特性,并在直播过程中为您答疑解惑。
去报名
热门标签