vdudouyt / stm8flash

program your stm8 devices with SWIM/stlinkv(1,2)
GNU General Public License v2.0
404 stars 183 forks source link

Writing outside of the lower 64K #36

Closed spth closed 7 years ago

spth commented 8 years ago

I did a bit further testing on chips with more than 32K (results in the README.md of my branch). It seems I cannot write outside the lower 32K of flash, i.e. I cannot write outside the lower 64K of the address space.

Philipp

welash commented 8 years ago

Out of curiosity, were you trying to write an address above 64k by using an intel hex file? I just looked at the intel hex code (to add the ability to create intel hex files on output) and it doesn't look like the current code handles the extended segment or extended linear address records from intel hex files that allow them to handle addresses above 64k. I don't think it would be hard to add these (basically just detect the record types and update an "offset" variable).

Unfortunately I don't have any parts with memory above 64k to test with.

I just came up with a quick and dirty patch for handling esa and ela records in intel hex files, and I am attaching it. If it solves your issue I can clean it up an commit it to my fork, along with support for reading out into an intel hex file for the larger devices.

diff --git a/ihex.c b/ihex.c
index 83e97e8..88e3c1b 100644
--- a/ihex.c
+++ b/ihex.c
@@ -23,7 +23,7 @@ static unsigned char checksum(unsigned char *buf, unsigned int length, int chunk

 int ihex_read(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int end) {
        fseek(pFile, 0, SEEK_SET);
-       unsigned int chunk_len, chunk_addr, chunk_type, i, byte, line_no = 0, greatest_addr = 0;
+       unsigned int chunk_len, chunk_addr, chunk_type, i, byte, line_no = 0, greatest_addr = 0, offset = 0;
        while(fgets(line, sizeof(line), pFile)) {
                line_no++;
                // Reading chunk header
@@ -32,6 +32,25 @@ int ihex_read(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int
                        ERROR2("Error while parsing IHEX at line %d\n", line_no);
                }
                // Reading chunk data
+               if(chunk_type == 2) // Extended Segment Address
+               {
+                       unsigned int esa;
+                       if(sscanf(&line[9],"%04x",&esa) != 1) {
+                               free(buf);
+                               ERROR2("Error while parsing IHEX at line %d\n", line_no);
+                       }
+                       offset = esa * 16;
+               }
+               if(chunk_type == 4) // Extended Linear Address
+               {
+                       unsigned int ela;
+                       if(sscanf(&line[9],"%04x",&ela) != 1) {
+                               free(buf);
+                               ERROR2("Error while parsing IHEX at line %d\n", line_no);
+                       }
+                       offset = ela * 65536;
+               }
+               
                for(i = 9; i < strlen(line) - 1; i +=2) {
                        if(sscanf(&(line[i]), "%02x", &byte) != 1) {
                                free(buf);
                                free(buf);
@@ -45,18 +64,18 @@ int ihex_read(FILE *pFile, unsigned char *buf, unsigned int start, unsigned int
                                // Respect chunk_len and do not capture checksum as data
                                break;
                        }
-                       if(chunk_addr < start) {
+                       if((chunk_addr + offset) < start) {
                                free(buf);
                                ERROR2("Address %04x is out of range at line %d\n", chunk_addr, line_no);
                        }
-                       if(chunk_addr + chunk_len > end) {
+                       if(chunk_addr + offset + chunk_len > end) {
                                free(buf);
                                ERROR2("Address %04x + %d is out of range at line %d\n", chunk_addr, chunk_len, line_no);
                        }
-                       if(chunk_addr + chunk_len > greatest_addr) {
-                               greatest_addr = chunk_addr + chunk_len;
+                       if(chunk_addr + offset + chunk_len > greatest_addr) {
+                               greatest_addr = chunk_addr + offset + chunk_len;
                        }
-                       buf[chunk_addr - start + (i - 9) / 2] = byte;
+                       buf[chunk_addr + offset - start + (i - 9) / 2] = byte;
                }
        }
spth commented 8 years ago

AFAIR, I was using a binary file. And looking at the stm8flash code, it seemed it can't handle addresses > 64K in the backends either.

Philipp

ghost commented 7 years ago

@vdudouyt What was the your source of USB protocol for STLinkV2.

It seems you are packing HI() and LO() parts of start address similar to: image

Instinticly I tried adding #define EX(x) (((x) & 0xff0000) >> 16)

stlink2_cmd(pgm, 0xf40a, 7, 0x00, 0x01, 0x00, EX(start), HI(start), LO(start), byte);

Does not seem to work! Thank you on the hints!!

ghost commented 7 years ago

I have started to capture USB packets. Now need to compare it to @vdudouyt code. I am flashing only one byte with ST Visual Programmer

  1. need to understand writing at address 0xFFFF (all sequences before actual byte transfer)
  2. comparing writing to 0xFFFF and 0x10000
  3. sequence until writting

I append a "Spreadsheet" 1byte_0x66_write_0xffff_0x10000_comparison.xlsx

Quick comparison: 0xFFFF: 00 02 00 00 F4 0A 00 01 00 00 FF FF 66 FF 00 00 00 00 00 00

0x10000: 00 02 00 00 F4 0A 00 01 00 01 00 00 66 FF 00 00 00 00 00 00

welash commented 7 years ago

Based on your comparison of the dumps, it looks to me like what you tried should have worked. (that is supplying the EX(start) as the byte before the HI part of the address. So it seems like if you changed the F40A and F40B commands to add that byte, things might "just work".

The only thing that looks a bit different is that they seem to have an extra FF in the buffer after the first byte. If you try reading 16 bits at 0xfffe and 0x10000 do they also append an FF

ghost commented 7 years ago

I cleaned comparison document a bit, deleted wait states 01 00 00 00, ? led toggle ? Next I will try to modify and compile stm8flash code to modify one byte in 0x10000 address, hardcoded

20170608_1byte_0x66_write_0xffff_0x10000_comparison.xlsx

ghost commented 7 years ago

Good news. I managed to write 1byte on address 0x10000 image

ghost commented 7 years ago

Writing to address over 64k works in latest commit: https://github.com/janezNov/stm8flash/commit/83040e2e5b88fa036ee33bf0288f0de3b8ddd308 Verification also WORKS! Test 128kB Actual data in 'zero' file.bin was /dev/urandom image

spth commented 7 years ago

Closing this issue. The fix has been merged, and I verified it works (see updated README in pull request #74)

Philipp