#ifndef _MINICHLINK_H #define _MINICHLINK_H #include struct MiniChlinkFunctions { // All functions return 0 if OK, negative number if fault, positive number as status code. // Low-level functions, if they exist. int (*WriteReg32)( void * dev, uint8_t reg_7_bit, uint32_t command ); int (*ReadReg32)( void * dev, uint8_t reg_7_bit, uint32_t * commandresp ); int (*FlushLLCommands)( void * dev ); int (*DelayUS)( void * dev, int microseconds ); // Higher-level functions can be generated automatically. int (*SetupInterface)( void * dev ); int (*Control3v3)( void * dev, int bOn ); int (*Control5v)( void * dev, int bOn ); int (*Unbrick)( void * dev ); // Turns on chip, erases everything, powers off. int (*Exit)( void * dev ); int (*HaltMode)( void * dev, int mode ); //0 for halt, 1 for reset, 2 for resume int (*ConfigureNRSTAsGPIO)( void * dev, int one_if_yes_gpio ); int (*ConfigureReadProtection)( void * dev, int one_if_yes_protect ); // No boundary or limit rules. Must support any combination of alignment and size. int (*WriteBinaryBlob)( void * dev, uint32_t address_to_write, uint32_t blob_size, uint8_t * blob ); int (*ReadBinaryBlob)( void * dev, uint32_t address_to_read_from, uint32_t read_size, uint8_t * blob ); int (*Erase)( void * dev, uint32_t address, uint32_t length, int type ); //type = 0 for fast, 1 for whole-chip // MUST be 4-byte-aligned. int (*VoidHighLevelState)( void * dev ); int (*WriteWord)( void * dev, uint32_t address_to_write, uint32_t data ); int (*ReadWord)( void * dev, uint32_t address_to_read, uint32_t * data ); // Debugging operations. // Note: You must already be in break mode to use these otherwise they // will return nonsensical data. // For x0...xN, use 0x1000 + regno. // For PC, use 0x7b1 int (*ReadCPURegister)( void * dev, uint32_t regno, uint32_t * regret ); int (*WriteCPURegister)( void * dev, uint32_t regno, uint32_t regval ); // Actually returns 17 registers (All 16 CPU registers + the debug register) int (*ReadAllCPURegisters)( void * dev, uint32_t * regret ); int (*WriteAllCPURegisters)( void * dev, uint32_t * regret ); int (*SetEnableBreakpoints)( void * dev, int halt_on_break, int single_step ); int (*PrepForLongOp)( void * dev ); // Called before the command that will take a while. int (*WaitForFlash)( void * dev ); int (*WaitForDoneOp)( void * dev, int ignore ); int (*PrintChipInfo)( void * dev ); // Geared for flash, but could be anything. Note: If in flash, must also erase. int (*BlockWrite64)( void * dev, uint32_t address_to_write, uint8_t * data ); // Returns positive if received text. // Returns negative if error. // Returns 0 if no text waiting. // Note: YOU CANNOT make lsb of leaveflagA bit in place 0x80 be high!!! int (*PollTerminal)( void * dev, uint8_t * buffer, int maxlen, uint32_t leaveflagA, int leaveflagB ); int (*PerformSongAndDance)( void * dev ); int (*VendorCommand)( void * dev, const char * command ); // Probably no need to override these. The base layer handles them. int (*WriteHalfWord)( void * dev, uint32_t address_to_write, uint16_t data ); int (*ReadHalfWord)( void * dev, uint32_t address_to_read, uint16_t * data ); int (*WriteByte)( void * dev, uint32_t address_to_write, uint8_t data ); int (*ReadByte)( void * dev, uint32_t address_to_read, uint8_t * data ); }; /** If you are writing a driver, the minimal number of functions you can implement are: WriteReg32 ReadReg32 FlushLLCommands */ inline static int IsAddressFlash( uint32_t addy ) { return ( addy & 0xff000000 ) == 0x08000000 || ( addy & 0x1FFFF000 ) == 0x1FFFF000; } #define HALT_MODE_HALT_AND_RESET 0 #define HALT_MODE_REBOOT 1 #define HALT_MODE_RESUME 2 #define HALT_MODE_GO_TO_BOOTLOADER 3 #define HALT_MODE_HALT_BUT_NO_RESET 5 // Convert a 4-character string to an int. #define STTAG( x ) (*((uint32_t*)(x))) struct InternalState; struct ProgrammerStructBase { struct InternalState * internal; // You can put other things here. }; #define MAX_FLASH_SECTORS 262144 enum RiscVChip { CHIP_CH32V10x = 0x01, CHIP_CH57x = 0x02, CHIP_CH56x = 0x03, CHIP_CH32V20x = 0x05, CHIP_CH32V30x = 0x06, CHIP_CH58x = 0x07, CHIP_CH32V003 = 0x09 }; struct InternalState { uint32_t statetag; uint32_t currentstateval; uint32_t flash_unlocked; int lastwriteflags; int processor_in_mode; int autoincrement; uint32_t ram_base; uint32_t ram_size; int sector_size; int flash_size; enum RiscVChip target_chip_type; uint8_t flash_sector_status[MAX_FLASH_SECTORS]; // 0 means unerased/unknown. 1 means erased. }; #define DMDATA0 0x04 #define DMDATA1 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 #if defined( WIN32 ) || defined( _WIN32 ) #if defined( MINICHLINK_AS_LIBRARY ) #define DLLDECORATE __declspec(dllexport) #elif defined( MINICHLINK_IMPORT ) #define DLLDECORATE __declspec(dllimport) #else #define DLLDECORATE #endif #else #define DLLDECORATE #endif /* initialization hints for init functions */ /* could be expanded with more in the future (e.g., PID/VID hints, priorities, ...)*/ /* not all init functions currently need these hints. */ typedef struct { const char * serial_port; const char * specific_programmer; } init_hints_t; void * MiniCHLinkInitAsDLL(struct MiniChlinkFunctions ** MCFO, const init_hints_t* init_hints) DLLDECORATE; extern struct MiniChlinkFunctions MCF; // Returns 'dev' on success, else 0. void * TryInit_WCHLinkE(void); void * TryInit_ESP32S2CHFUN(void); void * TryInit_NHCLink042(void); void * TryInit_B003Fun(void); void * TryInit_Ardulink(const init_hints_t*); // Returns 0 if ok, populated, 1 if not populated. int SetupAutomaticHighLevelFunctions( void * dev ); // Useful for converting numbers like 0x, etc. int64_t SimpleReadNumberInt( const char * number, int64_t defaultNumber ); // For drivers to call int DefaultVoidHighLevelState( void * dev ); int InternalUnlockBootloader( void * dev ); int InternalIsMemoryErased( struct InternalState * iss, uint32_t address ); void InternalMarkMemoryNotErased( struct InternalState * iss, uint32_t address ); int InternalUnlockFlash( void * dev, struct InternalState * iss ); // GDBSever Functions int SetupGDBServer( void * dev ); int PollGDBServer( void * dev ); int IsGDBServerInShadowHaltState( void * dev ); void ExitGDBServer( void * dev ); #endif