AVR BAD MEMORY allocation

Go To Last Post
35 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guys, 

 

I am trying to figure out what is the thing with my MCU - 1284p . So the scenario is like this. I made a program that sends commands to a SIM module . If I upload the program without the bootloader on the MCU, the program works fine and I have no memory flows. As soon as i upload with the bootloader the program starts to work bad. After days of trial I can't figure it out. I extracted some screenshots maybe someone will give me a hint. The bootloader had in the first try allocated 4096 bytes and the memory after I read it from the MCU looks like this.

 

 

The first thing was to shrink the bootloader memory so I modified it at half, meaning 2048 bytes. The allocation looks the same and the last command is not written into memory, if you look in the picture it is  rate failed  . . .  AT it should be "AT+CGNSCMD=0,\"$PMTK300,200,0,0,0,0*2F\"" .

 

The hex file read from the MCU with the modification to the bootloader looks like this.

 

 

And the problem from where it started it is in the last picture where the terminal shows what I actually sends the MCU to the SIM868 module.

 


 

I checked everything from memory allocation to bad pointers etc.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nikel1992 wrote:
If I upload the program without the bootloader on the MCU, the program works fine and I have no memory flows. As soon as i upload with the bootloader the program starts to work bad

So have you accounted for the memory occupied by the bootloader?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As i build my main program the stats for the program are.

 

 Program Memory Usage     :    65194 bytes   49.7 % Full
 Data Memory Usage         :    10383 bytes   63.4 % Full
 EEPROM Memory Usage     :    675 bytes   16.5 % Full

 

The bootloader allocated memory is 2048 bytes right now. The bootloader is avrubd.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Allocation is fine but what about the locations used? Where does your application start and end? Where does the bootloader start and end?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The fuse bits for the MCU, more exactly the BOOTSZ is for 4096 words. The bootloader in bootcfg looks like this. 

#ifndef _BOOTCFG_H_
#define _BOOTCFG_H_        1

//define uart buffer's length
#define BUFFERSIZE         16

//system clock(Hz)
#ifndef F_CPU
#define F_CPU              14745600UL
#endif

//baudrate
#define BAUDRATE           115200

//Boot section start address(byte)
//define BootStart to 0 will disable this function
#define BootStart          2 * 0xF000UL

//verify flash's data while write
//ChipCheck will only take effect while BootStart enable also
#define ChipCheck          0

//In SafeMode, it will not jump to user application till update successfully
#define SafeMode           1

//In SafeMode, it will set a flag in EEPROM
#define FlagAddr           E2END

//Bootloader launch  0:comport password  1:port level
#define LEVELMODE          0

#define LEVELPORT          D
#define LEVELPIN           PD7
//port level  1:High  0:Low
#define PINLEVEL           0

//max wait password time = TimeOutCnt * timeclk
//timeout count
#define TimeOutCnt         30

//basic timer interval(ms)
#define timeclk            500

//max wait data time = TimeOutCntC * timeclk
//send 'C' command count
#define TimeOutCntC        30

//password length
#define CONNECTCNT         1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> If I upload the program without the bootloader on the MCU, the program works fine 

 

Load your program, make sure it runs fine, read the mcu, save to a hex file.

 

Load the bootloader, load your same app via bootloader, read the mcu. The only difference should be the addition of the bootloader at a record address of 0xF000 (the second one, after a hex record switch to the second 64k segment). Your app should be the same in both, and if not then you are doing something wrong.

 

Your app has not changed in either case, so should make no difference who loads it, and it should end up in the same place with the same code. Your strings are pretty close to 64k (assuming the hex records shown are in the first 64k, but we cannot see that), and if you crossed that 64k then your reading of the strings can go wrong if you didn't plan for that. Your size output may be misleading, and although it shows you are <64k, that may not include the .rodata section where your strings may be living.

 

Get a comparison to the 2 hex files, which should show where things may be going wrong.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:

> If I upload the program without the bootloader on the MCU, the program works fine 

 

Load your program, make sure it runs fine, read the mcu, save to a hex file.

 

Load the bootloader, load your same app via bootloader, read the mcu. The only difference should be the addition of the bootloader at a record address of 0xF000 (the second one, after a hex record switch to the second 64k segment). Your app should be the same in both, and if not then you are doing something wrong.

 

Your app has not changed in either case, so should make no difference who loads it, and it should end up in the same place with the same code. Your strings are pretty close to 64k (assuming the hex records shown are in the first 64k, but we cannot see that), and if you crossed that 64k then your reading of the strings can go wrong if you didn't plan for that. Your size output may be misleading, and although it shows you are <64k, that may not include the .rodata section where your strings may be living.

 

Get a comparison to the 2 hex files, which should show where things may be going wrong.

As soon as i get home i will test it. I will post the info where maybe someone else will need it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:

> If I upload the program without the bootloader on the MCU, the program works fine 

 

Load your program, make sure it runs fine, read the mcu, save to a hex file.

 

Load the bootloader, load your same app via bootloader, read the mcu. The only difference should be the addition of the bootloader at a record address of 0xF000 (the second one, after a hex record switch to the second 64k segment). Your app should be the same in both, and if not then you are doing something wrong.

 

Your app has not changed in either case, so should make no difference who loads it, and it should end up in the same place with the same code. Your strings are pretty close to 64k (assuming the hex records shown are in the first 64k, but we cannot see that), and if you crossed that 64k then your reading of the strings can go wrong if you didn't plan for that. Your size output may be misleading, and although it shows you are <64k, that may not include the .rodata section where your strings may be living.

 

Get a comparison to the 2 hex files, which should show where things may be going wrong.

 

So I got home and made some tests. The first test was mean to reduce a little bit the dimensions of some buffers. 

 

The first one has this hex where the strings are written. and also the stats for the used memory

Task "RunOutputFileVerifyTask"
                Program Memory Usage     :    65208 bytes   49.7 % Full
                Data Memory Usage         :    10663 bytes   65.1 % Full
                EEPROM Memory Usage     :    675 bytes   16.5 % Full

 

 

Now after shrinking the buffers, the hex file read from MCU looks like in the picture below and has the next stats before writing.

Task "RunOutputFileVerifyTask"
                Program Memory Usage     :    65202 bytes   49.7 % Full
                Data Memory Usage         :    9213 bytes   56.2 % Full
                EEPROM Memory Usage     :    675 bytes   16.5 % Full

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I also need to mention that the optimization level is Os . 

 

I tried also with other optimization levels and also tried to modify the bootloader section, but as soon as I modify the boot start and bootsz in fuses I can`t upload the program with success. I am not sure if it is my mistake or the avrubd has a problem regarding other dimensions of the bootloader.

At this moment I am facing two problems. The first one:

  • I can upload the hex file of the main program on the bootloader with bootstart 0xF000 and BOOTSZ 0xF00, but the program does not run correctly . ( using optimization Os)
  • I can't upload the hex file using other parameters for the bootloader like bootstart 0xFC00 and BOOTSZ 0xFC00 even though the bootloader runs without any problem.

 

I have also tried to use other optimization levels but I get other things working bad. If anyone can give me any hint I can post anything needed 

Last Edited: Tue. Apr 28, 2020 - 06:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) The snippets of HEX files that you're posting a pretty useless.  the "type 0" .hex file record only has a 16bit byte address.  Since your program includes more than 64k bytes, there needs to be a (probably) type 4 record in there as well, loading the high bytes of the address.

2) That's assuming all your tools are properly dealing with the >64k issues.  We're all assuming standard gcc compilers and binutils being used to compile and convert to .hex and so on, and a programming tool that deals with high addresses as well, but it could be that they're not, or you're not using them properly.

3) don't forget the "well known" mismatch between the byte addressing used by most of the tools ("-sections-start", etc) and the word addressing used by the Atmel documentation ("start of bootloader section")

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using AVRUB,  https://sites.google.com/site/shaoziyang/Home/avr/avr-universal-bootloadere  - this one. The program after compilation as I posted in the upper section are 

                Program Memory Usage     :    65202 bytes   49.7 % Full
                Data Memory Usage         :    9213 bytes   56.2 % Full
                EEPROM Memory Usage     :    675 bytes   16.5 % Full

 

I am not sure for the moment if AVRUB can handle  Extended Linear Address and can write in the next section. And even if I would know for sure it can`t handle I would not know how to solve it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are not doing quite what I said, and we not have gained much.

 

Try more simple- build your app, not booloader, the app that you said works ok. Open the hex file to determine how much space is actually being used by reading the hex records. The avr-size may be misleading if the string data ends up in the .rodata section. I don't know if that's the case, but when looking at the hex file you will find out. The hex record snippets you show do not tell anyone which 64 segment they are in (there is a shorter record that switches to another 64k segment). If you are into the second 64k, then it looks like you have no room for the bootloader, if its still in the first 64k, then there should be no problem. Which is why I previously suggested the comparison as it would easily show what is going on.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:

You are not doing quite what I said, and we not have gained much.

 

Try more simple- build your app, not booloader, the app that you said works ok. Open the hex file to determine how much space is actually being used by reading the hex records. The avr-size may be misleading if the string data ends up in the .rodata section. I don't know if that's the case, but when looking at the hex file you will find out. The hex record snippets you show do not tell anyone which 64 segment they are in (there is a shorter record that switches to another 64k segment). If you are into the second 64k, then it looks like you have no room for the bootloader, if its still in the first 64k, then there should be no problem. Which is why I previously suggested the comparison as it would easily show what is going on.

 

I did upload only the hex file of the program and the last address of written data is at FED0 in the first memory party. After a few more blank bytes I see the memory delimiter.:020000021000EC

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nikel1992 wrote:
.:020000021000EC
Which is a 20 bit offset record. So the 4 digit addr fields that follow should be interpreted as 1???? rather than 0????. Does the user of tihs iHex "know" this ? (I'm not going to re-read this entire thread to find out I'm afraid).

 

EDIT: I followed the link in #11 but, having looked at the code, it's not clear to me what B/L protocol this uses and hence how it is driven from the PC side. The web page does not explain this well. As far as I can see the bootloader is never sent the start address so it just does:

  FlashAddr = 0;
  do
  {
    packNO++;
    ch =  WaitCom();                          //get package number
    cl = ~WaitCom();
    if ((packNO == ch) && (packNO == cl))
    {
      for(li = BUFFERSIZE; li > 0; li--)      //receive a full data frame
      {
        buf[bufptr++] = WaitCom();
      }
      crch = WaitCom();                       //get checksum
      crcl = WaitCom();
      crc16(&buf[bufptr - BUFFERSIZE]);       //calculate checksum
      if((crch == ch) && (crcl == cl))
      {
#if BootStart
        if(FlashAddr < BootStart)             //avoid write to boot section
        {
#endif

#if Decrypt
          DecryptBlock(&buf[bufptr - BUFFERSIZE], BUFFERSIZE); //decrypt buffer
#endif

#if (BUFFERSIZE <= SPM_PAGESIZE)
          if(bufptr >= SPM_PAGESIZE)          //Flash page full, write flash page;otherwise receive next frame
          {                                   //receive multi frames, write one page
            write_one_page(buf);              //write data to Flash
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr = 0;
          }
#else
          while(bufptr > 0)                   //receive one frame, write multi pages
          {
            write_one_page(&buf[BUFSIZE - bufptr]);
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr -= SPM_PAGESIZE;
          }
#endif

This starts at "FlashAddr = 0" then keeps doing "FlashAddr += SPM_PAGESIZE" so it doesn't seem to have any concept of data addressing??

Last Edited: Wed. Apr 29, 2020 - 08:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

nikel1992 wrote:
.:020000021000EC
Which is a 20 bit offset record. So the 4 digit addr fields that follow should be interpreted as 1???? rather than 0????. Does the user of tihs iHex "know" this ? (I'm not going to re-read this entire thread to find out I'm afraid).

 

EDIT: I followed the link in #11 but, having looked at the code, it's not clear to me what B/L protocol this uses and hence how it is driven from the PC side. The web page does not explain this well. As far as I can see the bootloader is never sent the start address so it just does:

  FlashAddr = 0;
  do
  {
    packNO++;
    ch =  WaitCom();                          //get package number
    cl = ~WaitCom();
    if ((packNO == ch) && (packNO == cl))
    {
      for(li = BUFFERSIZE; li > 0; li--)      //receive a full data frame
      {
        buf[bufptr++] = WaitCom();
      }
      crch = WaitCom();                       //get checksum
      crcl = WaitCom();
      crc16(&buf[bufptr - BUFFERSIZE]);       //calculate checksum
      if((crch == ch) && (crcl == cl))
      {
#if BootStart
        if(FlashAddr < BootStart)             //avoid write to boot section
        {
#endif

#if Decrypt
          DecryptBlock(&buf[bufptr - BUFFERSIZE], BUFFERSIZE); //decrypt buffer
#endif

#if (BUFFERSIZE <= SPM_PAGESIZE)
          if(bufptr >= SPM_PAGESIZE)          //Flash page full, write flash page;otherwise receive next frame
          {                                   //receive multi frames, write one page
            write_one_page(buf);              //write data to Flash
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr = 0;
          }
#else
          while(bufptr > 0)                   //receive one frame, write multi pages
          {
            write_one_page(&buf[BUFSIZE - bufptr]);
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr -= SPM_PAGESIZE;
          }
#endif

This starts at "FlashAddr = 0" then keeps doing "FlashAddr += SPM_PAGESIZE" so it doesn't seem to have any concept of data addressing??

Regarding the BL, i modified the code so that it can be able to send data. Regarding the addressing it parses the necessary files and writes in memory incrementaly, as I understand from the code.

Last Edited: Wed. Apr 29, 2020 - 09:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nikel1992 wrote:
i modified the code so that it can be able to send data.
Well isn't that the bit we need to actually see then??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The only thing I modified is in  buffersize from 128 to 16, because the BLE can handle only 16 bytes once. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Load your app via the bootloader, then read the mcu to see what the bootloader actually programmed. You can compare the hex files, one of course will also have the bootloader, but both will have the app and that part should be identical. Either they are identical, or they are not. This will also most likely point out what is going wrong, simply by looking at the hex files.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

curtvm wrote:
You can compare the hex files
Just to warn that sometimes that is not so easy. If one system happens to have used :10 and the other :20 (say) then a text comparison is close to impossible. Personally I'd be tempted to "avr-objcopy -I ihex -O binary filein.hex fileout.bin" in each case then use the most excellent "vbindiff" ( https://www.cjmweb.net/vbindiff/ ) to compare the binaries.

 

For example if I start with these two:

D:\test\test\Debug>type file1.hex
:1000000045C000004BC0000049C0000047C00000D0
:1000100045C0000043C0000041C000003FC00000D8
:100020003DC000003BC0000039C0000037C00000E8
:1000300035C0000033C0000031C000002FC00000F8
:100040002DC000002BC0000029C0000027C0000008
:1000500025C0000023C0000021C000001FC0000018
:100060001DC000001BC0000019C0000017C0000028
:1000700015C0000013C0000011C000000FC0000038
:100080000DC000000BC0000009C0000011241FBEFD
:10009000CFEFD0E4DEBFCDBF02D004C0B1CF85E545
:0800A00085B9FECFF894FFCFF3
:00000001FF

D:\test\test\Debug>type file2_narrow.hex
:020000040000FA
:0100000045BA
:01000100C03E
:0100020000FD
:0100030000FC
:010004004BB0
:01000500C03A
:0100060000F9
:0100070000F8
:0100080049AE
:01000900C036
:01000A0000F5
:01000B0000F4
:01000C0047AC
:01000D00C032
:01000E0000F1
:01000F0000F0
:0100100045AA
:01001100C02E
:0100120000ED
:0100130000EC
:0100140043A8
:01001500C02A
:0100160000E9
:0100170000E8
:0100180041A6
:01001900C026
:01001A0000E5
:01001B0000E4
:01001C003FA4
:01001D00C022
:01001E0000E1
:01001F0000E0
:010020003DA2
:01002100C01E
:0100220000DD
:0100230000DC
:010024003BA0
:01002500C01A
:0100260000D9
:0100270000D8
:01002800399E
:01002900C016
:01002A0000D5
:01002B0000D4
:01002C00379C
:01002D00C012
:01002E0000D1
:01002F0000D0
:01003000359A
:01003100C00E
:0100320000CD
:0100330000CC
:010034003398
:01003500C00A
:0100360000C9
:0100370000C8
:010038003196
:01003900C006
:01003A0000C5
:01003B0000C4
:01003C002F94
:01003D00C002
:01003E0000C1
:01003F0000C0
:010040002D92
:01004100C0FE
:0100420000BD
:0100430000BC
:010044002B90
:01004500C0FA
:0100460000B9
:0100470000B8
:01004800298E
:01004900C0F6
:01004A0000B5
:01004B0000B4
:01004C00278C
:01004D00C0F2
:01004E0000B1
:01004F0000B0
:01005000258A
:01005100C0EE
:0100520000AD
:0100530000AC
:010054002388
:01005500C0EA
:0100560000A9
:0100570000A8
:010058002186
:01005900C0E6
:01005A0000A5
:01005B0000A4
:01005C001F84
:01005D00C0E2
:01005E0000A1
:01005F0000A0
:010060001D82
:01006100C0DE
:01006200009D
:01006300009C
:010064001B80
:01006500C0DA
:010066000099
:010067000098
:01006800197E
:01006900C0D6
:01006A000095
:01006B000094
:01006C00177C
:01006D00C0D2
:01006E000091
:01006F000090
:01007000157A
:01007100C0CE
:01007200008D
:01007300008C
:010074001378
:01007500C0CA
:010076000089
:010077000088
:010078001176
:01007900C0C6
:01007A000085
:01007B000084
:01007C000F74
:01007D00C0C2
:01007E000081
:01007F000080
:010080000D72
:01008100C0BE
:01008200007D
:01008300007C
:010084000B70
:01008500C0BA
:010086000079
:010087000078
:01008800096E
:01008900C0B6
:01008A000075
:01008B000074
:01008C001162
:01008D00244E
:01008E001F52
:01008F00BEB2
:01009000CFA0
:01009100EF7F
:01009200D09D
:01009300E488
:01009400DE8D
:01009500BFAB
:01009600CD9C
:01009700BFA9
:010098000265
:01009900D096
:01009A000461
:01009B00C0A4
:01009C00B1B2
:01009D00CF93
:01009E008AD7
:01009F00EA76
:0100A00085DA
:0100A100B9A5
:0100A200FE5F
:0100A300CF8D
:0100A400F863
:0100A50094C6
:0100A600FF5A
:0100A700CF89
:00000001FF

which are virtually the same thing with just one very subtle difference then in this form it's very difficult to spot what that difference is. But converting each to BIN and then comparing...

D:\test\test\Debug>avr-objcopy -I ihex -O binary file1.hex file1.bin

D:\test\test\Debug>avr-objcopy -I ihex -O binary file2_narrow.hex file2_narrow.bin

D:\test\test\Debug>vbindiff file1.bin file2_narrow.bin

which reveals:

 

 

So it was simply a

PORTB = 0x55;

that became a

PORTB = 0xAA;

(for this demo I "faked" the file difference with srec_cat and "-line-length=10" but the point is that two different HEX creators looking at the data can some up with things that, on the surface appear to be radically different).

 

Last Edited: Wed. Apr 29, 2020 - 03:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> If one system happens to have used :10 and the other :20

 

I would assume he's using the same program to read either one, so will be the same format, and will be reading the whole mcu flash in both cases so will also be the same length. Described back in post #6, but I guess it must be hard to do.

 

Maybe I assume too much, and he cannot read the mcu to a hex file. I don't know. There is a screenshot where he is setting the fuses, so I assume has some friendly ide running, which I'm sure can handle reading the mcu.

 

Its not complicated. App works, read mcu. Bootloader installed, loads same app, doesn't work, read mcu. Compare what is different by looking at the hex files.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I retried to do as you said and compared the versions, the hex file uploaded with the STK500 and after that with the bootloader. In the left is the hex uploaded with the bootloader on there right is the hex uploaded with the STK.

 

 

Now, I will upload again the strings file from those addresses.

 

In the first picture is that part of hex where the string resides for the hex file uploaded with the STK.

 

In the next picture is the part of the hex where the strings are, but with bootloader upload.

 

 

Another thing that I thought I need to check is the input from the bootloader, I mean what comes through Bluetooth, maybe the application does not send the entire hex, but it seems It does have no problem.

 

 

 

0xFDF0 seems to be the last address at which it can write. The next try wil be with a smaller program.

 

Last Edited: Wed. Apr 29, 2020 - 05:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the code there's that test that the bootloader is not overwriting itself. Could it be this is not considering > 64K, that is that it's working in 16 bits when it needs to 32 bits?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

In the code there's that test that the bootloader is not overwriting itself. Could it be this is not considering > 64K, that is that it's working in 16 bits when it needs to 32 bits?

 

I don`t understand what you mean. I can investigate, but I don`t understand what you mean by overwriting. And where I should look.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did one more test with a program which has a very little dimension 176 bytes. And even if I receive the update success string, the  MCU does not have anything in memory. I presume that the problem is with the memory writing functions. If I don`t get a certain chunk of bytes It won`t write it to memory.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not near a PC with Zip file right now but there's some kind of barrier check to ensure the writing code is below a boundary address. I'm suggesting that may only cater for sub 64K boundaries. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
      for(li = BUFFERSIZE; li > 0; li--)      //receive a full data frame
      {
        buf[bufptr++] = WaitCom();
      }
      //putstr("ajuns4");    //send "Z"
      crch = WaitCom();                       //get checksum
      crcl = WaitCom();
     // putstr("ajuns5");    //send "Z"
      crc16(&buf[bufptr - BUFFERSIZE]);       //calculate checksum
      if((crch == ch) && (crcl == cl))
      {
      //  putstr("ajuns6");    //send "T"
#if BootStart
        if(FlashAddr < BootStart)             //avoid write to boot section
        {
#endif
        //	putstr("ajuns7"); 
#if Decrypt
          DecryptBlock(&buf[bufptr - BUFFERSIZE], BUFFERSIZE); //decrypt buffer
#endif

#if (BUFFERSIZE <= SPM_PAGESIZE)
          if(bufptr >= SPM_PAGESIZE)          //Flash page full, write flash page;otherwise receive next frame
          {                                   //receive multi frames, write one page
            write_one_page(buf);              //write data to Flash
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr = 0;
          }
          #else
          while(bufptr > 0)                   //receive one frame, write multi pages
          {
            write_one_page(&buf[BUFSIZE - bufptr]);
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr -= SPM_PAGESIZE;
          }
#endif

I think this part of code is the one with problems. Even though te bootloader gives the possibility to change the BUFFER SIZE I think that by changing it I have a problem with the write flash. My thought is that the last page is incomplete and this causes the bootloader not to write it. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The hex shows the last page is not being written (0xFE00 is the start of a flash page), so you need to figure out why the last page is not being written.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:

The hex shows the last page is not being written (0xFE00 is the start of a flash page), so you need to figure out why the last page is not being written.

 

Exactly the only thing is that I don`t know how to do it for the moment :D

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is in the source file-

 

//receive buffer' size will not smaller than SPM_PAGESIZE

 

 

If you are using 16, that is less than a page of course. That bootloader code is hard to read, but it looks like a page is written only when a page of data is stored, and in the process it also looks like your bufptr then also goes outside the bounds of the array (overwriting maybe something important in ram, maybe not). Which is probably why they made the comment to keep the buffer size no smaller than page size. Use the buffer size they want, and try again. You may also end up needing to pad the data to finish the last page.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I download winzip and notepad++ on this tablet so I could look at their zipped code again. It was the test "if FlashAddr < BootStart" that I thought might be suspicious but I see that if FLASHEND greater than 64K then FlashAddr is widened to ulong. Also I found BootStart as a #define in bootcfg.h and it's defined as a UL constant so the comparison should not be truncated to 16bit.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
efine in bootcfg.h and it's defined as a UL constant so the comparison should not be truncated to 16bit

 

I have tested out different things of truncated variables and I don`t think that is the problem, as I am looking over and over the code what I think is that when a page is incomplete it won`t be written into memory. So further thinking I have to solutions :

1. To try to add padding if the page is incomplete, but from the bootloader side I don`t know when this happens.

2. To add padding from application side, so everytime I upload an hex to an app to fill out the padding to be exactly one pagesize.

 

As I use the bootloader application as soon as I Upload the hex file it shows me how many packages I have got, in my case 4075. Tomorow I will modify it and I will add the padding to 4096 packets. I presume that this is the number that fills also the last frame.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shame you don't have a JTAG as you'd be able to see what's going wrong in about 2 minutes!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Shame you don't have a JTAG as you'd be able to see what's going wrong in about 2 minutes!

 

You know what is amusing. I don`t have any more pins, because I would definitely use a JTAG. I used the JTAG pins for other operations. Probably in the near future I will change one another MCU and I am thinking STM32 or NXP MCU. But for the moment no clue.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have the buffer size set to 16, and you loop to fill that buffer

      for(li = BUFFERSIZE; li > 0; li--)      //receive a full data frame
      {
        buf[bufptr++] = WaitCom();
      }

but now the page is not written until bufptr reaches the page size, so until bufptr (index into buf) reaches 512, there is no page write. After the page write bufptr is reset to 0.




          if(bufptr >= SPM_PAGESIZE)          //Flash page full, write flash page;otherwise receive next frame
          {                                   //receive multi frames, write one page
            write_one_page(buf);              //write data to Flash
            FlashAddr += SPM_PAGESIZE;        //modify Flash page address
            bufptr = 0;
          }

 

Padding looks like the simple answer, but you are also running up bufptr (index into buffer) into ram space unknown to the compiler (buffer overrun). If there happens to be nothing important above buf[15] (buf[16] to buf[511]), then you may get lucky. Odds are that you are overwriting something that may be important. Just set the buffer size to SPM_PAGESIZE, change your 'frame' loop count to 16, pad your data to fill a 512byte block.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Finally solved it, the next challenge will be to see if it is able to write to the extended memory. I think anyone who uses this bootloader should make the modifications and maybe they will include it in a new version. I will post here exactly the part which I modified. A new char variable needs to be defined.

 

unsigned char LFEOT;

 

    if(cnt > 100)                               //too many error, abort update
      break;
    LFEOT =WaitCom();
  }
  
  while(LFEOT != XMODEM_EOT);
  WriteCom(XMODEM_ACK);
 
 if((bufptr < SPM_PAGESIZE) && (bufptr > 0 ) && (LFEOT == XMODEM_EOT))
          {
            while (bufptr < SPM_PAGESIZE){
               buf[bufptr++] = 0xFF;

            }
            write_one_page(buf);
            bufptr = 0;
            putstr("final"); 
          }