RISC-V/minichlink/minichlink.h
2025-02-05 15:55:13 +01:00

205 lines
6.6 KiB
C

#ifndef _MINICHLINK_H
#define _MINICHLINK_H
#include <stdint.h>
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