超子物联网学习笔记

 OTA 分区跳转

1:设置sp,A区起始位置0x08005000,给到sp

2:设置pc,A区起始位置0x08005000+4,改到pc

3:把B区用到的外设,寄存器reset

补充几个点注意:

1.跳转之前必须关闭中断,不管是deinit,还是关闭总中断,反正必须关掉所有的中断;2.app初始化代码必须要手动初始化所有的全局变量,不然靠startup文件的初始化,极有可能有问题,应该可以靠链接文件直接初始化bss段;3.在app中初始化片上外设,必须要先将外设全部停止下来重新初始化。比如adc+dma方式,必须将adc和dma同时停下来再初始化,否者会有问题

视频:

【手把手写【STM32/GD32】OTA升级Boot程序,跳转A区两大关键点 SP和PC寄存器】

【手把手写【STM32/GD32】OTA升级Boot程序,利用函数指针,编写跳转A区程序】

define

可以使用#define来定义一个宏定义,而不加具体数字。这种情况下,宏定义A可以用来表示一个开关或者标记,用于条件编译或程序中控制代码执行的逻辑。

#define A

#ifdef A
    // 这段代码在A被定义时会执行
    // ...
#else
    // 这段代码在A未被定义时会执行
    // ...
#endif

分区下载之flash定义

在配置里面更改下载地址

更改中断向量表偏移量

 STM32的中断向量表

STM32中断向量表的偏移量设置方法

MDK软件 中,flash download界面中,Download Function

Erase Full Chip
Erase Sectors

 Verify

 Reset and Run

下载完后复位运行

 Do not Erase

bin文件 ,都是4字节的整数倍。从理论上分析, STM32 是32位的单片机,生成的代码也应该是32位(即4字节)的整数倍。

STM32F103C8T6的内部FLASH是如何划分的

STM32之CRC32

STM32f103G070RBTx 有硬件CRC32,硬件CRC模块可以通过配置寄存器来选择CRC多项式和输入数据的位宽,包括8位、16位和32位。通过输入数据和CRC多项式,硬件CRC模块可以自动计算CRC校验结果,无需CPU参与计算过程。

STM32F103 CRC32只能计算32位,不可以配置

IAP时,需要.bin文件

MDK配置

fromelf.exe --bin --output "@L.bin" "#L"
 

如此即为成功。

注意:网上有很多生成方法,我用的超子视频的不行(不会搞),上述时比较可行的方案。

还有有时候打开别人的工程,编译,发现底下奇怪的报错,估计时这个过程配置输出二进制文件了,取消勾选Run #1 应该可以解决。 

KEIL MDK生成bin文件的两种方法

利用MDK软件生成bin文件的简单方法

字符串之\0

在C语言中,字符串实际上是由字符数组组成的,数组的最后一个元素是空字符。当我们在C程序中声明一个字符串时,编译器会在我们输入的字符串最后自动添加一个空字符

例如,如果我们定义一个字符串 char str[ ] = "Hello";,那么编译器会在这个字符串的末尾自动添加一个空字符,使其变成 {'H', 'e', 'l', 'l', 'o', '\0'} 这样的字符数组。

这个空字符的存在非常重要,因为很多C语言库函数会依赖于这个空字符来确定字符串的结束位置,例如strlen()函数用于计算字符串的长度,它会一直读取字符直到遇到空字符才停止计数。
 

串口接收方案

采用DMA空闲中断 :不定长接收,因为采用DMA空闲中断,而不是靠DMA接收完成中断。所以设置DMA的接收量一般都大一点,不让DMA产生完成中断。

	dma_init_struct.number = U0_RX_MAX+1;                      
    //设置最大接收量  max+1:让DMA不产生完成中断

函数健壮性:

函数的健壮性指的是程序被设计的能力,以确保即使对参数的错误传递或存在无效的输入,程序也不会崩溃或发生意外的行为。实现函数的健壮性的一般原则,包括检查和处理所有输入,考虑所有可能的异常情况,避免使用过大或过小的步骤,并且确保程序可以以正确的方式处理所有情况。
 

关于 如何写出健壮的go函数? 的回答,具有参考意义。

健壮三原则

  • 原则一:不要相信任何外部输入的参数。

函数的使用者可能是任何人,对于任何的输入参数我们都要做有效性的边界校验。为了保证函数的健壮性,函数需要对所有输入的参数进行合法性的检查。一旦发现问题,立即终止函数的执行,返回预设的错误值。

  • 原则二:不要忽略任何一个错误

在函数调用逻辑里,我们可能调用标准的或者第三方的库函数,因为对于这种情况 我们不一定能真正调用成功。我们一定要显式地检查这些调用返回的错误值。一旦发现错误,要及时终止函数执行,防止错误继续传播。

  • 原则三:不要假定异常不会发生。

统一认知:异常不是错误。错误是可预期的,也是经常会发生的,我们有对应的公开错误码和错误处理预案,但异常却是少见的、意料之外的。通常意义上的异常,指的是硬件异常、操作系统异常、语言运行时异常,还有更大可能是代码中潜在 bug 导致的异常,比如代码中出现了以 0 作为分母,或者是数组越界访问等情况。

函数设计时,我们就需要根据函数的角色和使用场景,考虑是否要在函数内设置异常捕捉和恢复的环节。

健壮的函数意味着,无论调用者如何使用你的函数,你的函数都能以合理的方式处理调用者的任何输入,并给调用者返回预设的、清晰的错误值。即便你的函数发生内部异常,函数也会尽力从异常中恢复,尽可能地不让异常蔓延到整个程序。

 大端存储和小端存储 内容管理

大端存储,是将数据的低位字节放到高地址处,高位字节放到低地址处。

小端存储,是将数据的低位字节放到低地址处,高位字节放到高地址处。

大端存储和小端存储记忆时,可以理解为将低位字节放到大端还是小端?大端存储就是将低为放到高地址,小端就是将低位放到低地址,这样方便记忆

为什么会有大小端存储:
对于位数大于8的处理器,寄存器的宽度大于1个字节,那么将会存在如何将多个字节安排在寄存器内,就可以有大小端存储两种方法,大小端存储并没有优劣之分,都是存储的方法

 验证C语言的数据的存储是大端还是小端:

//判断大小端
//假设右边是高地址,左边是低地址
int main()
{
	int a = 1; // 0x0000 0001
	//如果是大端 低位字节放到高地址,高位字节放到低地址
	//00 00 00 01
	//如果是小端 高位字节放到高地址,低位字节放到低地址
	//01 00 00 00
	char* p = (char*)&a; //字符指针只读1个字节,读8位
    //如果是大端存储,则p读取的值是0
    //如果是小端存储,则p读取的值是1
	if (*p == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

工程结构 参考:

a. 1_APP
        i. 应用层,存放业务逻辑代码文件
    b. 2_Device
        i. 设备层,存放设备层代码文件
    c. 3_protocol
        i. 协议层,存放协议层代码文件,比如网络通信协议,蓝牙协议
    d. 4_Middleware
        i. 中间组件层,例如RTOS实时操作系统,FatFs文件系统
    e. 5_Platform
        i. 平台层代码文件
    f. 6_MoudleDriver
        i. 外设模块代码文件
    g. 7_HAL
        i. 硬件抽象层,存放处理器的内核接口文件和库文件
    h. 8_Core
        i. 处理器需要的一些配置文件,比如hal库的配置文件Stm32xxx_hal_conf.h,中断处理文件Stm32xxx_it.c和Stm32xxx_it.h,系统初始化文件system_stm32f1xx.c和system_stm32f1xx.h,
        ii. 还可以新建stm32f1xx_clk.c和stm32f1xx_clk.h来存放stm32的时钟树配置函数
    i. Project
        i. 工程文件,启动文件startup.s也放到这里

还可以建立错误信息打印。

注意编号和个数

比如20个区,编号从0-19。编写时注意 1。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值