[012] [STM32] 代码重定位与清除BSS段深入分析

本文详细介绍了STM32程序在MDK环境下重定位的概念、原因和实现方法,包括数据段重定位、代码段重定位以及BSS段的清除。通过分析重定位的必要性,探讨了位置无关码、散列文件(Scatter File)的作用,并给出了汇编和C语言实现的重定位例程。文章最后讨论了代码段不重定位的后果,并提供了完整的启动文件代码示例。
#include "my_include.h" void scanKeyAnddealKey(void); void My_ESP8266_SendStrStr(USART_TypeDef* USARTx, const char *str); void displayOfCollectedData(void);//显示采集到的数据 unsigned int i; //中间变量 i char dis0[256];//液晶显示暂存数组 char dis1[23];//液晶显示暂存数组 char dis2[23];//液晶显示暂存数组 char dis3[23];//液晶显示暂存数组 char dis4[23];//液晶显示暂存数组 char dis5[23];//液晶显示暂存数组 char dis6[23];//液晶显示暂存数组 char dis7[23];//液晶显示暂存数组 u16 yPlace = 0; //显示位置y坐标值 #define ADDR_FLASH_WRITE (FLASH_BASE_ADDR+STM32_FLASH_SIZE*1024-STM_SECTOR_SIZE*1) #define SET_MAX_NUM 3 //设置变量数量 int16 saveData[10] ={0 , 45, 85, 65, 20,100, 3, 3, 0}; const u16 setMaxData[10] ={1 , 99, 99, 99, 99,999, 99, 99, 0};//设置值的最大值 #define setMode saveData[0] #define setHumLow saveData[1] #define setHumHig saveData[2] unsigned int nowTemp=0; //当前温度 unsigned int nowHumi=0; //湿度 unsigned char buzFlag =0;//蜂鸣器报警状态 unsigned char dealFlag = 0;//定时 处理数据 unsigned char setFlag = 0;//设置标志 u8 errFlag =0;//异常提醒 u8 needWriteFlash=0;//需要保存数据到flash u8 startCheckWireLess = 0;//启动检测无线种类 u8 wirelessFlag = 0;//无线种类 0蓝牙或无无线 1wifi #define BUZ_PIN PC13 //接口 //#define yewei_pin PinRead(PA4) //液位接口 int main(void) { USARTx_Init(USART1,9600);//串口初始化 USARTx_Init(USART2,9600);//串口初始化 My_KEY_Init();//初始化输入 My_LED_Init(); //输出初始化 relay_beng=1;relay_cs=1;relay_jsq=1;//上电动作下 delay_ms(100); relay_beng=0;relay_cs=0;relay_jsq=0;//上电动作下 DHT11_Init();//初始化dht11 My_STMFlash_SectorSaveInit(ADDR_FLASH_WRITE,saveData,sizeof(saveData)); My_LEDBlink(BUZ_PIN,1,2,50,300);//控制蜂鸣器动作 LCD1602_Init(); //液晶初始化 LCD1602_Write_String(0,0,"init .. ");//显示字符串 i = 5;startCheckWireLess=1;//启动检测 一时间取消 while(i-- && wirelessFlag == 0) //此时判断是无线类型 {USARTSendString(USART1,"ATE0\r\n"); delay_ms(100);} startCheckWireLess = 0;//取消检测 if(wirelessFlag == 1) { i = 50;while(i--){delay_ms(100);} //wifi启动 必须延时5s或以上 USARTSendString(USART1,"AT+CWMODE_CUR=3\r\n");// 设置模式 delay_ms(50); USARTSendString(USART1,"AT+CWSAP=\"AUAISOUT000\",\"\",1,0\r\n");//设置网络名字及密码 delay_ms(50); USARTSendString(USART1,"AT+CIPAP_CUR=\"10.10.10.11\"\r\n");//设置本机ip delay_ms(50); // USARTSendString(USART1,"AT+CIPMODE=0\r\n");//设置ip模式 // delay_ms(50); USARTSendString(USART1,"AT+CIPMUX=1\r\n");//打开多连接 delay_ms(50); USARTSendString(USART1,"AT+CIPSERVER=1,80\r\n");//启动端口号 delay_ms(50); //以上作为服务端 局域网 } while(1) { scanKeyAnddealKey();//按键扫描及处理 if(myReadFlag_tick == true ) //定时读取时间到 { myReadFlag_tick = false; //清除标志 dealFlag++; //++ 处理 if(dealFlag>=5)//处理标志 { dealFlag=0; DHT11_ReadData(0); //读取温湿度值 nowTemp = DHT11_GetTemp(0);//获取温度 nowHumi = DHT11_GetHumi(0);//获取湿度 } errFlag=0;//清零 switch(setMode) { case 0: //自动模式 if(nowHumi<setHumLow) { relay_jsq = 1;//控制 加湿器 relay_cs = 0;//控制 除湿 errFlag++;//异常++ } else if(nowHumi>setHumHig) { relay_jsq = 0;//控制 加湿器 relay_cs = 1;//控制 除湿 errFlag++;//异常++ } else { relay_jsq = 0;//控制 加湿器 relay_cs = 0;//控制 除湿 } break; case 1: errFlag=0;//手动模式 按键中处理 break; default: break; } if(errFlag != 0 )//自动下有异常 { My_LEDBlink(BUZ_PIN,1,2,50,1000);//控制蜂鸣器动作 } else { My_LEDBlink_Stop(BUZ_PIN); } sprintf((char*)dis0,"M:%s%cH:%02d%% %02dC ",setMode==0?"auto":"manu",setFlag==1?'<':' ',nowHumi,nowTemp);//打印数据 LCD1602_Write_String(0,0,dis0);//显示字符串 sprintf((char*)dis0,"L%02d%cH%02d%c J:%s C:%s ",setHumLow,setFlag==2?'<':'-',setHumHig,setFlag==3?'<':' ',relay_jsq==1?"O":"C",relay_cs==1?"O ":"C");//打印数据 LCD1602_Write_String(0,1,dis0);//显示字符串 if(needWriteFlash==1) { My_STMFlash_SaveUseSector(saveData); //将数据保存到flash 掉电不丢失 needWriteFlash =0;//0 直接停止更新 除非下次触发 } else if(needWriteFlash >0 ){needWriteFlash--;}//定时写入数据延时 } if(mySendFlag_tick == true )//定时发送时间到 { mySendFlag_tick = false;//清除标志 sprintf(dis0,"MD%03dTE%03dHU%03dHL%03dHH%03d",setMode,nowTemp,nowHumi,setHumLow,setHumHig); sprintf(dis0,"%sJS%sCS%s\r\n",dis0,relay_jsq!=0?"O":"C",relay_cs !=0?"O":"C"); if(wirelessFlag == 0)USARTSendString(USART1 ,dis0); //发送 对应的 数据 else My_ESP8266_SendStrStr(USART1 ,dis0);//发送数据 } My_UartMessage_Process();//处理串口数据 } } void scanKeyAnddealKey(void) { My_KeyScan();//按键扫描 if(KeyIsPress(KEY_1)) { setFlag++;//设置标志 if(setFlag >= SET_MAX_NUM+1) setFlag = 0; } if(KeyIsPress(KEY_2))//按键按下 { if(setFlag == 0) { if(setMode == 1) relay_jsq = !relay_jsq ;//切换状态 } else { for(i=0;i<SET_MAX_NUM;i++) { if(i+1 == setFlag) { if(saveData[i]<setMaxData[i])saveData[i]++; else saveData[i] = 0; } } needWriteFlash=2; //将数据保存到flash 掉电不丢失 } } if(KeyIsPress(KEY_3))//按键按下 { if(setFlag == 0) { if(setMode == 1) relay_cs = !relay_cs ;//切换状态 } else { for(i=0;i<SET_MAX_NUM;i++) { if(i+1 == setFlag) { if(saveData[i]>0)saveData[i]--; else saveData[i] = setMaxData[i]; } } needWriteFlash=2; //将数据保存到flash 掉电不丢失 } } if(KeyIsPress(KEY_4)) { if(setFlag == 0) { if(setMode == 1) relay_beng = !relay_beng ;//切换状态 } else { setFlag = 0;//取消设置 } } } void OnGetUartMessage(const _uart_msg_obj *uartMsgRec) { char *strPtr; u16 midVal = 0;//中间提取之检测 // if((strPtr=strstr(uartMsgRec->payload,"RTC"))!=NULL)//接收到rtc字符串 *RTC20200420173611# // { // My_RTC_SetStr(strPtr+3);//设置时间 // } if((strPtr=strstr(uartMsgRec->payload,"SM"))!=NULL)//接收到字符串 { setMode=ParseInteger(strPtr+2,3);//提取设置参数 if(setMode>1)setMode=0; } if((strPtr=strstr(uartMsgRec->payload,"HL"))!=NULL)//接收到字符串 { setHumLow=ParseInteger(strPtr+2,3);//提取设置参数 } if((strPtr=strstr(uartMsgRec->payload,"HH"))!=NULL)//接收到字符串 { setHumHig=ParseInteger(strPtr+2,3);//提取设置参数 } if((strPtr=strstr(uartMsgRec->payload,"JS001"))!=NULL)//接收到字符串 { if(setMode == 1) relay_jsq = 1;//打开 } if((strPtr=strstr(uartMsgRec->payload,"JS000"))!=NULL)//接收到字符串 { if(setMode == 1) relay_jsq = 0;//关闭 } if((strPtr=strstr(uartMsgRec->payload,"CS001"))!=NULL)//接收到字符串 { if(setMode == 1) relay_cs = 1;//打开 } if((strPtr=strstr(uartMsgRec->payload,"CS000"))!=NULL)//接收到字符串 { if(setMode == 1) relay_cs = 0;//关闭 } if((strPtr=strstr(uartMsgRec->payload,"%"))!=NULL)//接收到字符串 { if(wirelessFlag == 0)USARTSendString(USART1,"\r\n*Test Ok!!#\r\n\r\n"); //发送 对应的 数据 else My_ESP8266_SendStrStr(USART1,"\r\n*Test Ok!!#\r\n\r\n");//发送数据 } needWriteFlash = 3; //需要更新存储数据 } void My_ESP8266_SendStrStr(USART_TypeDef* USARTx, const char *str) { // u8 i; // for(i=0;i<2;i++)//**All notes can be deleted and modified**// { My_USART_printf(USARTx,"AT + CIPSEND = %d, %d\r\n",0,strlen(str)); delay_ms(10); USARTSendBytes(USARTx,(const uint8_t *)str,strlen(str));//发送数据 USARTSendBytes(USARTx,"\r\n",2);//发送数据 delay_ms(5); } } void checkWireLessMode(u8 recBuf)//检查无线类型 { static u8 checkIn = 0;//查看第一次标志是否接受 if(startCheckWireLess == 1 && wirelessFlag == 0)//启动检测无线 { if (checkIn == 1 && recBuf == 'K')//**All notes can be deleted and modified**// { wirelessFlag = 1; //1表示wifi } } } 逐句解释代码
05-28
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柯西的彷徨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值