11/*
22 * This file is part of the Black Magic Debug project.
33 *
4- * Copyright (C) 2024 hardesk <hardesk @gmail.com>
4+ * Copyright (C) 2024-2026 hardesk <hardesk17 @gmail.com>
55 *
66 * This program is free software: you can redistribute it and/or modify
77 * it under the terms of the GNU General Public License as published by
2222#include "target_internal.h"
2323#include "buffer_utils.h"
2424#include "jep106.h"
25- #include "cortex .h"
25+ #include "cortexm .h"
2626
2727#define MSPM0_CONFIG_FLASH_DUMP_SUPPORT (CONFIG_BMDA == 1 || ENABLE_DEBUG == 1)
2828
3131#define TI_DEVID_MSPM0L_1227_2228 0xbb9fU /* MSPM0L[12]22[78]*/
3232#define TI_DEVID_MSPM0G 0xbb88U /* MSPM0G310[567], MSPM0G150[567], MSPM0G350[567] */
3333
34- #define MSPM0_SRAM_BASE 0x20000000U
35- #define MSPM0_FLASH_MAIN 0x00000000U
36- #define MSPM0_FLASH_NONMAIN 0x41c00000U /* One Sector, BANK0. Device boot configuration (BCR, BSL) */
37- #define MSPM0_FLASH_FACTORY 0x41c40000U /* One Sector, BANK0. Non modifiable */
38- #define MSPM0_FLASH_DATA 0x41d00000U
39- #define MSPM0_FLASH_SECTOR_SZ 1024U
34+ #define MSPM0_SRAM_BASE 0x20000000U
35+ #define MSPM0_FLASH_MAIN 0x00000000U
36+ #define MSPM0_FLASH_NONMAIN 0x41c00000U /* One Sector, BANK0. Device boot configuration (BCR, BSL) */
37+ #define MSPM0_FLASH_FACTORY 0x41c40000U /* One Sector, BANK0. Non modifiable */
38+ #define MSPM0_FLASH_DATA 0x41d00000U
39+ #define MSPM0_FLASH_SECTOR_SZ 1024U
40+ #define MSPM0_FLASH_WRITE_CHUNK_SZ MSPM0_FLASH_SECTOR_SZ
41+ #define MSPM0_FLASH_STUB_STACK_SIZE 0x20U
4042
4143#define MSPM0_FACTORYREGION_DEVICEID (MSPM0_FLASH_FACTORY + 0x4U)
4244#define MSPM0_FACTORYREGION_SRAMFLASH (MSPM0_FLASH_FACTORY + 0x18U)
8991typedef struct mspm0_flash {
9092 target_flash_s target_flash ;
9193 uint32_t banks ;
94+ uint32_t ram_size ; /* 0 if not enough ram to use stub flashing */
9295} mspm0_flash_s ;
9396
97+ static const uint16_t mspm0_flash_write_stub [] = {
98+ #include "flashstub/mspm0.stub"
99+ };
100+ #define STUB_BUFFER_BASE ALIGN(MSPM0_SRAM_BASE + sizeof(mspm0_flash_write_stub), 4)
101+
102+ static bool mspm0_flash_erase (target_flash_s * flash , target_addr_t addr , size_t length );
103+ static bool mspm0_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t length );
104+ static bool mspm0_mass_erase (target_s * target , platform_timeout_s * print_progess );
105+
94106#if MSPM0_CONFIG_FLASH_DUMP_SUPPORT
95107static bool mspm0_dump_factory_config (target_s * target , int argc , const char * * argv );
96108static bool mspm0_dump_bcr_config (target_s * target , int argc , const char * * argv );
@@ -102,10 +114,6 @@ static command_s mspm0_cmds_list[] = {
102114};
103115#endif
104116
105- static bool mspm0_flash_erase (target_flash_s * flash , target_addr_t addr , size_t length );
106- static bool mspm0_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t length );
107- static bool mspm0_mass_erase (target_s * target , platform_timeout_s * print_progess );
108-
109117#if MSPM0_CONFIG_FLASH_DUMP_SUPPORT
110118typedef struct conf_register {
111119 uint16_t reg_offset ;
@@ -185,20 +193,31 @@ static bool mspm0_dump_bcr_config(target_s *const target, const int argc, const
185193}
186194#endif
187195
188- static void mspm0_add_flash (target_s * const target , const uint32_t base , const size_t length , const uint32_t banks )
196+ static void mspm0_add_flash (
197+ target_s * const target , const uint32_t base , const size_t length , const uint32_t banks , uint32_t sram_size )
189198{
190199 mspm0_flash_s * const flash = calloc (1 , sizeof (* flash ));
191200 if (flash == NULL ) {
192201 DEBUG_WARN ("%s: calloc failed for %" PRIu32 " bytes\n" , __func__ , (uint32_t )length );
193202 return ;
194203 }
195204
205+ /* Decrease writesize until it fits within available RAM */
206+ uint32_t write_size = MSPM0_FLASH_WRITE_CHUNK_SZ ;
207+ uint32_t stub_plus = ALIGN (sizeof mspm0_flash_write_stub , 4 ) + MSPM0_FLASH_STUB_STACK_SIZE ;
208+ if (sram_size >= stub_plus ) {
209+ uint32_t avail_ram = sram_size - stub_plus ;
210+ while (write_size > avail_ram )
211+ write_size >>= 1 ;
212+ flash -> ram_size = sram_size ;
213+ }
214+
196215 flash -> banks = banks ;
197216 target_flash_s * target_flash = & flash -> target_flash ;
198217 target_flash -> start = base ;
199218 target_flash -> length = length ;
200219 target_flash -> blocksize = MSPM0_FLASH_SECTOR_SZ ;
201- target_flash -> writesize = 8U ;
220+ target_flash -> writesize = write_size ;
202221 target_flash -> erase = mspm0_flash_erase ;
203222 target_flash -> write = mspm0_flash_write ;
204223 target_flash -> erased = 0xffU ;
@@ -235,9 +254,9 @@ bool mspm0_probe(target_s *const target)
235254 MSPM0_FACTORYREGION_SRAMFLASH_DATAFLASH_SZ_SHIFT );
236255
237256 target_add_ram32 (target , MSPM0_SRAM_BASE , sram_size );
238- mspm0_add_flash (target , MSPM0_FLASH_MAIN , mainflash_size , main_num_banks );
257+ mspm0_add_flash (target , MSPM0_FLASH_MAIN , mainflash_size , main_num_banks , sram_size );
239258 if (dataflash_size != 0 )
240- mspm0_add_flash (target , MSPM0_FLASH_DATA , dataflash_size , 1U );
259+ mspm0_add_flash (target , MSPM0_FLASH_DATA , dataflash_size , 1U , sram_size );
241260
242261#if MSPM0_CONFIG_FLASH_DUMP_SUPPORT
243262 target_add_commands (target , mspm0_cmds_list , "MSPM0" );
@@ -257,7 +276,7 @@ static uint32_t mspm0_flash_wait_done(target_s *const target)
257276 status = target_mem32_read32 (target , MSPM0_FLASHCTL_STATCMD );
258277 if (platform_timeout_is_expired (& timeout ))
259278 return 0U ;
260- };
279+ }
261280
262281 return status ;
263282}
@@ -278,8 +297,10 @@ static void mspm0_flash_unprotect_sector(target_flash_s *const target_flash, con
278297 uint32_t mask = ~(1U << sector );
279298 target_mem32_write32 (target_flash -> t , MSPM0_FLASHCTL_CMDWEPROTA , mask );
280299 } else if (sector < 256U ) { /* 8 sectors per bit */
281- /* When main flash is single bank, PROTB covers sectors starting after PROTA which is 32k. In multibank case
282- * PROTB bits overlap PROTA and starts at sector 0. */
300+ /* Sectors affected by PROTB depend on the flash configuration. In single-bank
301+ * main flash, PROTB applies to sectors after those affected by PROTA
302+ * (that is, starting at sector 32). In multi-bank configurations, PROTA overlaps
303+ * PROTB, so PROTB applies starting at sector 0. */
283304 uint32_t start_protb_sector = mspm0_flash -> banks > 1U ? 0U : 32U ;
284305 uint32_t mask = ~(1U << ((sector - start_protb_sector ) >> 3U ));
285306 target_mem32_write32 (target_flash -> t , MSPM0_FLASHCTL_CMDWEPROTB , mask );
@@ -291,9 +312,7 @@ static void mspm0_flash_unprotect_sector(target_flash_s *const target_flash, con
291312
292313static bool mspm0_flash_erase (target_flash_s * const target_flash , const target_addr_t addr , const size_t length )
293314{
294- #ifdef DEBUG_TARGET_IS_NOOP
295315 (void )length ;
296- #endif
297316
298317 target_s * const target = target_flash -> t ;
299318
@@ -316,27 +335,19 @@ static bool mspm0_flash_erase(target_flash_s *const target_flash, const target_a
316335static bool mspm0_flash_write (
317336 target_flash_s * const target_flash , target_addr_t dest , const void * const src , const size_t length )
318337{
319- #ifdef DEBUG_TARGET_IS_NOOP
320- (void )length ;
321- #endif
322-
323338 target_s * const target = target_flash -> t ;
339+ mspm0_flash_s * flash = (mspm0_flash_s * )target_flash ;
340+ if (flash -> ram_size == 0 )
341+ return false;
324342
325- mspm0_flash_unprotect_sector (target_flash , dest );
326- target_mem32_write32 (target , MSPM0_FLASHCTL_CMDTYPE , MSPM0_FLASHCTL_CMDTYPE_PROG | MSPM0_FLASHCTL_CMDTYPE_SZ_1WORD );
327- target_mem32_write32 (target , MSPM0_FLASHCTL_CMDCTL , 0U );
328- target_mem32_write32 (target , MSPM0_FLASHCTL_CMDADDR , dest );
329- target_mem32_write32 (target , MSPM0_FLASHCTL_BYTEN , 0xffffffffU );
330- target_mem32_write32 (target , MSPM0_FLASHCTL_CMDDATA0 , read_le4 ((const uint8_t * )src , 0U ));
331- target_mem32_write32 (target , MSPM0_FLASHCTL_CMDDATA1 , read_le4 ((const uint8_t * )src , 4U ));
332- target_mem32_write32 (target , MSPM0_FLASHCTL_CMDEXEC , MSPM0_FLASHCTL_CMDEXEC_EXEC );
343+ DEBUG_TARGET (
344+ "%s: Writing flash addr %08" PRIx32 " length %08" PRIx32 "\n" , __func__ , (uint32_t )dest , (uint32_t )length );
333345
334- const uint32_t status = mspm0_flash_wait_done (target );
335- if (!(status & MSPM0_FLASHCTL_STAT_CMDPASS ))
336- DEBUG_TARGET ("%s: Failed to write to flash, status %08" PRIx32 " addr %08" PRIx32 " length %08" PRIx32 "\n" ,
337- __func__ , status , dest , (uint32_t )length );
346+ target_mem32_write (target , MSPM0_SRAM_BASE , mspm0_flash_write_stub , sizeof (mspm0_flash_write_stub ));
347+ target_mem32_write (target , STUB_BUFFER_BASE , src , length );
338348
339- return status & MSPM0_FLASHCTL_STAT_CMDPASS ;
349+ return cortexm_run_stub (
350+ target , MSPM0_SRAM_BASE , dest , STUB_BUFFER_BASE , length , 0 , MSPM0_SRAM_BASE + flash -> ram_size );
340351}
341352
342353static bool mspm0_mass_erase (target_s * const target , platform_timeout_s * const print_progess )
0 commit comments