Commit 0637ec2d9f80d8cf8b07dd8756321d74a8f0e1b3
receivedSun, 21. Jul 2024, 18:59:47 (by user sx)
Sun, 21 Jul 2024 16:59:47 +0000 (18:59 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Sun, 21 Jul 2024 16:59:01 +0000 (18:59 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sun, 21 Jul 2024 16:59:01 +0000 (18:59 +0200)
4 files changed:
software/gdb-stub/.gdbinit-gdbstub
software/gdb-stub/src/bootloader.cpp
software/gdb-stub/src/gdb.cpp
software/gdb-stub/src/gdb.h

index ad7a6f7fed8a86d9b977b2a632cb33392038902f..f01898ed1c667cfa9aeef30f3f58a33b39337fe2 100644 (file)
@@ -1 +1,5 @@
 target remote :1234
+layout split
+focus cmd
+br *0
+
index 19d7efc7c87018509dcd53b89f5871a6a734e331..cab6c1bdd5afb15b1941ac664c71bd45c6ba8531 100644 (file)
@@ -307,13 +307,15 @@ namespace bootloader {
                                        toggleLedRed();
                                        TCNT1 = 0;
                                        gdb::serve500msTimer();
-                                       if (startProgram > 0 && !pgdb->status.isStopped) {
-                                               startProgram--;
+                                       if (pgdb->status.flashPage < 0) {
+                                               if (startProgram > 0 && !pgdb->status.isStopped) {
+                                                       startProgram--;
+                                               }
+                                               printChar(stdoutUart, '\r');
+                                               putUint8Hex(stdoutUart, startProgram);
+                                               printChar(stdoutUart, ' ');
+                                               printWelcomeMessage();
                                        }
-                                       printChar(stdoutUart, '\r');
-                                       putUint8Hex(stdoutUart, startProgram);
-                                       printChar(stdoutUart, ' ');
-                                       printWelcomeMessage();
                                }
                                int b = getc(stdinUart);
                                if ( b == 27) { // escape pressed
index da0ecf48520e556e304c18d1053a2129f4f19a0b..61978e26a3806501a3619c96127c0dcdf346f83d 100644 (file)
@@ -14,8 +14,9 @@
 
 #define GDB_DEBUG_UART 0
 // #define GDB_DEBUG_UART_REQUEST GDB_DEBUG_UART
-// #define GDB_DEBUG_UART_FLASHERASE GDB_DEBUG_UART
-// #define GDB_DEBUG_UART_FLASHWRITE GDB_DEBUG_UART
+#define GDB_DEBUG_UART_FLASHERASE GDB_DEBUG_UART
+#define GDB_DEBUG_UART_FLASHWRITE GDB_DEBUG_UART
+// #define GDB_DEBUG_UART_KILL_APPLICATION GDB_DEBUG_UART
 // #define GDB_DEBUG_UART_REQUEST_PACKET GDB_DEBUG_UART
 // #define GDB_DEBUG_UART_STOP_APPLICATION
 
@@ -91,7 +92,12 @@ namespace gdb {
        }
 
        __attribute__((noinline, naked)) void saveBreakpointRegs (struct Breakpoint *p) {
+               #ifndef __AVR_ATmega644P__
+                       #error wrong CPU -> check RAMEND, SFR
+               #endif
                asm volatile (
+                       ".equ SPL, 0x3d     \n"
+                       ".equ SPH, 0x3e     \n"
                        "push  r28          \n"
                        "push  r29          \n"
                        "movw  r28, r24     \n"  // bp -> Y
@@ -100,8 +106,8 @@ namespace gdb {
                        "std   Y+27, r27    \n"  // save original r27
                        "std   Y+26, r26    \n"  // save original r26
 
-                       "in    r30, 0x3d    \n"  // SPL -> ZL
-               "in    r31, 0x3e    \n"  // SPH -> ZH
+                       "in    r30, SPL     \n"  // SPL -> ZL
+               "in    r31, SPH     \n"  // SPH -> ZH
                        "ldd   r27, Z+1     \n"  // save original r29
                        "std   Y+29, r27    \n"
                        "ldd   r27, Z+2     \n"  // save original r28
@@ -172,10 +178,6 @@ namespace gdb {
                do {} while(1);
        }
 
-       // void xputsStop () {
-       //      xputsmem(gdb_StatusStop);
-       // }
-
        // ATTENTION: static data not initialized when application not started !!
        // ---> xputs('hello'); not working!!!
 
@@ -227,29 +229,98 @@ namespace gdb {
        //      return crc;
        // }
 
-       void eraseFlash (uint16_t addressStart, uint16_t addressEnd) {
-               bootloader::putln(0);
-               for (uint16_t addr = addressStart; addr < 0xe000 && addr <= addressEnd; addr += SPM_PAGESIZE) {
+       void eraseFlash (uint16_t addressStart, int32_t length) {
+               #ifndef __AVR_ATmega644P__
+                       #error wrong CPU -> check end of application flash area
+               #else
+                       // 0xffff - 0x2000 (bootloader size)
+                       #define MEM_APP_END 0xdfff
+               #endif
+               #ifdef GDB_DEBUG_UART_FLASHERASE
+                       bootloader::putln(GDB_DEBUG_UART);
+                       printdbg(GDB_DEBUG_ID_FLASH_ERASE);
+               #endif
+
+               for (uint16_t addr = addressStart; addr <= MEM_APP_END && length > 0; addr += SPM_PAGESIZE, length -= SPM_PAGESIZE) {
                        boot_spm_busy_wait();
                        eeprom_busy_wait();
                        boot_page_erase(addr);
                        #ifdef GDB_DEBUG_UART_FLASHERASE
-                               printdbg(GDB_DEBUG_ID_FLASH_ERASE);
-                               bootloader::printCharUint8Hex(GDB_DEBUG_UART, (uint8_t)(addr >> 8));
-                               bootloader::printCharUint8Hex(GDB_DEBUG_UART, (uint8_t)(addr));
-                               bootloader::putln(GDB_DEBUG_UART);
+                               bootloader::printChar(GDB_DEBUG_UART, ' ');
+                               bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(addr >> 8));
+                               bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(addr));
                        #endif
                }
+
                #ifdef GDB_DEBUG_UART_FLASHERASE
+                   bootloader::printChar(GDB_DEBUG_UART, ' ');
                        bootloader::printChar(GDB_DEBUG_UART, '@');
                        bootloader::putln(GDB_DEBUG_UART);
                #endif
        }
 
        void writeFlash (uint16_t *from, uint8_t size, uint16_t startAddress) {
-               for (uint8_t i = 0; i < size; i += 2) {
-                       boot_page_fill(startAddress + i, *from++);
+               #ifndef __AVR_ATmega644P__
+                       #error wrong CPU -> check end of application flash area
+               #else
+                       // 0xffff - 0x2000 (bootloader size)
+                       #define MEM_APP_END 0xdfff
+               #endif
+               struct gdb::Gdb *pgdb = GDB_PTR;
+               if (size <= 0 || startAddress > MEM_APP_END) {
+                       return;
+               }
+
+               if (pgdb->status.flashPage < 0) {
+                       pgdb->status.flashPage = startAddress / SPM_PAGESIZE;
+                       #ifdef GDB_DEBUG_UART_FLASHWRITE
+                               printdbg(GDB_DEBUG_ID_FLASH_WRITE);
+                       #endif
                }
+
+               uint16_t address = startAddress;
+               for (uint8_t i = 0; i < size &&  address <= MEM_APP_END; i += 2, address += 2) {
+                       if ( (int16_t)(address / SPM_PAGESIZE) != pgdb->status.flashPage) {
+                               boot_page_write(pgdb->status.flashPage * SPM_PAGESIZE);
+                               #ifdef GDB_DEBUG_UART_FLASHWRITE
+                                       bootloader::printChar(GDB_DEBUG_UART, ' ');
+                                       bootloader::printChar(GDB_DEBUG_UART, 'W');
+                                       bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)pgdb->status.flashPage);
+                               #endif
+                               boot_spm_busy_wait();
+                               pgdb->status.flashPage = address / SPM_PAGESIZE;
+                       }
+                       boot_page_fill(address, *from++);
+               }
+               #ifdef GDB_DEBUG_UART_FLASHWRITE
+                       bootloader::printChar(GDB_DEBUG_UART, ' ');
+                       bootloader::printChar(GDB_DEBUG_UART, 'F');
+                       bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(startAddress >> 8));
+                       bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(startAddress));
+                       bootloader::printChar(GDB_DEBUG_UART, '-');
+                       bootloader::putUint8Hex(GDB_DEBUG_UART, size);
+               #endif
+       }
+
+       void writeFlashDone () {
+               struct gdb::Gdb *pgdb = GDB_PTR;
+               if (pgdb->status.flashPage < 0) {
+                       return;
+               }
+               #ifdef GDB_DEBUG_UART_FLASHWRITE
+                       bootloader::printChar(GDB_DEBUG_UART, ' ');
+                       bootloader::printChar(GDB_DEBUG_UART, 'W');
+                       bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)pgdb->status.flashPage);
+               #endif
+               boot_page_write(pgdb->status.flashPage * SPM_PAGESIZE);
+               boot_spm_busy_wait();
+               boot_rww_enable();
+               #ifdef GDB_DEBUG_UART_FLASHWRITE
+                       bootloader::printChar(GDB_DEBUG_UART, ' ');
+                       bootloader::printChar(GDB_DEBUG_UART, '@');
+                       bootloader::putln(GDB_DEBUG_UART);
+               #endif
+               pgdb->status.flashPage = -1;
        }
 
        void writeFlashOld (uint8_t *from, uint8_t size, uint16_t toPage) {
@@ -270,8 +341,8 @@ namespace gdb {
                if (i < SPM_PAGESIZE) {
                        #ifdef GDB_DEBUG_UART_FLASHERASE
                                printdbg(GDB_DEBUG_ID_FLASH_ERASE);
-                               bootloader::printCharUint8Hex(GDB_DEBUG_UART, (uint8_t)(toAddress >> 8));
-                               bootloader::printCharUint8Hex(GDB_DEBUG_UART, (uint8_t)(toAddress));
+                               bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(toAddress >> 8));
+                               bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(toAddress));
                                #endif
                        eeprom_busy_wait();
                        boot_page_erase(toAddress);
@@ -282,8 +353,8 @@ namespace gdb {
                                boot_page_fill(toAddress + i, w);
                                #ifdef GDB_DEBUG_UART_FLASHWRITE
                                        bootloader::printChar(GDB_DEBUG_UART, ' ');
-                                       bootloader::printCharUint8Hex(GDB_DEBUG_UART, (uint8_t)(w >> 8));
-                                       bootloader::printCharUint8Hex(GDB_DEBUG_UART, (uint8_t)(w));
+                                       bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(w >> 8));
+                                       bootloader::putUint8Hex(GDB_DEBUG_UART, (uint8_t)(w));
                                #endif
                        }
                        boot_page_write(toAddress);
@@ -311,7 +382,7 @@ namespace gdb {
 
                } else if (pgdb->ctrl.kill) {
                        pgdb->ctrl.kill = 0;
-                       #ifdef GDB_DEBUG_UART
+                       #ifdef GDB_DEBUG_UART_KILL_APPLICATION
                                printdbgln(GDB_DEBUG_ID_KILL_APPLICATION);
                        #endif
                        if (pgdb->status.isAppStarted) {
@@ -329,7 +400,7 @@ namespace gdb {
                        if (!pgdb->status.isStopped) {
                                pgdb->ctrl.stop = 0;
                                if (pgdb->status.isAppStarted) {
-                               #ifdef GDB_DEBUG_UART
+                               #ifdef GDB_DEBUG_UART_STOP_APPLICATION
                                        printdbgln(GDB_DEBUG_ID_STOP_APPLICATION);
                                #endif
                                }
@@ -351,12 +422,14 @@ namespace gdb {
        void handleGdbRequest () {
                struct gdb::Gdb *pgdb = GDB_PTR;
                struct Buffer *p = &pgdb->buffer;
+
                if (p->state == execerr) {
                        xputc('-');
                        p->state = idle;
 
                } else if (p->state == exec) {
                        xputc('+');
+
                        #ifdef GDB_DEBUG_UART_REQUEST
                                #ifdef GDB_DEBUG_UART_REQUEST_PACKET
                                        printdbg(GDB_DEBUG_ID_REQUEST);
@@ -409,10 +482,6 @@ namespace gdb {
                                        // https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#index-g-packet
                                        // Read general registers (used on gdb command load)
                                        xputc('$');
-                                       bootloader::putUart0Byte('B');
-                                       bootloader::putUart0Byte('-');
-                                       bootloader::putUint8Hex(0, pgdb->status.isBreakpointValid);
-                                       bootloader::putln(0);
                                        if (pgdb->status.isBreakpointValid) {
                                                for (uint8_t i = 0; i < 32; i++) {
                                                        xputUint8Hex(pgdb->breakpoint.regs[i]);
@@ -581,22 +650,21 @@ namespace gdb {
                                        return;
 
                                } else if (i == 11 && sum == 0x8e) { // vFlashErase:
+                                       // https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html#index-vFlashErase-packet
+                                       // Direct the stub to erase length bytes of flash starting at addr.
                                        i = 12;
-                                       uint32_t addressStart, addressEnd;
+                                       uint32_t addressStart, length;
                                        i += parseHex(p->buffer, i, &addressStart);
                                        i++;
-                                       i += parseHex(p->buffer, i, &addressEnd);
+                                       i += parseHex(p->buffer, i, &length);
                                        pgdb->ctrl.kill = 1;
                                        executeControl();
-                                       eraseFlash((uint16_t)addressStart, (uint16_t)addressEnd);
+                                       eraseFlash((uint16_t)addressStart, (int32_t)length);
                                        xputsmem(gdb_OK);
                                        return;
 
                                } else if (i == 9 && sum == 0xea) { // vFlashDone
-                                       asm volatile (
-                                               "nop \n"
-                                       );
-                                       boot_rww_enable();
+                                       writeFlashDone();
                                        xputsmem(gdb_OK);
                                        return;
 
@@ -633,7 +701,7 @@ namespace gdb {
                                        xputsmem(gdb_vCont);
                                        return;
 
-                               } else if (i == 6 && sum == 0xa8) { // vCont;c
+                               } else if (i == 6 && sum == 0xa8 && p->buffer[1] == 'C') { // vCont;c (sum conflict with vFlashDone
                                        // https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#index-vCont-packet
                                        // Resume the inferior, specifying different actions for each thread.
                                        pgdb->ctrl.proceed = 1;
index dc30bc658db0af265ae2e0fbd92328bc79e7f8e0..c8dc84e349e52b6c0d7f4b45bf7ba9c96d072cd2 100644 (file)
@@ -88,9 +88,10 @@ namespace gdb {
        // void restart ()                                                   ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        void saveBreakpointRegs (struct Breakpoint *p)                    ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        void checkByteFromGdb ()                                          ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
-       void eraseFlash (uint16_t addressStart, uint16_t addressEnd)      ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
+       void eraseFlash (uint16_t addressStart, int32_t length)           ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        void writeFlashOld (uint8_t *from, uint8_t size, uint16_t toPage)    ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        void writeFlash (uint16_t *from, uint8_t size, uint16_t startAddress) ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
+       void writeFlashDone ()                                                ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        uint16_t updateModbusCRC (uint16_t crc, uint8_t b)                ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        uint16_t flashCrc (uint16_t startAddress, uint16_t endAddress)    ATT_OPTIMIZE_GDB ATT_SECTION_GDB;
        uint8_t createFlashCrc (PGM_P startAddress, size_t size)          ATT_OPTIMIZE_GDB ATT_SECTION_GDB;