打印
[STM8]

求助,香主请进:STM8S的IAP升级之Flash写入的问题

[复制链接]
11496|39
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sed2003|  楼主 | 2012-11-2 11:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sed2003 于 2012-11-15 13:42 编辑

大家好,我目前用STM8S208MB来做IAP自升级功能。
目前,我是用ARM来转128个字节过来给STM8,然后,让烧写Flash的程序运行在RAM里,以此来写Flash。
目前,用STVP读出来发现,可以写进去一部分。但是,到了某一个固定的位置就会写错。不知道怎么回事。
沙发
sed2003|  楼主 | 2012-11-2 11:09 | 只看该作者
本帖最后由 sed2003 于 2012-11-2 12:42 编辑

请问我的方法有误吗?

使用特权

评论回复
板凳
sed2003|  楼主 | 2012-11-2 11:29 | 只看该作者
本帖最后由 sed2003 于 2012-11-2 18:10 编辑

等了一天,没有任何回音,失望啊

使用特权

评论回复
地板
gaoyueping| | 2012-11-9 17:15 | 只看该作者
先做一个很小的改动,读出FLASH里的内容看一下,然后和之前的比较有什么差异!

使用特权

评论回复
5
sed2003|  楼主 | 2012-11-12 16:53 | 只看该作者
我把代码改了一下,没有用user-bootloader那种方式来,我就是直接在RAM里执行写Flash操作。写完以后,重新调到8000H处执行。结果,发现无法开机。
我检查了一下读取的Flash数据,在COSMIC暂停以后,发现是正确的!
具体代码片段是这样的
                #if 1
/************* write into flash rom *************/               
                        for(i=0;i<128;i++)
                        {
                                FlashBuf[i] = DataBuffer[6+i];
                        }               
                        WriteBuffer(FlhDataAddress,FlhDataCount);
                        RdData = FLASH_ReadByteData(FLASH_START+2);
                #endif
                                                FlhDataAddress += FlhDataCount;

使用特权

评论回复
6
sed2003|  楼主 | 2012-11-12 16:57 | 只看该作者
我怀疑是写入的位置不对,或者跳转的位置不对。
我写入的起始位置是8000H,按128个字节的块来写的,最后一个块如果不到128个字节后面补0.
而bin文件,我发现该文件的00008000h之前都是0,所以,我就截掉前面的,直接从00008000H开始读取数据的。
目前仍没找到问题所在。

使用特权

评论回复
7
自然的天逸| | 2012-11-12 17:13 | 只看该作者
写入不对可以用仿真器读出整片FLASH

使用特权

评论回复
8
自然的天逸| | 2012-11-12 17:14 | 只看该作者
在比较查看了

使用特权

评论回复
9
sed2003|  楼主 | 2012-11-13 10:56 | 只看该作者
我仔细检查了一下,发现是Flash数据有误。后面改正以后,重新升级,但是当它升级到86%的时候,就停止了。用STVP读出数据,也有零星错误。
我怀疑是波特率太高了引起的,我用的是115200bps。STM8S在RAM里运行速度,好像比在FLASH上跑起来慢一些,我在FLASH上面测试接收UART数据是正确的,到了RAM中,就有错误,而且调试的时候又无法看到。只有写数据的以后,用STVP才发现的。

使用特权

评论回复
10
sed2003|  楼主 | 2012-11-13 11:19 | 只看该作者
还有种可能,就是那个写函数有问题,不知道怎么搞的。它在RAM里运行就全部错,在FLASH里运行又可以,见鬼了。

使用特权

评论回复
11
sed2003|  楼主 | 2012-11-13 16:12 | 只看该作者
本帖最后由 sed2003 于 2012-11-13 16:16 编辑

我现在改用波特率9600来做,发现数据接收是正确的。
问题已经找到,是FLASH在超过255个块以后,会重新回到8000H上写入数据。好像是那个写函数,本身就是有缺陷的。
ST公司提供的库函数,好像有这个问题。

使用特权

评论回复
12
sed2003|  楼主 | 2012-11-13 16:42 | 只看该作者
我看了一下ST公司提供的库函数,没有问题。
是网络里某些人写的有问题,他故意改了FLASH写入的类型大小,想整人。
我再次测试中...

使用特权

评论回复
13
sed2003|  楼主 | 2012-11-13 17:09 | 只看该作者
本帖最后由 sed2003 于 2012-11-15 13:44 编辑

描述有误

使用特权

评论回复
14
oayzw| | 2012-11-13 17:20 | 只看该作者
可能是Count定义成char了,定义成int就应该可以了

测试发现一旦
for (Count = 0; Count < BLOCK_SIZE; Count++)
    {
      *((@far u8*)StartAddress + Count) = ((u8)(Buffer[Count]));
    }
变成
for (Count = 0; Count < BLOCK_SIZE; Count++)
    {
        * ...
sed2003 发表于 2012-11-13 17:09

使用特权

评论回复
15
sed2003|  楼主 | 2012-11-13 17:39 | 只看该作者
本帖最后由 sed2003 于 2012-11-15 13:45 编辑

我用的是STM8S208MB,下面是我的函数,Count没有定义错。
    u16 Count = 0;
    u32 StartAddress = 0;
现在,我已经可以写进去一部分了,但是,到了D280H位置,就出错。原因不明。

使用特权

评论回复
16
gaoyueping| | 2012-11-15 17:12 | 只看该作者
一步步来,先升128字节看看对不对,然后偿试写2个128看看,依次测试,不要想着一次就写正确。
想问一下:你的接收函数是放在哪个位置?升级时本身用于升级的这一部分函数,包括接收和数据处理函数是不能写的,要不然就崩溃了

使用特权

评论回复
17
sed2003|  楼主 | 2012-11-16 16:34 | 只看该作者
本帖最后由 sed2003 于 2012-11-16 17:01 编辑

我用STM8S208MB来做升级,在RAM里运行对flash的擦写工作,晶振仍用外部的,结果,前面写都是正确的,到了一定地址就写不正确了,不知道是怎么回事,请各位帮我看看。

传输协议都是自己定制协议,然后调用ST的库函数里的INRAM的那三个函数。
IN_RAM(void FLASH_EraseBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType));
IN_RAM(void FLASH_ProgramBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType,
                        FLASH_ProgramMode_TypeDef FLASH_ProgMode, uint8_t *Buffer));
IN_RAM(FLASH_Status_TypeDef FLASH_WaitForLastOperation(FLASH_MemType_TypeDef FLASH_MemType));
在操作过程中,我具体步骤如下:

解锁Flash,并COPY到RAM中:
disableInterrupts();
unlock_PROG();
unlock_DATA();
_fctcpy('F');
MCUUpdateCodeProc(); // 该函数里有UART收发,写Flash的动作,就是下面写的那些
写Flash的动作:
for(i=0;i<128;i++)
{
FlashBuf = DataBuffer[6+i];
}
FLASH_EraseBlock(blockcnt,FLASH_MEMTYPE_PROG);
FLASH_ProgramBlock(blockcnt,FLASH_MEMTYPE_PROG,FLASH_PROGRAMMODE_STANDARD,FlashBuf);
FLASH_WaitForLastOperation(FLASH_MEMTYPE_PROG);Blockcnt++;
写完以后的动作:
/* Lock program memory */
FLASH->IAPSR = ~0x02;
/* Lock data memory */
FLASH->IAPSR = ~0x08;

跳转到起始位置,相当于重启:
//reset stack pointer (lower byte - because compiler decreases SP with some bytes)
_asm("LDW X, SP ");
_asm("LD A, $FF");
_asm("LD XL, A ");
_asm("LDW SP, X ");

使用特权

评论回复
18
sed2003|  楼主 | 2012-11-16 16:44 | 只看该作者
本帖最后由 sed2003 于 2012-11-16 16:48 编辑

16# gaoyueping
我就放在#pragma section(FLASH_CODE)里,请你看看对不对?
#include "sys.h"

#pragma section(FLASH_CODE)

static u8 *ReceivedData;
static u8 FlashBuf[128];
....
void  UpdateUartTx(uchar dat)
{...}
void Transmit(uchar *p,U8 len)
{...}
void Receive(u8* ReceivedData)
{...}
...
void MCUUpdateCodeProc(void)
{
  Transmit(); //省略形参
  ReceivedData = Receive();//省略形参
  FLASH_EraseBlock(blockcnt,FLASH_MEMTYPE_PROG);
  FLASH_ProgramBlock(blockcnt,FLASH_MEMTYPE_PROG,FLASH_PROGRAMMODE_STANDARD,FlashBuf);
  FLASH_WaitForLastOperation(FLASH_MEMTYPE_PROG);
Blockcnt++;
}

#pragma section()

使用特权

评论回复
19
gaoyueping| | 2012-11-16 17:57 | 只看该作者
这样做不能开中断.而且不能查看RAM内如何运行,本人还挂掉过一块MCU。
本人做的是用中断收发,但是接收发送数据及处理数据等函数放在FLASH里,通过LINK文件定位函数在8080地址开始的几K空间,做好升级后,这部分是不修改的,只有用户那部分会有修改,用户部分被定位在后续的FLASH几十K空间内,通过编程序工具烧录第一次后就可以IAP升级,升级时只升后面部分。这种做法已经通过验证。而且这样做不用拷贝到RAM里。

使用特权

评论回复
20
sed2003|  楼主 | 2012-11-18 08:37 | 只看该作者
我这种方式是没有开中断。的确在RAM里无法查看运行动作。
你用中断来做,能保证在MCU已经在应用程序里跳出来执行吗?请问gaoyueping你可不可以发一个例子给我借鉴一下?我的邮箱:sed2003@126.com。现在没任何思路了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

34

帖子

0

粉丝