diff --git a/fw/programmer/.gitignore b/fw/programmer/.gitignore deleted file mode 100644 index 6335249..0000000 --- a/fw/programmer/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.pio -.zed -.vscode -.cache -compile_commands.json diff --git a/fw/programmer/platformio.ini b/fw/programmer/platformio.ini deleted file mode 100644 index 1308496..0000000 --- a/fw/programmer/platformio.ini +++ /dev/null @@ -1,14 +0,0 @@ -; PlatformIO Project Configuration File -; -; Build options: build flags, source filter -; Upload options: custom upload port, speed and extra flags -; Library options: dependencies, extra library storages -; Advanced options: extra scripting -; -; Please visit documentation for the other options and examples -; https://docs.platformio.org/page/projectconf.html - -[env:default] -platform = https://github.com/maxgerhardt/platform-raspberrypi -framework = arduino -board = rpipico diff --git a/fw/programmer/src/bitbang_rvswdio.h b/fw/programmer/src/bitbang_rvswdio.h deleted file mode 100644 index 296630d..0000000 --- a/fw/programmer/src/bitbang_rvswdio.h +++ /dev/null @@ -1,1096 +0,0 @@ -// CH32V003 SWIO / CH32Vxxx / CH32Xxxx bit banging minimal reference -// implementation for bit banged IO or primitive IO. -// -// You will need to implement some of the basic functions. Example -// implementations for the functions on the ESP32-S2 are included. -// -// Copyright 2023-2024 <>< Charles Lohr, May be licensed under the MIT/x11 or -// NewBSD licenses. You choose. (Can be included in commercial and copyleft work) -// -// This file is original work. -// -// Mostly tested, though, not may not be perfect. Expect to tweak some things. -// The 003 code is pretty hardened, the other code may not be. -// -// Originally the only resources used to produce this file were publicly available docs -// and playing with the chips. The only leveraged tool was this: -// https://github.com/perigoso/sigrok-rvswd - -#ifndef _WCH_RVSWD_RVSWIO_H -#define _WCH_RVSWD_RVSWIO_H - -#include -#include - -// This is a hacky thing, but if you are laaaaazzzyyyy and don't want to add a 10k -// resistor, youcan do this. It glitches the line high very, very briefly. -// Enable for when you don't have a 10k pull-upand are relying on the internal pull-up. -// WARNING: If you set this, you should set the drive current to 5mA. This is -// only useful / needed if you are using the built-in functions. -//#define R_GLITCH_HIGH -//#define RUNNING_ON_ESP32S2 -//#define BB_PRINTF_DEBUG uprintf - -// You should interface to this file via these functions - -enum RiscVChip { - CHIP_UNKNOWN = 0x00, - CHIP_CH32V10x = 0x01, - CHIP_CH57x = 0x02, - CHIP_CH56x = 0x03, - CHIP_CH32V20x = 0x05, - CHIP_CH32V30x = 0x06, - CHIP_CH58x = 0x07, - CHIP_CH32V003 = 0x09, - CHIP_CH59x = 0x0b, - CHIP_CH643 = 0x0c, - CHIP_CH32X03x = 0x0d, - CHIP_CH32L10x = 0x0e, - CHIP_CH564 = 0x0f, - - CHIP_CH32V00x = 0x4e, - - CHIP_CH570 = 0x8b, - CHIP_CH585 = 0x4b, - CHIP_CH645 = 0x46, - CHIP_CH641 = 0x49, - CHIP_CH32V317 = 0x86, - CHIP_CH32M030 = 0x8e, -}; - -enum MemoryArea { - DEFAULT_AREA = 0, - PROGRAM_AREA = 1, - BOOTLOADER_AREA = 2, - OPTIONS_AREA = 3, - EEPROM_AREA = 4, - RAM_AREA = 5, -}; - -struct SWIOState -{ - int opmode; // 0 for undefined, 1 for SWIO, 2 for SWD - enum RiscVChip target_chip_type; - int sectorsize; - - // Zero the rest of the structure. - uint32_t statetag; - uint32_t lastwriteflags; - uint32_t currentstateval; - uint32_t flash_unlocked; - uint32_t autoincrement; - uint32_t clock_set; - uint32_t no_autoexec; -}; - -#define STTAG( x ) (*((uint32_t*)(x))) - - -// Provided Basic functions -static inline void ConfigureIOForRVSWD(void); -static inline void ConfigureIOForRVSWIO(void); -static void MCFWriteReg32( struct SWIOState * state, uint8_t command, uint32_t value ); -static int MCFReadReg32( struct SWIOState * state, uint8_t command, uint32_t * value ); - -// More advanced functions built on lower level PHY. -static int InitializeSWDSWIO( struct SWIOState * state ); -static int ReadWord( struct SWIOState * state, uint32_t word, uint32_t * ret ); -static int WriteWord( struct SWIOState * state, uint32_t word, uint32_t val ); -static int WaitForFlash( struct SWIOState * state ); -static int WaitForDoneOp( struct SWIOState * state ); -static int WriteBlock( struct SWIOState * iss, uint32_t address_to_write, uint8_t * data, uint8_t len, uint8_t erase ); -static int UnlockFlash( struct SWIOState * iss ); -static int EraseFlash( struct SWIOState * iss, uint32_t address, uint32_t length, int type ); -static void ResetInternalProgrammingState( struct SWIOState * iss ); -static int PollTerminal( struct SWIOState * iss, uint8_t * buffer, int maxlen, uint32_t leavevalA, uint32_t leavevalB ); - - -#define BDMDATA0 0x04 -#define BDMDATA1 0x05 -#define DMCONTROL 0x10 -#define DMSTATUS 0x11 -#define DMHARTINFO 0x12 -#define DMABSTRACTCS 0x16 -#define DMCOMMAND 0x17 -#define DMABSTRACTAUTO 0x18 -#define DMPROGBUF0 0x20 -#define DMPROGBUF1 0x21 -#define DMPROGBUF2 0x22 -#define DMPROGBUF3 0x23 -#define DMPROGBUF4 0x24 -#define DMPROGBUF5 0x25 -#define DMPROGBUF6 0x26 -#define DMPROGBUF7 0x27 - -#define DMCPBR 0x7C -#define DMCFGR 0x7D -#define DMSHDWCFGR 0x7E - -#ifndef __CH32V00x_H -#define FLASH_STATR_WRPRTERR ((uint8_t)0x10) -#define CR_PAGE_PG ((uint32_t)0x00010000) -#define CR_BUF_LOAD ((uint32_t)0x00040000) -#ifndef FLASH_CTLR_MER -#define FLASH_CTLR_MER ((uint16_t)0x0004) /* Mass Erase */ -#endif -#define CR_STRT_Set ((uint32_t)0x00000040) -#define CR_PAGE_ER ((uint32_t)0x00020000) -#define CR_BUF_RST ((uint32_t)0x00080000) -#endif - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// High level functions -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -static int InitializeSWDSWIO( struct SWIOState * state ) -{ - for( int timeout = 20; timeout; timeout-- ) - { - //printf( "CFG FOR RV\n" ); - ConfigureIOForRVSWIO(); - //printf( "DONE CFG FOR RV\n" ); - - // Careful - don't halt the part, we might just want to attach for a debug printf or something. - state->target_chip_type = CHIP_UNKNOWN; - state->sectorsize = 64; - - state->opmode = 1; // Try SWIO first - // First try to see if there is an 003. - MCFWriteReg32( state, DMSHDWCFGR, 0x5aa50000 | (1<<10) ); // Shadow Config Reg - MCFWriteReg32( state, DMCFGR, 0x5aa50000 | (1<<10) ); // CFGR (1<<10 == Allow output from slave) - MCFWriteReg32( state, DMSHDWCFGR, 0x5aa50000 | (1<<10) ); // Try twice just in case - MCFWriteReg32( state, DMCFGR, 0x5aa50000 | (1<<10) ); - - MCFWriteReg32( state, DMCONTROL, 0x00000001 ); - MCFWriteReg32( state, DMCONTROL, 0x00000001 ); - - // See if we can see a chip here... - uint32_t value = 0; - int readdm = MCFReadReg32( state, DMCFGR, &value ); - if( readdm == 0 && ( value & 0xffff0000 ) == ( 0x5aa50000 ) ) - { - BB_PRINTF_DEBUG( "Found RVSWIO interface.\n" ); - return 0; - } - - //printf( "CFG FOR SWD\n" ); - ConfigureIOForRVSWD(); - //printf( "DONE CFG FOR SWD\n" ); - - //Otherwise Maybe it's SWD? - state->opmode = 2; - - MCFWriteReg32( state, DMCONTROL, 0x00000001 ); - MCFWriteReg32( state, DMCONTROL, 0x00000001 ); - - uint32_t dmstatus, dmcontrol; - if( MCFReadReg32( state, DMSTATUS, &dmstatus ) != 0 || - MCFReadReg32( state, DMCONTROL, &dmcontrol ) != 0 ) - { - BB_PRINTF_DEBUG( "Could not read from RVSWD connection\n" ); - state->opmode = 0; - continue; - } - - // See if we can see a chip here... - if( ( ( ( dmstatus >> 8 ) & 0xf ) != 0x0c && - ( ( dmstatus >> 8 ) & 0xf ) != 0x03 ) || - dmcontrol != 1 ) - { - BB_PRINTF_DEBUG( "DMSTATUS invalid (Probably no RVSWD chip)\n" ); - state->opmode = 0; - continue; - } - - MCFWriteReg32( state, DMABSTRACTCS, 0x08000302 ); // Clear out abstractcs register. - BB_PRINTF_DEBUG( "Found RVSWD interface\n" ); - return 0; - } - BB_PRINTF_DEBUG( "TIMEOUT\n" ); - return -55; -} - -static int DetermineChipTypeAndSectorInfo( struct SWIOState * iss, uint8_t * reply) -{ - struct SWIOState * dev = iss; - if( iss->target_chip_type == CHIP_UNKNOWN || reply != NULL ) - { - if( iss->opmode == 0 ) - { - int r = InitializeSWDSWIO( iss ); - if( r ) return 0x11; - } - uint32_t rr; - if( MCFReadReg32( dev, DMHARTINFO, &rr ) ) - { - BB_PRINTF_DEBUG( "Error: Could not get hart info.\n" ); - return 0x12; - } - - MCFWriteReg32( dev, DMCONTROL, 0x80000001 ); // Make the debug module work properly. - MCFWriteReg32( dev, DMCONTROL, 0x80000001 ); // Initiate halt request. - - // Tricky, this function needs to clean everything up because it may be used entering debugger. - uint32_t old_data0; - MCFReadReg32( dev, BDMDATA0, &old_data0 ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - uint32_t old_x8; - MCFReadReg32( dev, BDMDATA0, &old_x8 ); - - uint32_t marchid = 0; - - MCFWriteReg32( dev, DMABSTRACTCS, 0x08000700 ); // Clear out any dmabstractcs errors. - - MCFWriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); - MCFWriteReg32( dev, DMCOMMAND, 0x00220000 | 0xf12 ); - MCFWriteReg32( dev, DMCOMMAND, 0x00220000 | 0xf12 ); // Need to double-read, not sure why. - MCFReadReg32( dev, BDMDATA0, &marchid ); - MCFWriteReg32( dev, DMPROGBUF0, 0x90024000 ); // c.ebreak <<== c.lw x8, 0(x8) - - uint32_t chip_id = 0; - uint32_t vendor_bytes = 0; - uint32_t sevenf_id = 0; - int read_protection = 0; - uint8_t ch5xx = 0; - MCFReadReg32( dev, 0x7f, &sevenf_id ); - - if( sevenf_id == 0 ) - { - // Need to load new progbuf because we're reading 1 byte now - MCFWriteReg32( dev, DMPROGBUF0, 0x00040403 ); // lb x8, 0(x8) - MCFWriteReg32( dev, DMPROGBUF1, 0x00100073 ); // c.ebreak - MCFWriteReg32( dev, BDMDATA0, 0x40001041 ); // Special chip ID location. - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &chip_id ); - chip_id = chip_id & 0xff; - - // Looks like a CH32V103 or a CH56x - if( chip_id == 0 ) - { - // First check for CH56x - MCFWriteReg32( dev, BDMDATA0, 0x40001001 ); - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &chip_id ); - MCFWriteReg32( dev, BDMDATA0, 0x40001002 ); // Special chip ID location. - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &vendor_bytes ); - - if( (vendor_bytes & 0xff) == 2 && ((chip_id & 0xff) == 65 || (chip_id & 0xff) == 69) ) - { - iss->target_chip_type = CHIP_CH56x; - chip_id = 0x500 | (chip_id & 0xff); - goto chip_identified; - } - - // Now actually check for CH32V103 - MCFWriteReg32( dev, DMPROGBUF0, 0x90024000 ); // c.ebreak <<== c.lw x8, 0(x8) - MCFWriteReg32( dev, BDMDATA0, 0x1ffff880 ); // Special chip ID location. - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &chip_id ); - MCFWriteReg32( dev, BDMDATA0, 0x1ffff884 ); // Special chip ID location. - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &vendor_bytes ); - - if( ((((vendor_bytes >> 16) & 0xff00) != 0x2500) && (((vendor_bytes >> 16) & 0xdf00) != 0x1500)) || chip_id != 0xdc78fe34 ) - { - uint32_t flash_obr = 0; - MCFWriteReg32( dev, BDMDATA0, 0x4002201c ); // Special chip ID location. - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &flash_obr ); - - if( (flash_obr & 3) == 2 ) - { - iss->target_chip_type = CHIP_CH32V10x; - iss->no_autoexec = 1; - iss->sectorsize = 128; - read_protection = 1; - chip_id = (3 << 12) | 0x103; - } - } - else - { - iss->target_chip_type = CHIP_CH32V10x; - iss->no_autoexec = 1; - iss->sectorsize = 128; - read_protection = -1; - chip_id = (3 << 12) | 0x103; - } - } - else - { - // Check for CH5xx - read_protection = -1; - if( (chip_id & 0xf0) == 0x90 ) - { - uint32_t sevenc = 0; - MCFReadReg32( dev, DMCPBR, &sevenc ); - if((sevenc & 0x30000) == 0) - { - iss->target_chip_type = CHIP_CH59x; - iss->sectorsize = 256; - ch5xx = 1; - chip_id = 0x500 | chip_id; - } - else - { - iss->target_chip_type = CHIP_CH585; - iss->no_autoexec = 1; - iss->sectorsize = 256; - ch5xx = 1; - chip_id = 0x500 | 0x85; - } - } - else - { - if( chip_id == 0x70 || chip_id == 0x72 ) - { - iss->target_chip_type = CHIP_CH570; - iss->sectorsize = 4096; - ch5xx = 1; - chip_id = 0x500 | chip_id; - } - else if( chip_id == 0x71 || chip_id == 0x73 ) - { - iss->target_chip_type = CHIP_CH57x; - iss->no_autoexec = 1; - iss->sectorsize = 256; - ch5xx = 1; - chip_id = 0x500 | chip_id; - } - else if( chip_id == 0x82 || chip_id == 0x83 ) - { - iss->target_chip_type = CHIP_CH58x; - iss->no_autoexec = 1; - iss->sectorsize = 256; - ch5xx = 1; - chip_id = 0x500 | chip_id; - } - } - } - } - else - { - uint32_t masked_id = sevenf_id & 0xfff00000; - uint32_t masked_id2 = sevenf_id & 0xfff00f00; - if( masked_id == 0x3b00000 ) - { - iss->target_chip_type = CHIP_CH32M030; - iss->sectorsize = 256; - chip_id = (2 << 12) | 0x30; - } - else if( masked_id == 0x56400000 ) - { - iss->target_chip_type = CHIP_CH564; - iss->sectorsize = 256; - chip_id = 0x564; - } - else if( masked_id == 0x31700000 ) - { - iss->target_chip_type = CHIP_CH32V317; - iss->sectorsize = 256; - chip_id = (3 << 12) | 0x317; - } - else if( masked_id == 0x00200000 || masked_id == 0x00400000 || masked_id == 0x00600000 || masked_id == 0x00700000 ) - { - iss->target_chip_type = CHIP_CH32V00x; - iss->sectorsize = 256; - chip_id = (3 << 12) | (masked_id >> 20); - } - - if( masked_id2 == 0x64100500 ) - { - iss->target_chip_type = CHIP_CH641; - iss->sectorsize = 64; - chip_id = 0x641; - } - else if( masked_id2 == 0x64300600 ) - { - iss->target_chip_type = CHIP_CH643; - iss->sectorsize = 256; - chip_id = 0x643; - } - else if( masked_id == 0x64500000 ) - { - iss->target_chip_type = CHIP_CH645; - iss->sectorsize = 256; - chip_id = 0x645; - } - else if( masked_id2 == 0x3500600 ) - { - iss->target_chip_type = CHIP_CH32X03x; - iss->sectorsize = 256; - chip_id = (4 << 12) | 0x35; - } - else if( masked_id2 == 0x10300700 ) - { - iss->target_chip_type = CHIP_CH32L10x; - iss->sectorsize = 256; - chip_id = (1 << 12) | 0x103; - } - else if( masked_id2 == 0x300500 ) - { - iss->target_chip_type = CHIP_CH32V003; - iss->sectorsize = 64; - chip_id = (3 << 12) | 0x3; - } - - if( (sevenf_id & 0x20000500) == 0x20000500 || (sevenf_id & 0x30000500) == 0x30000500 ) - { - switch ((sevenf_id & 0xfff00000) >> 20) - { - case 0x203: - case 0x208: - iss->target_chip_type = CHIP_CH32V20x; - iss->sectorsize = 256; - break; - case 0x303: - case 0x305: - case 0x307: - iss->target_chip_type = CHIP_CH32V30x; - iss->sectorsize = 256; - break; - } - chip_id = (3 << 12) | (masked_id >> 20); - } - } - -chip_identified: - - if( read_protection == 0 ) - { - uint32_t one; - int two; - MCFWriteReg32( dev, BDMDATA0, 0x4002201c ); - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, &one ); - MCFWriteReg32( dev, BDMDATA0, 0x40022020 ); - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute. - WaitForDoneOp( dev ); - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Copy data from x8. - MCFReadReg32( dev, BDMDATA0, (uint32_t*)&two ); - - if( (one & 2) || two != -1 ) read_protection = 1; - } - - if( reply != NULL ) - { - reply[3] = sevenf_id >> 24; - reply[2] = sevenf_id >> 16; - reply[1] = sevenf_id >> 8; - reply[0] = sevenf_id; - reply[5] = chip_id >> 8; - reply[4] = chip_id; - if( read_protection == 1 ) reply[5] |= 0x80; - } - - // Cleanup - MCFWriteReg32( dev, BDMDATA0, old_x8 ); - MCFWriteReg32( dev, DMCOMMAND, 0x00231008 ); // Copy data to x8 - MCFWriteReg32( dev, BDMDATA0, old_data0 ); - iss->statetag = STTAG( "XXXX" ); -#if CH5xx_SUPPORT - if( ch5xx ) ch5xx_set_clock( dev, 0 ); -#endif - } - return 0; -} - -static int WaitForFlash( struct SWIOState * iss ) -{ - struct SWIOState * dev = iss; - - if( DetermineChipTypeAndSectorInfo( iss, NULL ) ) return -9; - - uint32_t rw, timeout = 0; - do - { - rw = 0; - ReadWord( dev, 0x4002200C, &rw ); // FLASH_STATR => 0x4002200C - } while( (rw & 1) && timeout++ < 2000); // BSY flag. - - WriteWord( dev, 0x4002200C, 0 ); - - if( rw & FLASH_STATR_WRPRTERR ) - return -44; - - if( rw & 1 ) - return -5; - - return 0; -} - - -static int WaitForDoneOp( struct SWIOState * iss ) -{ - int r; - uint32_t rrv; - int ret = 0; - int timeout = 1000; - struct SWIOState * dev = iss; - do - { - r = MCFReadReg32( dev, DMABSTRACTCS, &rrv ); - if( r ) return r; - if( timeout-- == 0 ) return -8; - } - while( rrv & (1<<12) ); - if( (rrv >> 8 ) & 7 ) - { - MCFWriteReg32( dev, DMABSTRACTCS, 0x00000700 ); - ret = -33; - } - return ret; -} - -static int StaticUpdatePROGBUFRegs( struct SWIOState * dev ) -{ - if( DetermineChipTypeAndSectorInfo( dev, NULL ) ) return -9; - - MCFWriteReg32( dev, DMABSTRACTAUTO, 0 ); // Disable Autoexec. - uint32_t rr; - MCFReadReg32( dev, DMHARTINFO, &rr ); - uint32_t data0offset = 0xe0000000 | ( rr & 0x7ff ); - MCFWriteReg32( dev, BDMDATA0, data0offset ); // DATA0's location in memory. (hard code to 0xe00000f4 if only working on the 003) - MCFWriteReg32( dev, DMCOMMAND, 0x0023100a ); // Copy data to x10 - MCFWriteReg32( dev, BDMDATA0, data0offset + 4 ); // DATA1's location in memory. (hard code to 0xe00000f8 if only working on the 003) - MCFWriteReg32( dev, DMCOMMAND, 0x0023100b ); // Copy data to x11 - MCFWriteReg32( dev, BDMDATA0, 0x4002200c ); //FLASH->STATR (note add 4 to FLASH->CTLR) - MCFWriteReg32( dev, DMCOMMAND, 0x0023100c ); // Copy data to x12 - - // This is not even needed on the v20x/v30x chips. But it won't harm us to set the register for simplicity. - // v003 requires bufload every word. - // x035 requires bufload every word in spite of what the datasheet says. - // CR_PAGE_PG = FTPG = 0x00010000 | CR_BUF_LOAD = 0x00040000 - MCFWriteReg32( dev, BDMDATA0, 0x00010000|0x00040000 ); - - MCFWriteReg32( dev, DMCOMMAND, 0x0023100d ); // Copy data to x13 - return 0; -} - -static void ResetInternalProgrammingState( struct SWIOState * iss ) -{ - iss->statetag = 0; - iss->lastwriteflags = 0; - iss->currentstateval = 0; - iss->flash_unlocked = 0; - iss->autoincrement = 0; - iss->clock_set = 0; -} - -static int ReadByte( struct SWIOState * iss, uint32_t address_to_read, uint8_t * data ) -{ - struct SWIOState * dev = iss; - int ret = 0; - iss->statetag = STTAG( "XXXX" ); - - MCFWriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec. - - // Different address, so we don't need to re-write all the program regs. - // lb x8,0(x9) // Read from the address. - MCFWriteReg32( dev, DMPROGBUF0, 0x00048403 ); // lb x8, 0(x9) - MCFWriteReg32( dev, DMPROGBUF1, 0x00100073 ); // c.ebreak - - MCFWriteReg32( dev, BDMDATA0, address_to_read ); - MCFWriteReg32( dev, DMCOMMAND, 0x00231009 ); // Copy data to x9 - MCFWriteReg32( dev, DMCOMMAND, 0x00241000 ); // Only execute. - MCFWriteReg32( dev, DMCOMMAND, 0x00221008 ); // Read x8 into DATA0. - - ret |= WaitForDoneOp( dev ); - iss->currentstateval = -1; - - uint32_t rr; - ret |= MCFReadReg32( dev, BDMDATA0, &rr ); - *data = rr; - return ret; -} - -static int ReadWord( struct SWIOState * iss, uint32_t address_to_read, uint32_t * data ) -{ - struct SWIOState * dev = iss; - int autoincrement = 1; - - if( address_to_read == 0x40022010 || address_to_read == 0x4002200C ) // Don't autoincrement when checking flash flag. - autoincrement = 0; - - if( iss->statetag != STTAG( "RDSQ" ) || address_to_read != iss->currentstateval || autoincrement != iss->autoincrement ) - { - if( iss->statetag != STTAG( "RDSQ" ) || autoincrement != iss->autoincrement ) - { - if( iss->statetag != STTAG( "WRSQ" ) ) - { - int r = StaticUpdatePROGBUFRegs( dev ); - if( r ) return r; - } - - MCFWriteReg32( dev, DMABSTRACTAUTO, 0 ); // Disable Autoexec. - - // c.lw x8,0(x11) // Pull the address from DATA1 - // c.lw x9,0(x8) // Read the data at that location. - MCFWriteReg32( dev, DMPROGBUF0, 0x40044180 ); - if( autoincrement ) - { - // c.addi x8, 4 - // c.sw x9, 0(x10) // Write back to DATA0 - - MCFWriteReg32( dev, DMPROGBUF1, 0xc1040411 ); - } - else - { - // c.nop - // c.sw x9, 0(x10) // Write back to DATA0 - - MCFWriteReg32( dev, DMPROGBUF1, 0xc1040001 ); - } - // c.sw x8, 0(x11) // Write addy to DATA1 - // c.ebreak - MCFWriteReg32( dev, DMPROGBUF2, 0x9002c180 ); - if( !iss->no_autoexec ) - MCFWriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec (not autoincrement) - iss->autoincrement = autoincrement; - } - - MCFWriteReg32( dev, BDMDATA1, address_to_read ); - if( !iss->no_autoexec ) - MCFWriteReg32( dev, DMCOMMAND, 0x00240000 ); // Execute. - - iss->statetag = STTAG( "RDSQ" ); - iss->currentstateval = address_to_read; - } - - if( iss->autoincrement ) - iss->currentstateval += 4; - - if( iss->no_autoexec ) { - MCFWriteReg32( dev, DMCOMMAND, 0x00240000 ); - } - - // Only an issue if we are curising along very fast. - int r = WaitForDoneOp( dev ); - if( r ) return r; - - r = MCFReadReg32( dev, BDMDATA0, data ); - return r; -} - -static int WriteByte( struct SWIOState * iss, uint32_t address_to_write, uint8_t data ) -{ - struct SWIOState * dev = iss; - int ret = 0; - iss->statetag = STTAG( "XXXX" ); - - MCFWriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec. - - // Different address, so we don't need to re-write all the program regs. - // sh x8,0(x9) // Write to the address. - MCFWriteReg32( dev, DMPROGBUF0, 0x00848023 ); // sb x8, 0(x9) - MCFWriteReg32( dev, DMPROGBUF1, 0x00100073 ); // c.ebreak - - MCFWriteReg32( dev, BDMDATA0, address_to_write ); - MCFWriteReg32( dev, DMCOMMAND, 0x00231009 ); // Copy data to x9 - MCFWriteReg32( dev, BDMDATA0, data ); - MCFWriteReg32( dev, DMCOMMAND, 0x00271008 ); // Copy data to x8, and execute program. - - ret |= WaitForDoneOp( dev ); - iss->currentstateval = -1; - return ret; -} - -static int WriteWord( struct SWIOState * iss, uint32_t address_to_write, uint32_t data ) -{ - struct SWIOState * dev = iss; - - int ret = 0; - - int is_flash = 0; - if( ( address_to_write & 0xff000000 ) == 0x08000000 || ( address_to_write & 0x1FFF0000 ) == 0x1FFF0000 ) - { - // Is flash. - is_flash = 1; - } - - if( iss->statetag != STTAG( "WRSQ" ) || is_flash != iss->lastwriteflags ) - { - int did_disable_req = 0; - - if( iss->statetag != STTAG( "WRSQ" ) ) - { - MCFWriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec. - did_disable_req = 1; - - if( iss->statetag != STTAG( "RDSQ" ) ) - { - int r = StaticUpdatePROGBUFRegs( dev ); - if( r ) return r; - } - - // Different address, so we don't need to re-write all the program regs. - // c.lw x8,0(x10) // Get the value to write. - // c.lw x9,0(x11) // Get the address to write to. - MCFWriteReg32( dev, DMPROGBUF0, 0x41844100 ); - // c.sw x8,0(x9) // Write to the address. - // c.addi x9, 4 - MCFWriteReg32( dev, DMPROGBUF1, 0x0491c080 ); - } - - if( is_flash && iss->target_chip_type == CHIP_CH32V10x) - { - // Special 16 bytes buffer write sequence for CH32V103 - MCFWriteReg32( dev, DMPROGBUF2, 0x0001c184 ); // c.sw x9,0(x11); c.nop; - MCFWriteReg32( dev, DMPROGBUF3, 0x9002e391 ); // c.bnez x15, 4; c.ebreak; - MCFWriteReg32( dev, DMPROGBUF4, 0x4200c254 ); // c.sw x13,4(x12); c.lw x8,0(x12); - MCFWriteReg32( dev, DMPROGBUF5, 0xfc758805 ); // c.andi x8, 1; c.bnez x8, -4; - MCFWriteReg32( dev, DMPROGBUF6, 0x90024781 ); // c.li x15, 0; c.ebreak; - } - else if( is_flash ) - { - // A little weird - we need to wait until the buf load is done here to continue. - // x12 = 0x4002200C (FLASH_STATR) - // - // c254 c.sw x13,4(x12) // Acknowledge the page write. (BUT ONLY ON x035 / v003) - // otherwise c.nop - // 4200 c.lw x8,0(x12) // Start checking to see when buf load is done. - // 8809 c.andi x8, 2 // Only look at WR_BSY (seems to be rather undocumented) - // 8805 c.andi x8, 1 // Only look at BSY if we're not on a v30x / v20x - // fc75 c.bnez x8, -4 - // c.ebreak - MCFWriteReg32( dev, DMPROGBUF2, 0x0001c184 ); - MCFWriteReg32( dev, DMPROGBUF3, - (iss->target_chip_type == CHIP_CH32V003 || iss->target_chip_type == CHIP_CH32V00x - || iss->target_chip_type == CHIP_CH32X03x || iss->target_chip_type == CHIP_CH32L10x - || iss->target_chip_type == CHIP_CH641 || iss->target_chip_type == CHIP_CH643) ? - 0x4200c254 : 0x42000001 ); - - MCFWriteReg32( dev, DMPROGBUF4, - (iss->target_chip_type == CHIP_CH32V20x || iss->target_chip_type == CHIP_CH32V30x ) ? - 0xfc758809 : 0xfc758805 ); - - MCFWriteReg32( dev, DMPROGBUF5, 0x90029002 ); - } - else - { - MCFWriteReg32( dev, DMPROGBUF2, 0x9002c184 ); // c.sw x9,0(x11); c.ebreak; - } - - MCFWriteReg32( dev, BDMDATA1, address_to_write ); - MCFWriteReg32( dev, BDMDATA0, data ); - - if( iss->no_autoexec ) - { - MCFWriteReg32( dev, DMCOMMAND, 0x00240000 ); // Execute. - } - else if( did_disable_req ) - { - MCFWriteReg32( dev, DMCOMMAND, 0x00240000 ); // Execute. - MCFWriteReg32( dev, DMABSTRACTAUTO, 1 ); // Enable Autoexec. - } - - iss->lastwriteflags = is_flash; - - iss->statetag = STTAG( "WRSQ" ); - iss->currentstateval = address_to_write; - } - else - { - if( address_to_write != iss->currentstateval ) - { - MCFWriteReg32( dev, BDMDATA1, address_to_write ); - } - MCFWriteReg32( dev, BDMDATA0, data ); - if( iss->no_autoexec ) - { - MCFWriteReg32( dev, DMCOMMAND, 0x00240000 ); // Execute. - } - } - if( is_flash ) - ret |= WaitForDoneOp( dev ); - - iss->currentstateval += 4; - - return ret; -} - -static int UnlockFlash( struct SWIOState * iss ) -{ - struct SWIOState * dev = iss; - - if( DetermineChipTypeAndSectorInfo( iss, NULL ) ) return -9; - - uint32_t rw; - ReadWord( dev, 0x40022010, &rw ); // FLASH->CTLR = 0x40022010 - if( rw & 0x8080 ) - { - - WriteWord( dev, 0x40022004, 0x45670123 ); // FLASH->KEYR = 0x40022004 - WriteWord( dev, 0x40022004, 0xCDEF89AB ); - WriteWord( dev, 0x40022008, 0x45670123 ); // OBKEYR = 0x40022008 - WriteWord( dev, 0x40022008, 0xCDEF89AB ); - WriteWord( dev, 0x40022024, 0x45670123 ); // MODEKEYR = 0x40022024 - WriteWord( dev, 0x40022024, 0xCDEF89AB ); - - ReadWord( dev, 0x40022010, &rw ); // FLASH->CTLR = 0x40022010 - if( rw & 0x8080 ) - { - return -9; - } - } - iss->statetag = STTAG( "XXXX" ); - iss->flash_unlocked = 1; - return 0; -} - -static int EraseFlash( struct SWIOState * iss, uint32_t address, uint32_t length, int type ) -{ - struct SWIOState * dev = iss; - - uint32_t rw; - - if( !iss->flash_unlocked ) - { - if( ( rw = UnlockFlash( iss ) ) ) - return rw; - } - - if( type == 1 ) - { - // Whole-chip flash - iss->statetag = STTAG( "XXXX" ); - BB_PRINTF_DEBUG( "Whole-chip erase\n" ); - WriteWord( dev, 0x40022010, 0 ); // FLASH->CTLR = 0x40022010 - WriteWord( dev, 0x40022010, FLASH_CTLR_MER ); - WriteWord( dev, 0x40022010, CR_STRT_Set|FLASH_CTLR_MER ); - if( WaitForFlash( dev ) ) return -13; - WriteWord( dev, 0x40022010, 0 ); // FLASH->CTLR = 0x40022010 - } - else - { - // 16.4.7, Step 3: Check the BSY bit of the FLASH_STATR register to confirm that there are no other programming operations in progress. - // skip (we make sure at the end) - - int chunk_to_erase = address; - - while( chunk_to_erase < address + length ) - { - if( WaitForFlash( dev ) ) return -14; - - // Step 4: set PAGE_ER of FLASH_CTLR(0x40022010) - WriteWord( dev, 0x40022010, CR_PAGE_ER ); // Actually FTER // FLASH->CTLR = 0x40022010 - - // Step 5: Write the first address of the fast erase page to the FLASH_ADDR register. - WriteWord( dev, 0x40022014, chunk_to_erase ); // FLASH->ADDR = 0x40022014 - - // Step 6: Set the STAT bit of FLASH_CTLR register to '1' to initiate a fast page erase (64 bytes) action. - WriteWord( dev, 0x40022010, CR_STRT_Set|CR_PAGE_ER ); // FLASH->CTLR = 0x40022010 - if( WaitForFlash( dev ) ) return -15; - - WriteWord( dev, 0x40022010, 0 ); // FLASH->CTLR = 0x40022010 (Disable any pending ops) - chunk_to_erase+=64; - } - } - return 0; -} - -static int WriteBlock( struct SWIOState * iss, uint32_t address_to_write, uint8_t * blob, uint8_t len, uint8_t erase ) -{ - struct SWIOState * dev = iss; - - if( DetermineChipTypeAndSectorInfo( iss, NULL ) ) return -9; - - const int blob_size = len; - uint32_t wp = address_to_write; - uint32_t ew = wp + blob_size; - int group = -1; - int is_flash = 0; - int rw = 0; - - if( (address_to_write & 0xff000000) == 0x08000000 || (address_to_write & 0xff000000) == 0x00000000 || (address_to_write & 0x1FFF0000) == 0x1FFF0000 ) - { - // Need to unlock flash. - // Flash reg base = 0x40022000, - // FLASH_MODEKEYR => 0x40022024 - // FLASH_KEYR => 0x40022004 - - if( !iss->flash_unlocked ) - { - if( ( rw = UnlockFlash( dev ) ) ) - return rw; - } - - is_flash = 1; - - if( erase ) - { - // Only erase on first block in sector. - int block_in_sector = (wp & ( iss->sectorsize - 1 )) / blob_size; - int is_first_block = block_in_sector == 0; - - if( is_first_block ) - { - rw = EraseFlash( dev, address_to_write, blob_size, 0 ); - if( rw ) return rw; - // 16.4.6 Main memory fast programming, Step 5 - //if( WaitForFlash( dev ) ) return -11; - //WriteWord( dev, 0x40022010, FLASH_CTLR_BUF_RST ); - //if( WaitForFlash( dev ) ) return -11; - } - } - } - - /* General Note: - Most flash operations take about 3ms to complete :( - */ - - while( wp < ew ) - { - if( is_flash ) - { - group = (wp & 0xffffffc0); - - int block_in_sector = (group & ( iss->sectorsize - 1 )) / blob_size; - int is_first_block = block_in_sector == 0; - int is_last_block = block_in_sector == (iss->sectorsize / blob_size - 1 ); - - if( is_first_block ) - { - if( dev->target_chip_type == CHIP_CH32V20x || dev->target_chip_type == CHIP_CH32V30x ) - { - // No bufrst on v20x, v30x - WaitForFlash( dev ); - WriteWord( dev, 0x40022010, CR_PAGE_PG ); // THIS IS REQUIRED, (intptr_t)&FLASH->CTLR = 0x40022010 - //FTPG == CR_PAGE_PG == ((uint32_t)0x00010000) - } - else - { - // V003, x035, maybe more. - WriteWord( dev, 0x40022010, CR_PAGE_PG ); // THIS IS REQUIRED, (intptr_t)&FLASH->CTLR = 0x40022010 - WriteWord( dev, 0x40022010, CR_BUF_RST | CR_PAGE_PG ); // (intptr_t)&FLASH->CTLR = 0x40022010 - } - WaitForFlash( dev ); - } - - int j; - for( j = 0; j < blob_size/4; j++ ) - { - int index = (wp-address_to_write); - uint32_t data = 0xffffffff; - if( index + 3 < blob_size ) - { - memcpy( &data, &blob[index], 4 ); - } - else if( (int32_t)(blob_size - index) > 0 ) - { - memcpy( &data, &blob[index], blob_size - index ); - } - if( iss->target_chip_type == CHIP_CH32V10x && !((j+1)&3) ) - { - // Signal to WriteWord that we need to do a buffer load - MCFWriteReg32( dev, BDMDATA0, 1 ); - MCFWriteReg32( dev, DMCOMMAND, 0x0023100f ); - } - WriteWord( dev, wp, data ); - wp += 4; - } - - - if( ( iss->target_chip_type == CHIP_CH32V20x || iss->target_chip_type == CHIP_CH32V30x ) ) - { - if( is_last_block ) - { - WriteWord( dev, 0x40022010, CR_PAGE_PG | (1<<21) ); // Page Start - if( WaitForFlash( dev ) ) return -13; - } - } - else - { - // Datasheet says the x03x needs to have this called every group-of-16, but that's not true, it should be every 16-words. - WriteWord( dev, 0x40022014, group ); //0x40022014 -> FLASH->ADDR - WriteWord( dev, 0x40022010, CR_PAGE_PG|CR_STRT_Set ); // 0x40022010 -> FLASH->CTLR - if( WaitForFlash( dev ) ) return -16; - } - } - else - { - int index = (wp-address_to_write); - uint32_t data = 0xffffffff; - if( index + 3 < blob_size ) - { - memcpy( &data, &blob[index], 4 ); - } - else if( (int32_t)(blob_size - index) > 0 ) - { - memcpy( &data, &blob[index], blob_size - index ); - } - WriteWord( dev, wp, data ); - wp += 4; - } - } - - return 0; -} - -// Polls up to 7 bytes of printf, and can leave a 7-bit flag for the CH32V003. -static int PollTerminal( struct SWIOState * iss, uint8_t * buffer, int maxlen, uint32_t leavevalA, uint32_t leavevalB ) -{ - struct SWIOState * dev = iss; - - int r; - uint32_t rr; - if( iss->statetag != STTAG( "TERM" ) ) - { - MCFWriteReg32( dev, DMABSTRACTAUTO, 0x00000000 ); // Disable Autoexec. - iss->statetag = STTAG( "TERM" ); - } - r = MCFReadReg32( dev, BDMDATA0, &rr ); - if( r < 0 ) return r; - - if( maxlen < 8 ) return -9; - - // BDMDATA1: - // bit 7 = host-acknowledge. - if( rr & 0x80 ) - { - int ret = 0; - int num_printf_chars = (rr & 0xf)-4; - - if( num_printf_chars > 0 && num_printf_chars <= 7) - { - if( num_printf_chars > 3 ) - { - uint32_t r2; - r = MCFReadReg32( dev, BDMDATA1, &r2 ); - memcpy( buffer+3, &r2, num_printf_chars - 3 ); - } - int firstrem = num_printf_chars; - if( firstrem > 3 ) firstrem = 3; - memcpy( buffer, ((uint8_t*)&rr)+1, firstrem ); - buffer[num_printf_chars] = 0; - ret = num_printf_chars; - } - if( leavevalA ) - { - MCFWriteReg32( dev, BDMDATA1, leavevalB ); - } - MCFWriteReg32( dev, BDMDATA0, leavevalA ); // Write that we acknowledge the data. - return ret; - } - else - { - return 0; - } -} - -#endif // _CH32V003_SWIO_H diff --git a/fw/programmer/src/bitbang_rvswdio_pico.h b/fw/programmer/src/bitbang_rvswdio_pico.h deleted file mode 100644 index 4136f6d..0000000 --- a/fw/programmer/src/bitbang_rvswdio_pico.h +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include - -#include "bitbang_rvswdio.h" -#include "hardware/timer.h" -#include "lwipopts.h" -#include "pico.h" - - -#define PIN_SWDIO 10 -#define PIN_SWCLK 11 - - -// wait time between line transitions -#define SWD_DELAY() busy_wait_us(2); - -// microseconds between each register read/write -#define STOP_WAIT 8 - -// Single wire debug (SWDIO and SWCLK) -static inline void ConfigureIOForRVSWD(void) -{ - // SWCLK forced, starts at 1 - gpio_init(PIN_SWCLK); - gpio_set_pulls(PIN_SWCLK, false, false); - gpio_put(PIN_SWCLK, 1); - gpio_set_dir(PIN_SWCLK, GPIO_OUT); - - // SWDIO, open drain (emulated) with pull-up - gpio_init(PIN_SWDIO); - gpio_set_pulls(PIN_SWDIO, true, false); - gpio_put(PIN_SWDIO, 1); - gpio_set_dir(PIN_SWDIO, GPIO_IN); -} - - -// Single wire input-output SDI (just SWDIO) -static inline void ConfigureIOForRVSWIO(void) -{ - //BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" ); -} - - -void rvswd_write_bit(bool value) -{ - gpio_put(PIN_SWCLK, 0); - gpio_put(PIN_SWDIO, value); - gpio_set_dir(PIN_SWDIO, GPIO_OUT); - gpio_set_dir(PIN_SWDIO, GPIO_IN); - SWD_DELAY(); - gpio_put(PIN_SWCLK, 1); // Data is sampled on rising edge of clock - SWD_DELAY(); -} - - -bool rvswd_read_bit(void) -{ - gpio_put(PIN_SWDIO, 1); - gpio_set_dir(PIN_SWDIO, GPIO_IN); - gpio_put(PIN_SWCLK, 0); - SWD_DELAY(); - bool bit = gpio_get(PIN_SWDIO); - gpio_put(PIN_SWCLK, 1); // Data is output on rising edge of clock - SWD_DELAY(); - return bit; -} - - -static inline void rvswd_stop(void) -{ - gpio_put(PIN_SWCLK, 0); - SWD_DELAY(); - gpio_put(PIN_SWDIO, 0); - gpio_set_dir(PIN_SWDIO, GPIO_OUT); - SWD_DELAY(); - gpio_put(PIN_SWCLK, 1); - SWD_DELAY(); - gpio_put(PIN_SWDIO, 1); - gpio_set_dir(PIN_SWDIO, GPIO_IN); -} - - -static void MCFWriteReg32( struct SWIOState * state, uint8_t command, uint32_t value ) -{ - // only supported mode is SWD - if (state->opmode != 2) { - //BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" ); - return; - } - - noInterrupts(); - - // start transaction - gpio_put(PIN_SWDIO, 0); - gpio_set_dir(PIN_SWDIO, GPIO_OUT); - SWD_DELAY(); - - // ADDR HOST - bool parity = true; - for (uint32_t mask = 1<<6; mask; mask >>= 1) { - bool bit = !!(command & mask); - parity ^= bit; - rvswd_write_bit(bit); - } - - rvswd_write_bit(1); // Operation: write - rvswd_write_bit(parity); - rvswd_read_bit(); // ??? - rvswd_read_bit(); // Seems only need to be set for first transaction (We are ignoring that though) - rvswd_read_bit(); // ??? - rvswd_write_bit(0); // 0 for register, 1 for value. - rvswd_write_bit(0); // ??? Seems to have something to do with halting. - - // DATA - parity = false; // This time it's even parity? - for (uint32_t mask = 1<<31; mask; mask >>= 1) { - bool bit = !!(value & mask); - parity ^= bit; - rvswd_write_bit(bit); - } - - // Parity bit - rvswd_write_bit(parity); - - rvswd_read_bit(); // ??? - rvswd_read_bit(); // ??? - rvswd_read_bit(); // ??? - rvswd_write_bit(1); // 0 for register, 1 for value - rvswd_write_bit(0); // ??? Seems to have something to do with halting? - - rvswd_stop(); - interrupts(); - sleep_us(STOP_WAIT); -} - - -static int MCFReadReg32( struct SWIOState * state, uint8_t command, uint32_t * value ) -{ - // only supported mode is SWD - if (state->opmode != 2) { - //BB_PRINTF_DEBUG( "TODO: add support for SWIO\n" ); - return -1; - } - - noInterrupts(); - - // start transaction - gpio_put(PIN_SWDIO, 0); - gpio_set_dir(PIN_SWDIO, GPIO_OUT); - SWD_DELAY(); - - // ADDR HOST - bool parity = false; - for (uint8_t mask = 1<<6; mask; mask >>= 1) { - bool bit = !!(command & mask); - parity ^= bit; - rvswd_write_bit(bit); - } - - rvswd_write_bit(0); // Operation: read - rvswd_write_bit(parity); - rvswd_read_bit(); // ?? - rvswd_read_bit(); // ?? - rvswd_read_bit(); // ?? - rvswd_write_bit(0); // 0 for register, 1 for value - rvswd_write_bit(0); // ??? Seems to have something to do with halting? - - // DATA - *value = 0; - parity = false; - uint32_t rval = 0; - for (uint8_t position = 0; position < 32; position++) { - bool bit = rvswd_read_bit(); - rval <<= 1; - rval |= bit; - parity ^= bit; - } - *value = rval; - - // Parity bit - bool parity_read = rvswd_read_bit(); - if (parity_read != parity) goto read_end; - - rvswd_read_bit(); // ?? - rvswd_read_bit(); // ?? - rvswd_read_bit(); // ?? - rvswd_write_bit(1); // 0 for register, 1 for value - rvswd_write_bit(0); // ??? Seems to have something to do with halting? - - rvswd_stop(); - -read_end: - interrupts(); - sleep_us(STOP_WAIT); - BB_PRINTF_DEBUG("wrong parity: %d\n", parity_read); - return (parity == parity_read) ? 0 : -1; -} diff --git a/fw/programmer/src/main.cpp b/fw/programmer/src/main.cpp deleted file mode 100644 index a680dd9..0000000 --- a/fw/programmer/src/main.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "pico/time.h" -#include -#include - -#define BB_PRINTF_DEBUG(...) Serial.printf(__VA_ARGS__) -//#define BB_PRINTF_DEBUG(...) -#include "bitbang_rvswdio.h" -#include "bitbang_rvswdio_pico.h" - -SWIOState state = {.opmode = 2}; - -void setup() { - Serial.begin(115200); - Serial.setTimeout(100); -} - - -void setup1() -{ - pinMode(LED_BUILTIN, OUTPUT); -} - - -void loop() { - if (Serial.available() > 0) { - char cmd = Serial.read(); - int ret = 0; - uint8_t reg; - - switch (cmd) { - case '!': - state = {}; - ret = InitializeSWDSWIO(&state); - if (ret != 0) { - Serial.printf("error initializing SWD: %d\n", ret); - break; - } - ret = DetermineChipTypeAndSectorInfo(&state, NULL); - if (ret != 0) { - Serial.printf("failed to determine chip type: %d\n", ret); - break; - } - Serial.printf("chip type is %x\n", state.target_chip_type); - break; - default: - Serial.printf("unknown command '%c'\n", cmd); - break; - } - } -} - - -void loop1() -{ - digitalWrite(LED_BUILTIN, 1); - delay(200); - digitalWrite(LED_BUILTIN, 0); - delay(200); -} diff --git a/fw/programmer/test/rvswd.c b/fw/programmer/test/rvswd.c deleted file mode 100644 index a80c948..0000000 --- a/fw/programmer/test/rvswd.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "rvswd.h" -#include -#include -#include -#include - - -// adapted from https://github.com/Nicolai-Electronics/esp32-component-rvswd - -rvswd_result_t rvswd_init(rvswd_handle_t* handle) { - //gpio_config_t swio_cfg = { - // .pin_bit_mask = BIT64(handle->swdio), - // .mode = GPIO_MODE_INPUT_OUTPUT_OD, - // .pull_up_en = true, - // .pull_down_en = false, - // .intr_type = GPIO_INTR_DISABLE, - //}; - gpio_init(handle->swdio); - gpio_set_pulls(handle->swdio, true, false); - gpio_put(handle->swdio, 0); - gpio_set_dir(handle->swdio, GPIO_IN); - - //gpio_config_t swck_cfg = { - // .pin_bit_mask = BIT64(handle->swclk), - // .mode = GPIO_MODE_OUTPUT, - // .pull_up_en = false, - // .pull_down_en = false, - // .intr_type = GPIO_INTR_DISABLE, - //}; - gpio_init(handle->swclk); - gpio_set_pulls(handle->swclk, false, false); - gpio_put(handle->swclk, 0); - gpio_set_dir(handle->swclk, GPIO_OUT); - - return RVSWD_OK; -} - -rvswd_result_t rvswd_start(rvswd_handle_t* handle) { - // Start with both lines high - // open drain emulation, input for high (pulled up) and out for low (forced) - gpio_set_dir(handle->swdio, GPIO_IN); // high - gpio_put(handle->swclk, 1); - sleep_us(2); - - // Pull data low - gpio_set_dir(handle->swdio, GPIO_OUT); // low - gpio_put(handle->swclk, 1); - sleep_us(1); - - // Pull clock low - gpio_set_dir(handle->swdio, GPIO_OUT); // low - gpio_put(handle->swclk, 0); - sleep_us(1); - - return RVSWD_OK; -} - -rvswd_result_t rvswd_stop(rvswd_handle_t* handle) { - // Pull data low - gpio_set_dir(handle->swdio, GPIO_OUT); - sleep_us(1); - gpio_put(handle->swclk, 1); - sleep_us(2); - - // Let data float high - gpio_set_dir(handle->swdio, GPIO_IN); - sleep_us(1); - return RVSWD_OK; -} - -rvswd_result_t rvswd_reset(rvswd_handle_t* handle) { - // set data floating high - gpio_set_dir(handle->swdio, GPIO_IN); - sleep_us(1); - // let clock go brrr - for (uint8_t i = 0; i < 100; i++) { - gpio_put(handle->swclk, 0); - sleep_us(1); - gpio_put(handle->swclk, 1); - sleep_us(1); - } - return rvswd_stop(handle); -} - -#define OD_PULL(pin, value) gpio_set_dir((pin), (value) ? GPIO_IN : GPIO_OUT) - -void rvswd_write_bit(rvswd_handle_t* handle, bool value) { - OD_PULL(handle->swdio, value); - gpio_put(handle->swclk, 0); - // FIXME: does this need a delay? - gpio_put(handle->swclk, 1); // Data is sampled on rising edge of clock -} - -bool rvswd_read_bit(rvswd_handle_t* handle) { - // let data float high - gpio_set_dir(handle->swdio, GPIO_IN); - // pulse clock - gpio_put(handle->swclk, 0); - gpio_put(handle->swclk, 1); // Data is output on rising edge of clock - // FIXME: does this need a delay? - return gpio_get(handle->swdio); -} - -rvswd_result_t rvswd_write(rvswd_handle_t* handle, uint8_t reg, uint32_t value) { - rvswd_start(handle); - - // ADDR HOST - bool parity = false; // This time it's odd parity? - for (uint8_t position = 0; position < 7; position++) { - bool bit = (reg >> (6 - position)) & 1; - rvswd_write_bit(handle, bit); - if (bit) parity = !parity; - } - - // Operation: write - rvswd_write_bit(handle, true); - parity = !parity; - - // Parity bit (even) - rvswd_write_bit(handle, parity); - - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 0); - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 0); - rvswd_write_bit(handle, 1); - - // Data - parity = false; // This time it's even parity? - for (uint8_t position = 0; position < 32; position++) { - bool bit = (value >> (31 - position)) & 1; - rvswd_write_bit(handle, bit); - if (bit) parity = !parity; - } - - // Parity bit - rvswd_write_bit(handle, parity); - - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 0); - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 1); - - rvswd_stop(handle); - - return RVSWD_OK; -} - -rvswd_result_t rvswd_read(rvswd_handle_t* handle, uint8_t reg, uint32_t* value) { - bool parity; - - rvswd_start(handle); - - // ADDR HOST - parity = false; - for (uint8_t position = 0; position < 7; position++) { - bool bit = (reg >> (6 - position)) & 1; - rvswd_write_bit(handle, bit); - if (bit) parity = !parity; - } - - // Operation: read - rvswd_write_bit(handle, false); - - // Parity bit (even) - rvswd_write_bit(handle, parity); - - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 0); - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 0); - rvswd_write_bit(handle, 1); - - *value = 0; - - // Data - parity = false; - for (uint8_t position = 0; position < 32; position++) { - bool bit = rvswd_read_bit(handle); - if (bit) { - *value |= 1 << (31 - position); - } - if (bit) parity = !parity; - } - - // Parity bit - bool parity_read = rvswd_read_bit(handle); - - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 0); - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 1); - rvswd_write_bit(handle, 1); - - rvswd_stop(handle); - - return (parity == parity_read) ? RVSWD_OK : RVSWD_FAIL; -} diff --git a/fw/programmer/test/rvswd.h b/fw/programmer/test/rvswd.h deleted file mode 100644 index dd43d31..0000000 --- a/fw/programmer/test/rvswd.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include - -typedef struct rvswd_handle { - int swdio; - int swclk; -} rvswd_handle_t; - -typedef enum rvswd_result { - RVSWD_OK = 0, - RVSWD_FAIL = 1, - RVSWD_INVALID_ARGS = 2, - RVSWD_PARITY_ERROR = 3, -} rvswd_result_t; - -rvswd_result_t rvswd_init(rvswd_handle_t* handle); -rvswd_result_t rvswd_reset(rvswd_handle_t* handle); -rvswd_result_t rvswd_write(rvswd_handle_t* handle, uint8_t reg, uint32_t value); -rvswd_result_t rvswd_read(rvswd_handle_t* handle, uint8_t reg, uint32_t* value);