天天看點

關于STM32 IAP

轉眼間天亮了......

然後就想起了一個朋友QQ的個性簽名:年輕人總是要為一些自己認為有意義的事情而廢寝忘食,通宵達旦,直至白發方休........

對了這篇文章一定會介紹的很詳細,請細嚼慢咽.......嗯,我是這樣認為的,,,,,,

上面是昨天寫的,應該說是今天寫的,,今天發現發現部落格又不能複制粘貼圖檔了!!!!然後就睡了一覺,,麻煩。。。。是不是因為我寫的部落格有太多的圖檔而把我屏蔽了。能讓人一目了然的就是圖檔。。。。

說一下自己是如何做的,,,

先說一下實作的功能

IAP程式的功能

關于STM32 IAP

再看自己的使用者程式--使用者程式自己也做了些設定

關于STM32 IAP

對了關于我為什麼拷貝到Flash裡面------自己用的單片機的RAM不夠用,存不了使用者程式,是以自己就定義了一個小點的數組(環形隊列),序列槽一邊接收,一邊往Flash裡面寫,環形隊列可是幫了大忙了,,,,

把IAP更新程式下進去,以後就直接通過序列槽發送自己的使用者程式就行了...什麼都不需要做了,先說一下操作過程吧!最後有自己的源碼

IAP程式軟體不需要任何配置

關于STM32 IAP
關于STM32 IAP

波特率太快的話,資料來不及寫入Flash,環形隊列容易溢出,,太慢的話,程式發送的慢。。。

使用者程式軟體需要一些配置

關于STM32 IAP

8006000告訴編譯器我的使用者程式打算在這裡開始,你幫我設定一下吧,預設是在8000000開始的

0x1A000,就是告訴編譯器我的程式空間有這麼大。

我的使用者程式裡面也是設定的6000,這個一定要和程式設定的一樣哈

關于STM32 IAP

關于這個我後面會說為什麼這樣設定。。。當然也可以百度一下。

其實我的本來是

關于STM32 IAP

20000換成十進制就是131072個位元組  除以1024 等于128

由于我先把IAP程式下進去了,IAP程式也需要空間來運作,,,我就給了他6000 換成十進制就是24576  除以1024就是24K

我的總共是128K然後去掉IAP暫用的24K就是  128-24 = 104K  = 106496個位元組   換成16進制就是 1A000

是以我上面寫了1A000

對了如果您的闆子是大容量的如果您非常明白就自己随意修改把,别忘了修改程式裡的那個,,,

如果不是很明白按照上面修改就行,後面會讓您明白

關于STM32 IAP

這個呢就是讓Keil軟體幫忙生成bin檔案

F:\Keil4&&MDK4.70A\ARM\ARMCC\bin\fromelf.exe   --bin -o  .\Progect\Progect.bin  ..\Progect\output\Progect.axf

F:\Keil4&&MDK4.70A\ARM\ARMCC\bin\fromelf.exe   --bin -o   這個是執行的指令,就是生成bin檔案,根據自己的安裝路徑找哈

.\Progect\Progect.bin 就是告訴他把生成的bin檔案放在哪個地方

..\Progect\output\Progect.axf 這個就是自己工程編譯的時候産生的.axf檔案,根據自己的找到

./目前目錄

../上一級目錄

../../上上一級目錄

關于Bin檔案和Hex檔案

<a href="http://blog.sina.com.cn/s/blog_6b94d5680100lo2h.html" target="_blank"> http://blog.sina.com.cn/s/blog_6b94d5680100lo2h.html</a>

這是我的使用者程式的Hex與Bin

關于STM32 IAP

咱們自己設定好寫到哪裡了,是以前頭的就不需要了,後面的校驗也不需要了,,不過呢應該向他那樣加上校驗,資料對了再寫進去!!!!

好生成了bin檔案

關于STM32 IAP

然後

關于STM32 IAP
關于STM32 IAP
關于STM32 IAP
關于STM32 IAP

假設修改了程式了,再更新

關于STM32 IAP
關于STM32 IAP
關于STM32 IAP
關于STM32 IAP

您再更新就再更新把!!

再更新

關于STM32 IAP
關于STM32 IAP
關于STM32 IAP

不要老是更新哈!!!玩壞了Flash可就不好玩了

自己用的F103RBT6單片機的RAM隻有

關于STM32 IAP

 5000 也就是20480個位元組,,但是自己的程式已經超過了這個位元組數

是以自己就不能先定義一個很大的數組然後然後把程式先存在裡面了,列如很多都是:

u8 USART_RX_BUF[USART_REC_LEN]  __attribute__ ((at(0X20001000)));//接收緩沖,最大USART_REC_LEN個位元組,起始位址為0X20001000.//把資料固定的存在以0X20001000為起始位址的RAM裡面

自己呢就是用的環形隊列一邊接收,一邊寫入,,,關于環形隊列可以看我的環形隊列的文章,,,

<a href="http://www.cnblogs.com/yangfengwu/p/6822984.html" target="_blank">http://www.cnblogs.com/yangfengwu/p/6822984.html</a>

就再說一下自己的程式的一些地方

序列槽接收的

用的系統定時器中斷來檢測的序列槽空閑,判斷接沒接收到一條完整的資料--方法呢是看到人家的一種方法,感覺比自己以前的好,是以直接拿過來用了

關于單片機空閑中斷可以看一下自己以前的

<a href="http://www.cnblogs.com/yangfengwu/p/6746403.html" target="_blank">http://www.cnblogs.com/yangfengwu/p/6746403.html</a>

我的IAP的接收的資料往Flash裡面寫和使用者程式的往Flash裡面寫有一點不同,其實使用者程式的往Flash裡面寫的程式是後期的改進...

先看我的IAP的

if(rbCanRead(&amp;pRb)&gt;1)

因為一次性要往Flash裡面寫16位資料,是以才會判斷資料個數大于一個的時候再往裡面寫.

雖然現在程式沒有問題,但是我還在想如果程式的個數是奇數個就完啦!但是好像程式的個數總是偶數個....其實可以在判斷接收完成的裡面

做一下判斷,如果資料還殘留一個,那就寫進去....

好,那就看一下判斷接收完程式

後邊屏蔽的是測試的時候,看一下寫入的資料,然後和源資料對比一下,看一下寫入的對不對

if(((*(vu32*)(FLASH_APP2_ADDR+4))&amp;0xFF000000)==0x08000000)

這句話

先問一個問題,怎麼知道接收過來的是使用者程式呢????要是别的資料怎麼辦???,,必須有一個判斷依據才行對吧!!

就必須找到使用者程式中永恒不變的變量....

然後呢,我是看别人的程式說,資料的第一個4個位元組為棧頂位址,資料的第二個4位元組為複位中斷向量的入口位址

關于STM32 IAP

FLASH_APP2_ADDR+4指針就移動到了IAP更新程式的E9或者說電壓電流采集程式的D5上

(*(vu32*)(FLASH_APP2_ADDR+4))然後強制型的轉成32位的,然後取出來,就是IAP更新程式的E9 20 00 08

或者說電壓電流采集程式的D5 7E 00 08

還有一件事就是STM32是小端模式,,,,所謂小端模式就是低位在低位址,高位在高位址

舉個例子

把60000存到STM32的Flash的,60000轉換成16進制是EA60  EA是高8位,60是低八位,,存到Flash裡面就是60EA這樣存的

60存到了低位址,EA存到了高位址,,,,,當然有小端模式就有大端模式,,,大端模式就是低位在高位址,高位在低位址,電腦就是這樣...

說到這裡就要說一下共用體

一個整形資料快速的轉換成16進制存到數組裡面

Resolver_7758.Data = 60000;

那麼Resolver_7758.Data_Table[0] = 0x60;

      Resolver_7758.Data_Table[1] = 0xEA;

      Resolver_7758.Data_Table[2] = 0x00;

      Resolver_7758.Data_Table[3] = 0x00;

一個浮點型的資料轉換成16進制存到數組裡面--其實也是按照IEEE754規約來計算的

Resolver_Usart.Data = 220.5;

那麼Resolver_Usart.Data_Table[0] = 0x00;

      Resolver_Usart.Data_Table[1] = 0x80;

      Resolver_Usart.Data_Table[2] = 0x5C;

      Resolver_Usart.Data_Table[3] = 0x43;

是以說上面的資料取出來就是08 00 20 E9然後&amp;0xFF000000 肯定就等于 0x08000000啦

其實這樣還有一個原因是因為32的位址是從08000000開始的,複位中斷向量的位址的最高兩位肯定是08啦!!!!

然後還有個if(((*(vu32*)appxaddr)&amp;0x2FFE0000)==0x20000000) //檢查棧頂位址是否合法.

這個......難道棧頂位址的最高位就是20......以後等看到相關的資料再說吧

有人這樣介紹的--仔細看,細細品味....

<a href="http://blog.csdn.net/yx_l128125/article/details/12992773" target="_blank">http://blog.csdn.net/yx_l128125/article/details/12992773</a>

 對了說一下中斷向量表

就從我的MSP430的文章中摘抄過來

關于STM32 IAP
關于STM32 IAP

原文位址

<a href="http://www.cnblogs.com/yangfengwu/p/6064129.html" target="_blank">http://www.cnblogs.com/yangfengwu/p/6064129.html</a>

 突然想起來一句話,知識是相通的....

32也有中斷向量表,就像上面的430的似的,

隻不過呢!32的中斷函數的入口位址是可以改變的!!!(F0好像固定,但是看過一篇文章好像也能通過某種方式改改)

我們寫入IAP程式後單片機内部就有了一個中斷向量表,這個呢是其内部一開始的固定的,

如果跳轉到使用者程式,使用者程式肯定會有自己的中斷函數吧!如序列槽,,定時器,,等等,,,,如果不改變中斷向量表的話!!!産生的中斷

豈不是跑到了IAP那邊去了,IAP那邊有自己的中斷函數,,,亂了,徹底亂了,,,,,是以必須得讓中斷向量表改變改變,好讓自己産生的

中斷,執行自己的中斷函數......

那就加一句話,或者修改一個地方

關于STM32 IAP
關于STM32 IAP

再看我的使用者程式的一個地方,,感覺自己羅嗦了

畢竟是使用者程式,序列槽1可能要參與别的通信,,,是以自己加了一個判斷是否是要更新程式的資料,,,是的話才往Flash裡面寫

自己的源碼

這兩天發現了自己程式的Bug

1,如果使用者程式主函數加入延時,那麼程式就來不及讀出然後寫到Flash裡面,序列槽卻不停的往環形隊列裡面寫,進而造成環形隊列溢出....

再者如果寫入的時候,設定的序列槽助手的波特率太快,,,,同樣也會造成環形隊列溢出(就是往環形隊列寫的太快了)....

自己把寫Flash的程式放在了定時器裡面,50Us進入一次的定時器,看着網上說往Flash寫一個位元組大約16Us,,,,加上其餘的程式整體應該不會超過50Us

如果有溢出程式不在往環形隊列裡面寫了

最後接收完如果判斷溢出過,直接複位重新開機,複位重新開機更友善直接...

2,如果寫了一些後,突然因為某些原因停止了寫入,,,,,本想在程式中觀察末尾有什麼固定的資料沒有,,,,或者自己最後加一些标志位

但是這個現在程式好像能判斷出來....但是自己一直沒有明白程式為什麼可以判斷出來............應該判斷不出來的......

後來一想現在反正是自己去更新程式,真不行可以直接燒,,,,就先放一放,,,,

更改後的

繼續閱讀