diff --git a/configure.ac b/configure.ac index 9d851c06f..341ee52e9 100644 --- a/configure.ac +++ b/configure.ac @@ -243,6 +243,10 @@ AC_ARG_ENABLE([rshim], AS_HELP_STRING([--enable-rshim], [Enable building the rshim driver]), [build_rshim=$enableval], [build_rshim=no]) +AC_ARG_ENABLE([dmem], + AS_HELP_STRING([--enable-dmem], [Enable building the dmem driver]), + [build_dmem=$enableval], [build_dmem=no]) + m4_define([AC_ARG_ADAPTERS], [ m4_foreach([adapter], [$1], [AC_ARG_ENABLE(ADAPTER_OPT([adapter]), @@ -359,6 +363,10 @@ AS_CASE([$host_os], AC_MSG_ERROR([build_rshim is only available on linux or freebsd]) ]) ]) + + AS_IF([test "x$build_dmem" = "xyes"], [ + AC_MSG_ERROR([dmem is only available on linux]) + ]) ]) AC_ARG_ENABLE([internal-jimtcl], @@ -479,6 +487,12 @@ AS_IF([test "x$build_rshim" = "xyes"], [ AC_DEFINE([BUILD_RSHIM], [0], [0 if you don't want to debug BlueField SoC via rshim.]) ]) +AS_IF([test "x$build_dmem" = "xyes"], [ + AC_DEFINE([BUILD_DMEM], [1], [1 if you want to debug via Direct Mem.]) +], [ + AC_DEFINE([BUILD_DMEM], [0], [0 if you don't want to debug via Direct Mem.]) +]) + AS_IF([test "x$build_dummy" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_DUMMY], [1], [1 if you want dummy driver.]) @@ -755,6 +769,7 @@ AM_CONDITIONAL([USE_LIBGPIOD], [test "x$use_libgpiod" = "xyes"]) AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"]) AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"]) AM_CONDITIONAL([RSHIM], [test "x$build_rshim" = "xyes"]) +AM_CONDITIONAL([DMEM], [test "x$build_dmem" = "xyes"]) AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"]) AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"]) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index fd88564bd..b0e229d07 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -226,6 +226,8 @@ ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev", # ANGIE USB-JTAG Adapter ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4255", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4355", MODE="660", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4a55", MODE="660", GROUP="plugdev", TAG+="uaccess" # Marvell Sheevaplug diff --git a/contrib/firmware/angie/c/Makefile b/contrib/firmware/angie/c/Makefile index 80e8cbe57..e919cd011 100644 --- a/contrib/firmware/angie/c/Makefile +++ b/contrib/firmware/angie/c/Makefile @@ -38,7 +38,7 @@ LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \ --xram-size $(XRAM_SIZE) --iram-size 256 --model-small # list of base object files -OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel +OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel i2c.rel HEADERS = $(INCLUDE_DIR)/usb.h \ $(INCLUDE_DIR)/protocol.h \ $(INCLUDE_DIR)/jtag.h \ @@ -47,7 +47,8 @@ HEADERS = $(INCLUDE_DIR)/usb.h \ $(INCLUDE_DIR)/io.h \ $(INCLUDE_DIR)/serial.h \ $(INCLUDE_DIR)/fx2macros.h \ - $(INCLUDE_DIR)/msgtypes.h + $(INCLUDE_DIR)/msgtypes.h \ + $(INCLUDE_DIR)/i2c.h # Disable all built-in rules. .SUFFIXES: @@ -61,7 +62,7 @@ all: angie_firmware.ihx angie_firmware.ihx: $(OBJECTS) $(CC) -mmcs51 $(LDFLAGS) -o $@ $^ -# Rebuild every C module (there are only 5 of them) if any header changes. +# Rebuild every C module (there are only 8 of them) if any header changes. %.rel: $(SRC_DIR)/%.c $(HEADERS) $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $< diff --git a/contrib/firmware/angie/c/README b/contrib/firmware/angie/c/README index 04ed0be2a..2d41da7a4 100644 --- a/contrib/firmware/angie/c/README +++ b/contrib/firmware/angie/c/README @@ -12,8 +12,8 @@ To compile the firmware, the SDCC compiler package is required. Most Linux distributions include SDCC in their official package repositories. The SDCC source code can be found at http://sdcc.sourceforge.net/ -Simply type "make hex" in the ANGIE directory to compile the firmware. -"make clean" will remove all generated files except the Intel HEX file +Simply type "make bin" in the ANGIE directory to compile the firmware. +"make clean" will remove all generated files except the BIN file required for downloading the firmware to ANGIE. Note that the EZ-USB FX2 microcontroller does not have on-chip flash, diff --git a/contrib/firmware/angie/c/include/i2c.h b/contrib/firmware/angie/c/include/i2c.h new file mode 100644 index 000000000..06185efb4 --- /dev/null +++ b/contrib/firmware/angie/c/include/i2c.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/**************************************************************************** + File : i2c.h * + Contents : i2c bit-bang library * + Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. * + * + * +*****************************************************************************/ + +#ifndef __I2C_H +#define __I2C_H + +#include +#include +#include + +void start_cd(void); +void repeated_start(void); +void stop_cd(void); +void clock_cd(void); +void send_ack(void); +bool get_ack(void); + +uint8_t get_address(uint8_t adr, uint8_t rdwr); + +void send_byte(uint8_t input); +uint8_t receive_byte(void); +#endif diff --git a/contrib/firmware/angie/c/include/io.h b/contrib/firmware/angie/c/include/io.h index 35afa626f..af488f4ed 100644 --- a/contrib/firmware/angie/c/include/io.h +++ b/contrib/firmware/angie/c/include/io.h @@ -45,14 +45,14 @@ #define PIN_TDI IOB3 #define PIN_TDO IOB4 #define PIN_SRST IOB5 -/* PA6 Not Connected */ -/* PA7 Not Connected */ +/* PB6 Not Connected */ +/* PB7 Not Connected */ /* JTAG Signals with direction 'OUT' on port B */ /* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */ #define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5) -/* PORT C */ // Debug: +/* PORT C */ #define PIN_T0 IOC0 #define PIN_T1 IOC1 #define PIN_T2 IOC2 @@ -62,4 +62,14 @@ /* PC6 Not Connected */ /* PC7 Not Connected */ +/* PORT D */ +#define PIN_SDA IOD0 +#define PIN_SCL IOD1 +#define PIN_SDA_DIR IOD2 +/* PD3 Not Connected */ +/* PD4 Not Connected */ +/* PD5 Not Connected */ +/* PD6 Not Connected */ +/* PD7 Not Connected */ + #endif diff --git a/contrib/firmware/angie/c/include/usb.h b/contrib/firmware/angie/c/include/usb.h index 0450d1d1c..07cb12ae6 100644 --- a/contrib/firmware/angie/c/include/usb.h +++ b/contrib/firmware/angie/c/include/usb.h @@ -24,18 +24,19 @@ #define STALL_EP0() (EP0CS |= EPSTALL) #define CLEAR_IRQ() (USBINT = 0) -/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/ +/*********** USB descriptors. See USB 2.0 Spec **********/ -/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */ -#define DESCRIPTOR_TYPE_DEVICE 0x01 -#define DESCRIPTOR_TYPE_CONFIGURATION 0x02 -#define DESCRIPTOR_TYPE_STRING 0x03 -#define DESCRIPTOR_TYPE_INTERFACE 0x04 -#define DESCRIPTOR_TYPE_ENDPOINT 0x05 +/* USB Descriptor Types. See USB 2.0 Spec */ +#define DESCRIPTOR_TYPE_DEVICE 0x01 +#define DESCRIPTOR_TYPE_CONFIGURATION 0x02 +#define DESCRIPTOR_TYPE_STRING 0x03 +#define DESCRIPTOR_TYPE_INTERFACE 0x04 +#define DESCRIPTOR_TYPE_ENDPOINT 0x05 +#define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0B #define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } } -/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */ +/** USB Device Descriptor. See USB 2.0 Spec */ struct usb_device_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */ @@ -53,7 +54,7 @@ struct usb_device_descriptor { uint8_t bnumconfigurations; /**< Number of possible configurations. */ }; -/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */ +/** USB Configuration Descriptor. See USB 2.0 Spec */ struct usb_config_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */ @@ -65,7 +66,19 @@ struct usb_config_descriptor { uint8_t maxpower; /**< Maximum power consumption in 2 mA units. */ }; -/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */ +/** USB Interface association Descriptor. See USB 2.0 Spec */ +struct usb_interface_association_descriptor { + uint8_t blength; + uint8_t bdescriptortype; + uint8_t bfirstinterface; + uint8_t binterfacecount; + uint8_t bfunctionclass; + uint8_t bfunctionsubclass; + uint8_t bfunctionprotocol; + uint8_t ifunction; +}; + +/** USB Interface Descriptor. See USB 2.0 Spec */ struct usb_interface_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< INTERFACE descriptor type. */ @@ -78,7 +91,7 @@ struct usb_interface_descriptor { uint8_t iinterface; /**< Index of interface string descriptor. */ }; -/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */ +/** USB Endpoint Descriptor. See USB 2.0 Spec */ struct usb_endpoint_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */ @@ -88,14 +101,14 @@ struct usb_endpoint_descriptor { uint8_t binterval; /**< Polling interval (in ms) for this endpoint. */ }; -/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */ +/** USB Language Descriptor. See USB 2.0 Spec */ struct usb_language_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< STRING descriptor type. */ uint16_t wlangid[]; /**< LANGID codes. */ }; -/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */ +/** USB String Descriptor. See USB 2.0 Spec */ struct usb_string_descriptor { uint8_t blength; /**< Size of this descriptor in bytes. */ uint8_t bdescriptortype; /**< STRING descriptor type. */ @@ -104,7 +117,7 @@ struct usb_string_descriptor { /********************** USB Control Endpoint 0 related *********************/ -/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */ +/** USB Control Setup Data. See USB 2.0 Spec */ struct setup_data { uint8_t bmrequesttype; /**< Characteristics of a request. */ uint8_t brequest; /**< Specific request. */ @@ -121,66 +134,66 @@ extern volatile bool ep1_in; extern volatile __xdata __at 0xE6B8 struct setup_data setup_data; /* - * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2 + * USB Request Types (bmRequestType): See USB 2.0 Spec * * Bit 7: Data transfer direction - * 0 = Host-to-device - * 1 = Device-to-host + * 0 = Host-to-device + * 1 = Device-to-host * Bit 6...5: Type - * 0 = Standard - * 1 = Class - * 2 = Vendor - * 3 = Reserved + * 0 = Standard + * 1 = Class + * 2 = Vendor + * 3 = Reserved * Bit 4...0: Recipient - * 0 = Device - * 1 = Interface - * 2 = Endpoint - * 3 = Other - * 4...31 = Reserved + * 0 = Device + * 1 = Interface + * 2 = Endpoint + * 3 = Other + * 4...31 = Reserved */ -#define USB_DIR_OUT 0x00 -#define USB_DIR_IN 0x80 +#define USB_DIR_OUT 0x00 +#define USB_DIR_IN 0x80 #define USB_REQ_TYPE_STANDARD (0x00 << 5) #define USB_REQ_TYPE_CLASS (0x01 << 5) #define USB_REQ_TYPE_VENDOR (0x02 << 5) #define USB_REQ_TYPE_RESERVED (0x03 << 5) -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 /* Clear Interface Request */ -#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Get Configuration Request */ -#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Get Descriptor Request */ -#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Get Interface Request */ #define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) /* Get Status Request: See USB 1.1 spec, page 190 */ -#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) /* Set Address Request is handled by EZ-USB core */ /* Set Configuration Request */ -#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Set Descriptor Request */ -#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) /* Set Feature Request */ -#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) +#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) #define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) #define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) @@ -190,27 +203,27 @@ extern volatile __xdata __at 0xE6B8 struct setup_data setup_data; /* Synch Frame Request */ #define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) -/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */ -#define GET_STATUS 0 -#define CLEAR_FEATURE 1 +/* USB Requests (bRequest): See USB 2.0 Spec */ +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 /* Value '2' is reserved for future use */ -#define SET_FEATURE 3 +#define SET_FEATURE 3 /* Value '4' is reserved for future use */ -#define SET_ADDRESS 5 -#define GET_DESCRIPTOR 6 -#define SET_DESCRIPTOR 7 -#define GET_CONFIGURATION 8 -#define SET_CONFIGURATION 9 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 #define GET_INTERFACE 10 #define SET_INTERFACE 11 #define SYNCH_FRAME 12 -/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */ -#define DEVICE_REMOTE_WAKEUP 1 -#define ENDPOINT_HALT 0 +/* Standard Feature Selectors: See USB 2.0 Spec */ +#define DEVICE_REMOTE_WAKEUP 1 +#define ENDPOINT_HALT 0 /************************** EZ-USB specific stuff **************************/ -/** USB Interrupts. See AN2131-TRM, page 9-4 for details */ +/** USB Interrupts. See EZ-USB FX2-TRM, for details */ enum usb_isr { SUDAV_ISR = 13, SOF_ISR, @@ -265,7 +278,10 @@ bool usb_handle_set_feature(void); bool usb_handle_get_descriptor(void); void usb_handle_set_interface(void); void usb_handle_setup_data(void); +void usb_handle_i2c_in(void); +void usb_handle_i2c_out(void); +void i2c_recieve(void); void ep_init(void); void interrupt_init(void); void io_init(void); diff --git a/contrib/firmware/angie/c/src/i2c.c b/contrib/firmware/angie/c/src/i2c.c new file mode 100644 index 000000000..a7004bfac --- /dev/null +++ b/contrib/firmware/angie/c/src/i2c.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/**************************************************************************** + File : i2c.cpp * + Contents : i2c bit-bang library * + Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. * + * + * +*****************************************************************************/ + +#include "i2c.h" +#include "io.h" +#include "delay.h" +#include "reg_ezusb.h" + +void start_cd(void) +{ + PIN_SDA = 0; //SDA = 1; + delay_us(1); + PIN_SCL = 0; //SCL = 1; + delay_us(1); +} + +void repeated_start(void) +{ + PIN_SDA = 1; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SDA = 0; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + +void stop_cd(void) +{ + PIN_SDA = 0; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SDA = 1; + delay_us(1); +} + +void clock_cd(void) +{ + PIN_SCL = 1; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + +void send_ack(void) +{ + PIN_SDA = 0; + delay_us(1); + PIN_SCL = 1; + delay_us(1); + PIN_SCL = 0; + delay_us(1); +} + +bool get_ack(void) +{ + PIN_SDA_DIR = 1; + delay_us(1); + OED = 0xFE; + PIN_SCL = 1; + delay_us(1); + bool ack = PIN_SDA; + PIN_SCL = 0; + delay_us(1); + OED = 0xFF; + PIN_SDA_DIR = 0; + delay_us(1); + return ack; +} + +/* here address(8 bits) = adr (7 bits) + type (1 bit) */ +uint8_t get_address(uint8_t adr, uint8_t rdwr) +{ + adr &= 0x7F; + adr = adr << 1; + adr |= (rdwr & 0x01); + return adr; +} + +/* here send bit after bit and clocking scl with each bit */ +void send_byte(uint8_t input) +{ + for (uint8_t i = 0; i < 8; i++) { + if ((input & 0x80)) { + PIN_SDA = 1; + delay_us(1); + clock_cd(); + } else { + PIN_SDA = 0; + delay_us(1); + clock_cd(); + } + input = input << 1; + } +} + +/* here receive bit after bit and clocking scl with each bit */ + +uint8_t receive_byte(void) +{ + PIN_SDA_DIR = 1; //FX2 <-- FPGA + OED = 0xFE; + uint8_t input = 0x00; + for (uint8_t i = 0; i < 8; i++) { + PIN_SCL = 1; + delay_us(1); + input = input << 1; + if (PIN_SDA == 1) + input |= 0x01; + else + input |= 0X00; + + PIN_SCL = 0; + delay_us(1); + } + OED = 0xFF; + PIN_SDA_DIR = 0; + return input; +} diff --git a/contrib/firmware/angie/c/src/protocol.c b/contrib/firmware/angie/c/src/protocol.c index 3f3aaaf36..d84534bf2 100644 --- a/contrib/firmware/angie/c/src/protocol.c +++ b/contrib/firmware/angie/c/src/protocol.c @@ -139,15 +139,12 @@ bool execute_command(void) payload_index_in += usb_in_bytecount; /* Determine if this was the last command */ - if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) { + if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) return true; - /* Line between return and else required by checkpatch: */ - uint8_t a = 0; - } else { - /* Not the last command, update cmd_id_index */ - cmd_id_index += (usb_out_bytecount + 1); - return false; - } + + /* Not the last command, update cmd_id_index */ + cmd_id_index += (usb_out_bytecount + 1); + return false; } /** diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c index 8fd4de637..747fef124 100644 --- a/contrib/firmware/angie/c/src/usb.c +++ b/contrib/firmware/angie/c/src/usb.c @@ -18,6 +18,7 @@ #include #include #include +#include "i2c.h" /* Also update external declarations in "include/usb.h" if making changes to * these variables! @@ -36,9 +37,9 @@ __code struct usb_device_descriptor device_descriptor = { .blength = sizeof(struct usb_device_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_DEVICE, .bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */ - .bdeviceclass = 0xFF, /* 0xFF = vendor-specific */ - .bdevicesubclass = 0xFF, - .bdeviceprotocol = 0xFF, + .bdeviceclass = 0xEF, + .bdevicesubclass = 0x02, + .bdeviceprotocol = 0x01, .bmaxpacketsize0 = 64, .idvendor = 0x584e, .idproduct = 0x424e, @@ -55,25 +56,36 @@ __code struct usb_config_descriptor config_descriptor = { .blength = sizeof(struct usb_config_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION, .wtotallength = sizeof(struct usb_config_descriptor) + - sizeof(struct usb_interface_descriptor) + - (NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)), - .bnuminterfaces = 1, + 3 * sizeof(struct usb_interface_descriptor) + + ((NUM_ENDPOINTS + 2) * sizeof(struct usb_endpoint_descriptor)), + .bnuminterfaces = 2, .bconfigurationvalue = 1, - .iconfiguration = 4, /* String describing this configuration */ + .iconfiguration = 1, /* String describing this configuration */ .bmattributes = 0x80, /* Only MSB set according to USB spec */ .maxpower = 50 /* 100 mA */ }; +__code struct usb_interface_association_descriptor interface_association_descriptor = { + .blength = sizeof(struct usb_interface_association_descriptor), + .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, + .bfirstinterface = 0x01, + .binterfacecount = 0x02, + .bfunctionclass = 0x02, + .bfunctionsubclass = 0x00, + .bfunctionprotocol = 0x00, + .ifunction = 0x00 +}; + __code struct usb_interface_descriptor interface_descriptor00 = { .blength = sizeof(struct usb_interface_descriptor), .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE, .binterfacenumber = 0, .balternatesetting = 0, .bnumendpoints = NUM_ENDPOINTS, - .binterfaceclass = 0xFF, - .binterfacesubclass = 0xFF, - .binterfaceprotocol = 0xFF, - .iinterface = 0 + .binterfaceclass = 0XFF, + .binterfacesubclass = 0x00, + .binterfaceprotocol = 0x00, + .iinterface = 4 }; __code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = { @@ -103,16 +115,19 @@ __code struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor = { .binterval = 0 }; -__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = { - .blength = sizeof(struct usb_endpoint_descriptor), - .bdescriptortype = 0x05, - .bendpointaddress = (4 | USB_DIR_IN), - .bmattributes = 0x02, - .wmaxpacketsize = 512, - .binterval = 0 +__code struct usb_interface_descriptor interface_descriptor01 = { + .blength = sizeof(struct usb_interface_descriptor), + .bdescriptortype = DESCRIPTOR_TYPE_INTERFACE, + .binterfacenumber = 1, + .balternatesetting = 0, + .bnumendpoints = 2, + .binterfaceclass = 0x0A, + .binterfacesubclass = 0x00, + .binterfaceprotocol = 0x00, + .iinterface = 0x00 }; -__code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = { +__code struct usb_endpoint_descriptor bulk_ep6_out_endpoint_descriptor = { .blength = sizeof(struct usb_endpoint_descriptor), .bdescriptortype = 0x05, .bendpointaddress = (6 | USB_DIR_OUT), @@ -121,19 +136,18 @@ __code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = { .binterval = 0 }; -__code struct usb_endpoint_descriptor bulk_ep8_endpoint_descriptor = { +__code struct usb_endpoint_descriptor bulk_ep8_in_endpoint_descriptor = { .blength = sizeof(struct usb_endpoint_descriptor), .bdescriptortype = 0x05, - .bendpointaddress = (8 | USB_DIR_OUT), + .bendpointaddress = (8 | USB_DIR_IN), .bmattributes = 0x02, .wmaxpacketsize = 512, .binterval = 0 }; - __code struct usb_language_descriptor language_descriptor = { .blength = 4, .bdescriptortype = DESCRIPTOR_TYPE_STRING, - .wlangid = {0x0409 /* US English */} + .wlangid = {0x0409} /* US English */ }; __code struct usb_string_descriptor strmanufacturer = @@ -212,9 +226,15 @@ void ep4_isr(void)__interrupt EP4_ISR } void ep6_isr(void)__interrupt EP6_ISR { + i2c_recieve(); + EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ + EPIRQ = 0x40; /* Clear individual EP6OUT IRQ */ + } void ep8_isr(void)__interrupt EP8_ISR { + EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */ + EPIRQ = 0x80; /* Clear individual EP8IN IRQ */ } void ibn_isr(void)__interrupt IBN_ISR { @@ -411,21 +431,21 @@ bool usb_handle_clear_feature(void) switch (setup_data.bmrequesttype) { case CF_DEVICE: /* Clear remote wakeup not supported: stall EP0 */ - STALL_EP0(); - break; + STALL_EP0(); + break; case CF_ENDPOINT: - if (setup_data.wvalue == 0) { + if (setup_data.wvalue == 0) { /* Unstall the endpoint specified in wIndex */ - ep_cs = usb_get_endpoint_cs_reg(setup_data.windex); - if (!ep_cs) - return false; - *ep_cs &= ~EPSTALL; + ep_cs = usb_get_endpoint_cs_reg(setup_data.windex); + if (!ep_cs) + return false; + *ep_cs &= ~EPSTALL; } else { /* Unsupported feature, stall EP0 */ - STALL_EP0(); - } - break; - default: + STALL_EP0(); + } + break; + default: /* Vendor commands... */ break; } @@ -597,7 +617,6 @@ bool usb_handle_send_bitstream(void) /* wait until GPIF transaction has been completed */ while ((GPIFTRIG & BMGPIFDONE) == 0) { if (ix-- == 0) { - printf("GPIF done time out\n"); break; } delay_ms(1); @@ -697,9 +716,9 @@ void ep_init(void) syncdelay(3); EP4CFG = 0x00; syncdelay(3); - EP6CFG = 0x00; + EP6CFG = 0xA2; syncdelay(3); - EP8CFG = 0x00; + EP8CFG = 0xE2; syncdelay(3); /* arm EP1-OUT */ @@ -714,6 +733,12 @@ void ep_init(void) EP1INBC = 0; syncdelay(3); + /* arm EP6-OUT */ + EP6BCL = 0x80; + syncdelay(3); + EP6BCL = 0x80; + syncdelay(3); + /* Standard procedure to reset FIFOs */ FIFORESET = BMNAKALL; /* NAK all transfers during the reset */ syncdelay(3); @@ -727,9 +752,110 @@ void ep_init(void) syncdelay(3); } +void i2c_recieve(void) +{ + PIN_SDA_DIR = 0; + if (EP6FIFOBUF[0] == 1) { + uint8_t rdwr = EP6FIFOBUF[0]; //read + uint8_t reg_adr_check = EP6FIFOBUF[1]; + uint8_t count = EP6FIFOBUF[2]; //request data count + uint8_t adr = EP6FIFOBUF[3]; //address + uint8_t reg_adr = EP6FIFOBUF[4]; + uint8_t address = get_address(adr, rdwr); //address byte (read command) + uint8_t address_2 = get_address(adr, 0); //address byte 2 (write command) + + printf("%d\n", address); + + /* start: */ + start_cd(); + /* address: */ + send_byte(address_2); //write + /* ack: */ + uint8_t ack = get_ack(); + + delay_us(10); + + /* send data */ + if (reg_adr_check) { //if there is a byte reg + send_byte(reg_adr); + /* ack(): */ + ack = get_ack(); + } + + delay_us(10); + + /* repeated start: */ + repeated_start(); + /* address: */ + send_byte(address); + /* get ack: */ + ack = get_ack(); + + delay_us(10); + + /* receive data */ + for (uint8_t i = 0; i < count; i++) { + EP8FIFOBUF[i] = receive_byte(); + + /* send ack: */ + send_ack(); + } + + delay_ms(1); + + /* stop */ + stop_cd(); + + delay_us(10); + + EP8BCH = 0; //EP8 + syncdelay(3); + EP8BCL = count; //EP8 + + EP6BCL = 0x80; //EP6 + syncdelay(3); + EP6BCL = 0x80; //EP6 + } else { + uint8_t rdwr = EP6FIFOBUF[0]; //write + uint8_t count = EP6FIFOBUF[1]; //data count + uint8_t adr = EP6FIFOBUF[2]; //address + uint8_t address = get_address(adr, rdwr); //address byte (read command) + uint8_t ack_cnt = 0; + +/* start(): */ + start_cd(); +/* address: */ + send_byte(address); //write +/* ack(): */ + if (!get_ack()) + ack_cnt++; +/* send data */ + for (uint8_t i = 0; i < count; i++) { + send_byte(EP6FIFOBUF[i + 3]); + + /* get ack: */ + if (!get_ack()) + ack_cnt++; + } + +/* stop */ + stop_cd(); + + EP8FIFOBUF[0] = ack_cnt; + + EP8BCH = 0; //EP8 + syncdelay(3); + EP8BCL = 1; //EP8 + + EP6BCL = 0x80; //EP6 + syncdelay(3); + EP6BCL = 0x80; //EP6 + } +} + /** * Interrupt initialization. Configures USB interrupts. - */ + **/ void interrupt_init(void) { /* Enable Interrupts */ @@ -742,11 +868,11 @@ void interrupt_init(void) /* Enable INT 2 & 4 Autovectoring */ INTSETUP |= (AV2EN | AV4EN); - /* Enable individual EP1OUT&IN interrupts */ - EPIE |= 0x0C; + /* Enable individual EP1OUT&IN & EP6&8 interrupts */ + EPIE |= 0xCC; /* Clear individual USB interrupt IRQ */ - EPIRQ = 0x0C; + EPIRQ = 0xCC; /* Enable SUDAV interrupt */ USBIEN |= SUDAVI; @@ -777,8 +903,15 @@ void io_init(void) PIN_TDI = 0; PIN_SRST = 1; + + /* PORT C */ PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */ - OEC = 0xEF; + OEC = 0xFF; IOC = 0xFF; + + /* PORT D */ + OED = 0xFF; + IOD = 0xFF; + PIN_SDA_DIR = 0; } diff --git a/contrib/firmware/angie/hdl/Makefile b/contrib/firmware/angie/hdl/Makefile index c2c74a0b8..b28b65089 100644 --- a/contrib/firmware/angie/hdl/Makefile +++ b/contrib/firmware/angie/hdl/Makefile @@ -2,7 +2,7 @@ # Copyright (C) 2023 by NanoXplore, France - all rights reserved # Needed by timing test -export PROJECT := angie_openocd +export PROJECT := angie_bitstream TARGET_PART := xc6slx9-2tqg144 export TOPLEVEL := S609 diff --git a/contrib/firmware/angie/hdl/src/angie_openocd.ucf b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf similarity index 83% rename from contrib/firmware/angie/hdl/src/angie_openocd.ucf rename to contrib/firmware/angie/hdl/src/angie_bitstream.ucf index fda3cdaaf..92a89c99e 100644 --- a/contrib/firmware/angie/hdl/src/angie_openocd.ucf +++ b/contrib/firmware/angie/hdl/src/angie_bitstream.ucf @@ -14,17 +14,31 @@ net TRST LOC = 'P48' ; net TMS LOC = 'P43' ; net TCK LOC = 'P44' ; net TDI LOC = 'P45' ; -net TDO LOC = 'P46' ; +net TDO LOC = 'P46' ; net SRST LOC = 'P61' ; + +net SDA LOC = 'P50' ; +net SCL LOC = 'P51' ; +net SDA_DIR LOC = 'P56' ; + net SI_TDO LOC = 'P16' ; net SO_TRST LOC = 'P32' ; net SO_TMS LOC = 'P27' ; net SO_TCK LOC = 'P30' ; net SO_TDI LOC = 'P26' ; net SO_SRST LOC = 'P12' ; + +net SO_SDA_OUT LOC = 'P140' ; +net SO_SDA_IN LOC = 'P1' ; +net SO_SCL LOC = 'P137'; + net ST_0 LOC = 'P29' ; net ST_1 LOC = 'P21' ; net ST_2 LOC = 'P11' ; + +net ST_4 LOC = 'P134' ; +net ST_5 LOC = 'P139' ; + net FTP<0> LOC = 'P121' ; net FTP<1> LOC = 'P120' ; net FTP<2> LOC = 'P119' ; diff --git a/contrib/firmware/angie/hdl/src/angie_openocd.vhd b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd similarity index 55% rename from contrib/firmware/angie/hdl/src/angie_openocd.vhd rename to contrib/firmware/angie/hdl/src/angie_bitstream.vhd index d79c0fece..21ddb844a 100644 --- a/contrib/firmware/angie/hdl/src/angie_openocd.vhd +++ b/contrib/firmware/angie/hdl/src/angie_bitstream.vhd @@ -16,22 +16,35 @@ library UNISIM; use UNISIM.VComponents.all; entity S609 is port( - TRST : in std_logic; - TMS : in std_logic; - TCK : in std_logic; - TDI : in std_logic; - TDO : out std_logic; - SRST : in std_logic; - FTP : out std_logic_vector(7 downto 0); -- Test points + TRST : in std_logic; + TMS : in std_logic; + TCK : in std_logic; + TDI : in std_logic; + TDO : out std_logic; + SRST : in std_logic; + + SDA : inout std_logic; + SDA_DIR : in std_logic; + SCL : in std_logic; + + FTP : out std_logic_vector(7 downto 0):=(others => '1'); -- Test points SI_TDO : in std_logic; - ST_0 : out std_logic; - ST_1 : out std_logic; - ST_2 : out std_logic; + ST_0 : out std_logic; + ST_1 : out std_logic; + ST_2 : out std_logic; + + ST_4 : out std_logic; + ST_5 : out std_logic; + + SO_SDA_OUT : out std_logic; + SO_SDA_IN : in std_logic; + SO_SCL : out std_logic; + SO_TRST : out std_logic; - SO_TMS : out std_logic; - SO_TCK : out std_logic; + SO_TMS : out std_logic; + SO_TCK : out std_logic; SO_TDI : out std_logic; - SO_SRST :out std_logic + SO_SRST : out std_logic ); end S609; @@ -42,6 +55,8 @@ begin ST_0 <= '0'; ST_1 <= '1'; +ST_4 <= '0'; + --TDO: TDO <= not SI_TDO; @@ -53,11 +68,26 @@ SO_TDI <= TDI; ST_2 <= SRST; SO_SRST <= '0'; +SO_SCL <= SCL; + +SDA <= not(SO_SDA_IN) when (SDA_DIR = '1') else 'Z'; +SO_SDA_OUT <= SDA; + +process(SDA_DIR) +begin + if(SDA_DIR = '1') then + ST_5 <= '1'; + else + ST_5 <= '0'; + end if; +end process; + + --Points de test: -FTP(0) <= TRST; -FTP(1) <= TMS; -FTP(2) <= TCK; -FTP(3) <= TDI; +FTP(0) <= SDA; +FTP(1) <= SCL; +FTP(2) <= not(SO_SDA_IN); +FTP(3) <= SDA_DIR; FTP(5) <= SRST; FTP(4) <= SI_TDO; FTP(6) <= '1'; diff --git a/doc/openocd.texi b/doc/openocd.texi index c8a42f4a5..a2dacf27e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3597,6 +3597,79 @@ espusbjtag chip_id 1 @end deffn +@deffn {Interface Driver} {dmem} Direct Memory access debug interface + +The Texas Instruments K3 SoC family provides memory access to DAP +and coresight control registers. This allows control over the +microcontrollers directly from one of the processors on the SOC +itself. + +For maximum performance, the driver accesses the debug registers +directly over the SoC memory map. The memory mapping requires read +and write permission to kernel memory via "/dev/mem" and assumes that +the system firewall configurations permit direct access to the debug +memory space. + +@verbatim ++-----------+ +| OpenOCD | SoC mem map (/dev/mem) +| on +--------------+ +| Cortex-A53| | ++-----------+ | + | ++-----------+ +-----v-----+ +|Cortex-M4F <--------+ | ++-----------+ | | + | DebugSS | ++-----------+ | | +|Cortex-M4F <--------+ | ++-----------+ +-----------+ +@end verbatim + +NOTE: Firewalls are configurable in K3 SoC and depending on various types of +device configuration, this function may be blocked out. Typical behavior +observed in such cases is a firewall exception report on the security +controller and armv8 processor reporting a system error. + +See @file{tcl/interface/ti_k3_am625-swd-native.cfg} for a sample configuration +file. + +@deffn {Command} {dmem info} +Print the DAPBUS dmem configuration. +@end deffn + +@deffn {Config Command} {dmem device} device_path +Set the DAPBUS memory access device (default: /dev/mem). +@end deffn + +@deffn {Config Command} {dmem base_address} base_address +Set the DAPBUS base address which is used to access CoreSight +compliant Access Ports (APs) directly. +@end deffn + +@deffn {Config Command} {dmem ap_address_offset} offset_address +Set the address offset between Access Ports (APs). +@end deffn + +@deffn {Config Command} {dmem max_aps} n +Set the maximum number of valid access ports on the SoC. +@end deffn + +@deffn {Config Command} {dmem emu_ap_list} n +Set the list of Access Ports (APs) that need to be emulated. This +emulation mode supports software translation of an AP request into an +address mapped transaction that does not rely on physical AP hardware. +This maybe needed if the AP is either denied access via memory map or +protected using other SoC mechanisms. +@end deffn + +@deffn {Config Command} {dmem emu_base_address_range} base_address address_window_size +Set the emulated address and address window size. Both of these +parameters must be aligned to page size. +@end deffn + +@end deffn + @section Transport Configuration @cindex Transport As noted earlier, depending on the version of OpenOCD you use, diff --git a/doc/usb_adapters/angie/584e_424e_angie.txt b/doc/usb_adapters/angie/584e_424e_angie.txt index 8162cbad5..d68657a98 100644 --- a/doc/usb_adapters/angie/584e_424e_angie.txt +++ b/doc/usb_adapters/angie/584e_424e_angie.txt @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later -Bus 001 Device 056: ID 584e:424e NanoXplore, SAS. ANGIE Adapter +Bus 001 Device 029: ID 584e:424e NanoXplore, SAS. ANGIE Adapter Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 - bDeviceClass 255 Vendor Specific Class - bDeviceSubClass 255 Vendor Specific Subclass - bDeviceProtocol 255 Vendor Specific Protocol + bDeviceClass 239 Miscellaneous Device + bDeviceSubClass 2 + bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x584e idProduct 0x424e @@ -19,13 +19,22 @@ Device Descriptor: Configuration Descriptor: bLength 9 bDescriptorType 2 - wTotalLength 0x0027 - bNumInterfaces 1 + wTotalLength 0x0047 + bNumInterfaces 2 bConfigurationValue 1 - iConfiguration 4 (error) + iConfiguration 1 NanoXplore, SAS. bmAttributes 0x80 (Bus Powered) MaxPower 100mA + Interface Association: + bLength 8 + bDescriptorType 11 + bFirstInterface 1 + bInterfaceCount 2 + bFunctionClass 2 Communications + bFunctionSubClass 0 + bFunctionProtocol 0 + iFunction 0 Interface Descriptor: bLength 9 bDescriptorType 4 @@ -33,9 +42,9 @@ Device Descriptor: bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 255 Vendor Specific Class - bInterfaceSubClass 255 Vendor Specific Subclass - bInterfaceProtocol 255 Vendor Specific Protocol - iInterface 0 + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 4 JTAG Adapter Endpoint Descriptor: bLength 7 bDescriptorType 5 @@ -66,3 +75,33 @@ Device Descriptor: Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 1 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 10 CDC Data + bInterfaceSubClass 0 + bInterfaceProtocol 0 + iInterface 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x06 EP 6 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x88 EP 8 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 4b2dbc44d..e404afe9f 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -161,6 +161,9 @@ endif if RSHIM DRIVERFILES += %D%/rshim.c endif +if DMEM +DRIVERFILES += %D%/dmem.c +endif if OSBDM DRIVERFILES += %D%/osbdm.c endif diff --git a/src/jtag/drivers/angie.c b/src/jtag/drivers/angie.c index 35811fb80..9cc086599 100644 --- a/src/jtag/drivers/angie.c +++ b/src/jtag/drivers/angie.c @@ -30,8 +30,10 @@ /** USB Product ID of ANGIE device in unconfigured state (no firmware loaded * yet) or with its firmware. */ -#define ANGIE_PID 0x424e -#define ANGIE_PID_2 0x4a55 +#define ANGIE_PID 0x424e +#define ANGIE_PID_2 0x4255 +#define ANGIE_PID_3 0x4355 +#define ANGIE_PID_4 0x4a55 /** Address of EZ-USB ANGIE CPU Control & Status register. This register can be * written by issuing a Control EP0 vendor request. */ @@ -252,8 +254,8 @@ static struct angie *angie_handle; static int angie_usb_open(struct angie *device) { struct libusb_device_handle *usb_device_handle; - const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, 0}; - const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, 0}; + const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0}; + const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, 0}; int ret = jtag_libusb_open(vids, pids, &usb_device_handle, NULL); @@ -1719,6 +1721,8 @@ static int angie_reset(int trst, int srst) high |= SIGNAL_SRST; int ret = angie_append_set_signals_cmd(device, low, high); + if (ret == ERROR_OK) + angie_clear_queue(device); ret = angie_execute_queued_commands(device, LIBUSB_TIMEOUT_MS); if (ret == ERROR_OK) diff --git a/src/jtag/drivers/angie/angie_bitstream.bit b/src/jtag/drivers/angie/angie_bitstream.bit index 9e83e6b69..aebd3700b 100644 Binary files a/src/jtag/drivers/angie/angie_bitstream.bit and b/src/jtag/drivers/angie/angie_bitstream.bit differ diff --git a/src/jtag/drivers/angie/angie_firmware.bin b/src/jtag/drivers/angie/angie_firmware.bin index 38f81c4ae..da69631d9 100644 Binary files a/src/jtag/drivers/angie/angie_firmware.bin and b/src/jtag/drivers/angie/angie_firmware.bin differ diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 39e4af365..f41f7b51e 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -167,7 +167,8 @@ static void initialize_gpio(enum adapter_gpio_config_index idx) } /* Direction for non push-pull is already set by set_gpio_value() */ - if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) + if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL + && adapter_gpio_config[idx].init_state != ADAPTER_GPIO_INIT_STATE_INPUT) OUT_GPIO(adapter_gpio_config[idx].gpio_num); bcm2835_gpio_synchronize(); } diff --git a/src/jtag/drivers/dmem.c b/src/jtag/drivers/dmem.c new file mode 100644 index 000000000..4dc582115 --- /dev/null +++ b/src/jtag/drivers/dmem.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ */ + +/** + * @file + * This file implements support for the Direct memory access to CoreSight + * Access Ports (APs) or emulate the same to access CoreSight debug registers + * directly. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct dmem_emu_ap_info { + uint64_t ap_num; + /* Emulation mode AP state variables */ + uint32_t apbap_tar; + uint32_t apbap_csw; +}; + +/* + * This bit tells if the transaction is coming in from jtag or not + * we just mask this out to emulate direct address access + */ +#define ARM_APB_PADDR31 BIT(31) + +static void *dmem_map_base, *dmem_virt_base_addr; +static size_t dmem_mapped_size; + +/* Default dmem device. */ +#define DMEM_DEV_PATH_DEFAULT "/dev/mem" +static char *dmem_dev_path; +static uint64_t dmem_dap_base_address; +static unsigned int dmem_dap_max_aps = 1; +static uint32_t dmem_dap_ap_offset = 0x100; + +/* DAP error code. */ +static int dmem_dap_retval = ERROR_OK; + +/* AP Emulation Mode */ +static uint64_t dmem_emu_base_address; +static uint64_t dmem_emu_size; +static void *dmem_emu_map_base, *dmem_emu_virt_base_addr; +static size_t dmem_emu_mapped_size; +#define DMEM_MAX_EMULATE_APS 5 +static unsigned int dmem_emu_ap_count; +static struct dmem_emu_ap_info dmem_emu_ap_list[DMEM_MAX_EMULATE_APS]; + +/* + * This helper is used to determine the TAR increment size in bytes. The AP's + * CSW encoding for SIZE supports byte count decode using "1 << SIZE". + */ +static uint32_t dmem_memap_tar_inc(uint32_t csw) +{ + if ((csw & CSW_ADDRINC_MASK) != 0) + return 1 << (csw & CSW_SIZE_MASK); + return 0; +} + +/* + * EMULATION MODE: In Emulation MODE, we assume the following: + * TCL still describes as system is operational from the view of AP (ex. jtag) + * However, the hardware doesn't permit direct memory access to these APs + * (only permitted via JTAG). + * + * So, the access to these APs have to be decoded to a memory map + * access which we can directly access. + * + * A few TI processors have this issue. + */ +static bool dmem_is_emulated_ap(struct adiv5_ap *ap, unsigned int *idx) +{ + for (unsigned int i = 0; i < dmem_emu_ap_count; i++) { + if (ap->ap_num == dmem_emu_ap_list[i].ap_num) { + *idx = i; + return true; + } + } + return false; +} + +static void dmem_emu_set_ap_reg(uint64_t addr, uint32_t val) +{ + addr &= ~ARM_APB_PADDR31; + + *(volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr) = val; +} + +static uint32_t dmem_emu_get_ap_reg(uint64_t addr) +{ + uint32_t val; + + addr &= ~ARM_APB_PADDR31; + + val = *(volatile uint32_t *)((uintptr_t)dmem_emu_virt_base_addr + addr); + + return val; +} + +static int dmem_emu_ap_q_read(unsigned int ap_idx, unsigned int reg, uint32_t *data) +{ + uint64_t addr; + int ret = ERROR_OK; + struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx]; + + switch (reg) { + case ADIV5_MEM_AP_REG_CSW: + *data = ap_info->apbap_csw; + break; + case ADIV5_MEM_AP_REG_TAR: + *data = ap_info->apbap_tar; + break; + case ADIV5_MEM_AP_REG_CFG: + *data = 0; + break; + case ADIV5_MEM_AP_REG_BASE: + *data = 0; + break; + case ADIV5_AP_REG_IDR: + *data = 0; + break; + case ADIV5_MEM_AP_REG_BD0: + case ADIV5_MEM_AP_REG_BD1: + case ADIV5_MEM_AP_REG_BD2: + case ADIV5_MEM_AP_REG_BD3: + addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C); + + *data = dmem_emu_get_ap_reg(addr); + + break; + case ADIV5_MEM_AP_REG_DRW: + addr = ap_info->apbap_tar; + + *data = dmem_emu_get_ap_reg(addr); + + ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw); + break; + default: + LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg); + ret = ERROR_FAIL; + break; + } + + /* Track the last error code. */ + if (ret != ERROR_OK) + dmem_dap_retval = ret; + + return ret; +} + +static int dmem_emu_ap_q_write(unsigned int ap_idx, unsigned int reg, uint32_t data) +{ + uint64_t addr; + int ret = ERROR_OK; + struct dmem_emu_ap_info *ap_info = &dmem_emu_ap_list[ap_idx]; + + switch (reg) { + case ADIV5_MEM_AP_REG_CSW: + /* + * This implementation only supports 32-bit accesses. + * Force this by ensuring CSW_SIZE field indicates 32-BIT. + */ + ap_info->apbap_csw = ((data & ~CSW_SIZE_MASK) | CSW_32BIT); + break; + case ADIV5_MEM_AP_REG_TAR: + /* + * This implementation only supports 32-bit accesses. + * Force LS 2-bits of TAR to 00b + */ + ap_info->apbap_tar = (data & ~0x3); + break; + + case ADIV5_MEM_AP_REG_CFG: + case ADIV5_MEM_AP_REG_BASE: + case ADIV5_AP_REG_IDR: + /* We don't use this, so we don't need to store */ + break; + + case ADIV5_MEM_AP_REG_BD0: + case ADIV5_MEM_AP_REG_BD1: + case ADIV5_MEM_AP_REG_BD2: + case ADIV5_MEM_AP_REG_BD3: + addr = (ap_info->apbap_tar & ~0xf) + (reg & 0x0C); + + dmem_emu_set_ap_reg(addr, data); + + break; + case ADIV5_MEM_AP_REG_DRW: + addr = ap_info->apbap_tar; + dmem_emu_set_ap_reg(addr, data); + + ap_info->apbap_tar += dmem_memap_tar_inc(ap_info->apbap_csw); + break; + default: + LOG_INFO("%s: Unknown reg: 0x%02x", __func__, reg); + ret = EINVAL; + break; + } + + /* Track the last error code. */ + if (ret != ERROR_OK) + dmem_dap_retval = ret; + + return ret; +} + +/* AP MODE */ +static uint32_t dmem_get_ap_reg_offset(struct adiv5_ap *ap, unsigned int reg) +{ + return (dmem_dap_ap_offset * ap->ap_num) + reg; +} + +static void dmem_set_ap_reg(struct adiv5_ap *ap, unsigned int reg, uint32_t val) +{ + *(volatile uint32_t *)((uintptr_t)dmem_virt_base_addr + + dmem_get_ap_reg_offset(ap, reg)) = val; +} + +static uint32_t dmem_get_ap_reg(struct adiv5_ap *ap, unsigned int reg) +{ + return *(volatile uint32_t *)((uintptr_t)dmem_virt_base_addr + + dmem_get_ap_reg_offset(ap, reg)); +} + +static int dmem_dp_q_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) +{ + if (!data) + return ERROR_OK; + + switch (reg) { + case DP_CTRL_STAT: + *data = CDBGPWRUPACK | CSYSPWRUPACK; + break; + + default: + *data = 0; + break; + } + + return ERROR_OK; +} + +static int dmem_dp_q_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) +{ + return ERROR_OK; +} + +static int dmem_ap_q_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) +{ + unsigned int idx; + + if (is_adiv6(ap->dap)) { + static bool error_flagged; + + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by dmem dap-direct mode"); + + error_flagged = true; + + return ERROR_FAIL; + } + + if (dmem_is_emulated_ap(ap, &idx)) + return dmem_emu_ap_q_read(idx, reg, data); + + *data = dmem_get_ap_reg(ap, reg); + + return ERROR_OK; +} + +static int dmem_ap_q_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) +{ + unsigned int idx; + + if (is_adiv6(ap->dap)) { + static bool error_flagged; + + if (!error_flagged) + LOG_ERROR("ADIv6 dap not supported by dmem dap-direct mode"); + + error_flagged = true; + + return ERROR_FAIL; + } + + if (dmem_is_emulated_ap(ap, &idx)) + return dmem_emu_ap_q_write(idx, reg, data); + + dmem_set_ap_reg(ap, reg, data); + + return ERROR_OK; +} + +static int dmem_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack) +{ + return ERROR_OK; +} + +static int dmem_dp_run(struct adiv5_dap *dap) +{ + int retval = dmem_dap_retval; + + /* Clear the error code. */ + dmem_dap_retval = ERROR_OK; + + return retval; +} + +static int dmem_connect(struct adiv5_dap *dap) +{ + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_device_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + free(dmem_dev_path); + dmem_dev_path = strdup(CMD_ARGV[0]); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_base_address_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], dmem_dap_base_address); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_max_aps_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], dmem_dap_max_aps); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_ap_offset_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], dmem_dap_ap_offset); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_emu_base_address_command) +{ + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], dmem_emu_base_address); + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], dmem_emu_size); + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_emu_ap_list_command) +{ + uint64_t em_ap; + + if (CMD_ARGC < 1 || CMD_ARGC > DMEM_MAX_EMULATE_APS) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned int i = 0; i < CMD_ARGC; i++) { + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[i], em_ap); + dmem_emu_ap_list[i].ap_num = em_ap; + } + + dmem_emu_ap_count = CMD_ARGC; + + return ERROR_OK; +} + +COMMAND_HANDLER(dmem_dap_config_info_command) +{ + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + command_print(CMD, "dmem (Direct Memory) AP Adapter Configuration:"); + command_print(CMD, " Device : %s", + dmem_dev_path ? dmem_dev_path : DMEM_DEV_PATH_DEFAULT); + command_print(CMD, " Base Address : 0x%" PRIx64, dmem_dap_base_address); + command_print(CMD, " Max APs : %u", dmem_dap_max_aps); + command_print(CMD, " AP offset : 0x%08" PRIx32, dmem_dap_ap_offset); + command_print(CMD, " Emulated AP Count : %u", dmem_emu_ap_count); + + if (dmem_emu_ap_count) { + command_print(CMD, " Emulated AP details:"); + command_print(CMD, " Emulated address : 0x%" PRIx64, dmem_emu_base_address); + command_print(CMD, " Emulated size : 0x%" PRIx64, dmem_emu_size); + for (unsigned int i = 0; i < dmem_emu_ap_count; i++) + command_print(CMD, " Emulated AP [%u] : %" PRIx64, i, + dmem_emu_ap_list[i].ap_num); + } + return ERROR_OK; +} + +static const struct command_registration dmem_dap_subcommand_handlers[] = { + { + .name = "info", + .handler = dmem_dap_config_info_command, + .mode = COMMAND_ANY, + .help = "print the config info", + .usage = "", + }, + { + .name = "device", + .handler = dmem_dap_device_command, + .mode = COMMAND_CONFIG, + .help = "set the dmem memory access device (default: /dev/mem)", + .usage = "device_path", + }, + { + .name = "base_address", + .handler = dmem_dap_base_address_command, + .mode = COMMAND_CONFIG, + .help = "set the dmem dap AP memory map base address", + .usage = "base_address", + }, + { + .name = "ap_address_offset", + .handler = dmem_dap_ap_offset_command, + .mode = COMMAND_CONFIG, + .help = "set the offsets of each ap index", + .usage = "offset_address", + }, + { + .name = "max_aps", + .handler = dmem_dap_max_aps_command, + .mode = COMMAND_CONFIG, + .help = "set the maximum number of APs this will support", + .usage = "n", + }, + { + .name = "emu_ap_list", + .handler = dmem_emu_ap_list_command, + .mode = COMMAND_CONFIG, + .help = "set the list of AP indices to be emulated (upto max)", + .usage = "n", + }, + { + .name = "emu_base_address_range", + .handler = dmem_emu_base_address_command, + .mode = COMMAND_CONFIG, + .help = "set the base address and size of emulated AP range (all emulated APs access this range)", + .usage = "base_address address_window_size", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration dmem_dap_command_handlers[] = { + { + .name = "dmem", + .mode = COMMAND_ANY, + .help = "Perform dmem (Direct Memory) DAP management and configuration", + .chain = dmem_dap_subcommand_handlers, + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static int dmem_dap_init(void) +{ + char *path = dmem_dev_path ? dmem_dev_path : DMEM_DEV_PATH_DEFAULT; + uint32_t dmem_total_memory_window_size; + long page_size = sysconf(_SC_PAGESIZE); + size_t dmem_mapped_start, dmem_mapped_end; + long start_delta; + int dmem_fd; + + if (!dmem_dap_base_address) { + LOG_ERROR("dmem DAP Base address NOT set? value is 0"); + return ERROR_FAIL; + } + + dmem_fd = open(path, O_RDWR | O_SYNC); + if (dmem_fd == -1) { + LOG_ERROR("Unable to open %s", path); + return ERROR_FAIL; + } + + dmem_total_memory_window_size = (dmem_dap_max_aps + 1) * dmem_dap_ap_offset; + + dmem_mapped_start = dmem_dap_base_address; + dmem_mapped_end = dmem_dap_base_address + dmem_total_memory_window_size; + /* mmap() requires page aligned offsets */ + dmem_mapped_start = ALIGN_DOWN(dmem_mapped_start, page_size); + dmem_mapped_end = ALIGN_UP(dmem_mapped_end, page_size); + + dmem_mapped_size = dmem_mapped_end - dmem_mapped_start; + start_delta = dmem_mapped_start - dmem_dap_base_address; + + dmem_map_base = mmap(NULL, + dmem_mapped_size, + (PROT_READ | PROT_WRITE), + MAP_SHARED, dmem_fd, + dmem_mapped_start); + if (dmem_map_base == MAP_FAILED) { + LOG_ERROR("Mapping address 0x%lx for 0x%lx bytes failed!", + dmem_mapped_start, dmem_mapped_size); + goto error_fail; + } + + dmem_virt_base_addr = (void *)((uintptr_t)dmem_map_base + start_delta); + + /* Lets Map the emulated address if necessary */ + if (dmem_emu_ap_count) { + dmem_mapped_start = dmem_emu_base_address; + dmem_mapped_end = dmem_emu_base_address + dmem_emu_size; + /* mmap() requires page aligned offsets */ + dmem_mapped_start = ALIGN_DOWN(dmem_mapped_start, page_size); + dmem_mapped_end = ALIGN_UP(dmem_mapped_end, page_size); + + dmem_emu_mapped_size = dmem_mapped_end - dmem_mapped_start; + start_delta = dmem_mapped_start - dmem_emu_base_address; + + dmem_emu_map_base = mmap(NULL, + dmem_emu_mapped_size, + (PROT_READ | PROT_WRITE), + MAP_SHARED, dmem_fd, + dmem_mapped_start); + if (dmem_emu_map_base == MAP_FAILED) { + LOG_ERROR("Mapping EMU address 0x%lx for 0x%lx bytes failed!", + dmem_emu_base_address, dmem_emu_size); + goto error_fail; + } + dmem_emu_virt_base_addr = (void *)((uintptr_t)dmem_emu_map_base + + start_delta); + } + + close(dmem_fd); + return ERROR_OK; + +error_fail: + close(dmem_fd); + return ERROR_FAIL; +} + +static int dmem_dap_quit(void) +{ + if (munmap(dmem_map_base, dmem_mapped_size) == -1) + LOG_ERROR("%s: Failed to unmap mapped memory!", __func__); + + if (dmem_emu_ap_count + && munmap(dmem_emu_map_base, dmem_emu_mapped_size) == -1) + LOG_ERROR("%s: Failed to unmap emu mapped memory!", __func__); + + return ERROR_OK; +} + +static int dmem_dap_reset(int req_trst, int req_srst) +{ + return ERROR_OK; +} + +static int dmem_dap_speed(int speed) +{ + return ERROR_OK; +} + +static int dmem_dap_khz(int khz, int *jtag_speed) +{ + *jtag_speed = khz; + return ERROR_OK; +} + +static int dmem_dap_speed_div(int speed, int *khz) +{ + *khz = speed; + return ERROR_OK; +} + +/* DAP operations. */ +static const struct dap_ops dmem_dap_ops = { + .connect = dmem_connect, + .queue_dp_read = dmem_dp_q_read, + .queue_dp_write = dmem_dp_q_write, + .queue_ap_read = dmem_ap_q_read, + .queue_ap_write = dmem_ap_q_write, + .queue_ap_abort = dmem_ap_q_abort, + .run = dmem_dp_run, +}; + +static const char *const dmem_dap_transport[] = { "dapdirect_swd", NULL }; + +struct adapter_driver dmem_dap_adapter_driver = { + .name = "dmem", + .transports = dmem_dap_transport, + .commands = dmem_dap_command_handlers, + + .init = dmem_dap_init, + .quit = dmem_dap_quit, + .reset = dmem_dap_reset, + .speed = dmem_dap_speed, + .khz = dmem_dap_khz, + .speed_div = dmem_dap_speed_div, + + .dap_swd_ops = &dmem_dap_ops, +}; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 2c5b63dd6..c5326a206 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -456,7 +456,7 @@ static inline int stlink_usb_xfer_noerrcheck(void *handle, const uint8_t *buf, i #define STLINK_DEBUG_PORT_ACCESS 0xffff #define STLINK_TRACE_SIZE 4096 -#define STLINK_TRACE_MAX_HZ 2000000 +#define STLINK_TRACE_MAX_HZ 2250000 #define STLINK_V3_TRACE_MAX_HZ 24000000 #define STLINK_V3_MAX_FREQ_NB 10 diff --git a/src/jtag/interface.h b/src/jtag/interface.h index 25ae7e8a1..3df424086 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -370,6 +370,7 @@ extern struct adapter_driver at91rm9200_adapter_driver; extern struct adapter_driver bcm2835gpio_adapter_driver; extern struct adapter_driver buspirate_adapter_driver; extern struct adapter_driver cmsis_dap_adapter_driver; +extern struct adapter_driver dmem_dap_adapter_driver; extern struct adapter_driver dummy_adapter_driver; extern struct adapter_driver ep93xx_adapter_driver; extern struct adapter_driver esp_usb_adapter_driver; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index aa0ad3ade..c24ead8cd 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -147,6 +147,9 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_RSHIM == 1 &rshim_dap_adapter_driver, #endif +#if BUILD_DMEM == 1 + &dmem_dap_adapter_driver, +#endif #if BUILD_AM335XGPIO == 1 &am335xgpio_adapter_driver, #endif diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c index 934a8dd1c..a4c60904b 100644 --- a/src/rtos/zephyr.c +++ b/src/rtos/zephyr.c @@ -57,6 +57,7 @@ enum zephyr_offsets { OFFSET_T_ARCH, OFFSET_T_PREEMPT_FLOAT, OFFSET_T_COOP_FLOAT, + OFFSET_T_ARM_EXC_RETURN, OFFSET_MAX }; diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 2084de65e..1fc7d2afa 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -204,6 +204,7 @@ ARC_SRC = \ %D%/image.h \ %D%/mips32.h \ %D%/mips64.h \ + %D%/mips_cpu.h \ %D%/mips_m4k.h \ %D%/mips_mips64.h \ %D%/mips_ejtag.h \ diff --git a/src/target/arm.h b/src/target/arm.h index f3abd6cba..28e533019 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -61,6 +61,7 @@ enum arm_arch { /** Known ARM implementor IDs */ enum arm_implementor { ARM_IMPLEMENTOR_ARM = 0x41, + ARM_IMPLEMENTOR_REALTEK = 0x72, }; /** diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 87a884552..014ceaeba 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -111,6 +111,17 @@ static const struct cortex_m_part_info cortex_m_parts[] = { .arch = ARM_ARCH_V8M, .flags = CORTEX_M_F_HAS_FPV5, }, + { + .impl_part = REALTEK_M200_PARTNO, + .name = "Real-M200 (KM0)", + .arch = ARM_ARCH_V8M, + }, + { + .impl_part = REALTEK_M300_PARTNO, + .name = "Real-M300 (KM4)", + .arch = ARM_ARCH_V8M, + .flags = CORTEX_M_F_HAS_FPV5, + }, }; /* forward declarations */ diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index 806ff5910..b5d1da7f2 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -56,6 +56,8 @@ enum cortex_m_impl_part { CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21), CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31), CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22), + REALTEK_M200_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd20), + REALTEK_M300_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_REALTEK, 0xd22), }; /* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */ diff --git a/src/target/mips32.c b/src/target/mips32.c index ce16a7b5d..4e6d25118 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -18,6 +18,7 @@ #endif #include "mips32.h" +#include "mips_cpu.h" #include "breakpoints.h" #include "algorithm.h" #include "register.h" @@ -693,6 +694,63 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } +/* read processor identification cp0 register */ +static int mips32_read_c0_prid(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + int retval; + + retval = mips32_cp0_read(ejtag_info, &mips32->prid, 15, 0); + if (retval != ERROR_OK) { + LOG_ERROR("processor id not available, failed to read cp0 PRId register"); + mips32->prid = 0; + } + + return retval; +} + +/* + * Detect processor type and apply required quirks. + * + * NOTE: The proper detection of certain CPUs can become quite complicated. + * Please consult the following Linux kernel code when adding new CPUs: + * arch/mips/include/asm/cpu.h + * arch/mips/kernel/cpu-probe.c + */ +int mips32_cpu_probe(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + const char *cpu_name = "unknown"; + int retval; + + if (mips32->prid) + return ERROR_OK; /* Already probed once, return early. */ + + retval = mips32_read_c0_prid(target); + if (retval != ERROR_OK) + return retval; + + switch (mips32->prid & PRID_COMP_MASK) { + case PRID_COMP_INGENIC_E1: + switch (mips32->prid & PRID_IMP_MASK) { + case PRID_IMP_XBURST_REV1: + cpu_name = "Ingenic XBurst rev1"; + mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET; + break; + default: + break; + } + break; + default: + break; + } + + LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, mips32->prid); + + return ERROR_OK; +} + /* read config to config3 cp0 registers and log isa implementation */ int mips32_read_config_regs(struct target *target) { diff --git a/src/target/mips32.h b/src/target/mips32.h index 81b6d649d..3d03e98c5 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -13,6 +13,8 @@ #ifndef OPENOCD_TARGET_MIPS32_H #define OPENOCD_TARGET_MIPS32_H +#include + #include "target.h" #include "mips32_pracc.h" @@ -55,6 +57,9 @@ #define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 +/* Insert extra NOPs after the DRET instruction on exit from debug. */ +#define EJTAG_QUIRK_PAD_DRET BIT(0) + /* offsets into mips32 core register cache */ enum { MIPS32_PC = 37, @@ -91,6 +96,11 @@ struct mips32_common { enum mips32_isa_mode isa_mode; enum mips32_isa_imp isa_imp; + /* processor identification register */ + uint32_t prid; + /* CPU specific quirks */ + uint32_t cpu_quirks; + /* working area for fastdata access */ struct working_area *fast_data_area; @@ -408,6 +418,8 @@ int mips32_enable_interrupts(struct target *target, int enable); int mips32_examine(struct target *target); +int mips32_cpu_probe(struct target *target); + int mips32_read_config_regs(struct target *target); int mips32_register_commands(struct command_context *cmd_ctx); diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h new file mode 100644 index 000000000..8190b32e4 --- /dev/null +++ b/src/target/mips_cpu.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef OPENOCD_TARGET_MIPS_CPU_H +#define OPENOCD_TARGET_MIPS_CPU_H + +/* + * NOTE: The proper detection of certain CPUs can become quite complicated. + * Please consult the following Linux kernel code when adding new CPUs: + * arch/mips/include/asm/cpu.h + * arch/mips/kernel/cpu-probe.c + */ + +/* Assigned Company values for bits 23:16 of the PRId register. */ +#define PRID_COMP_MASK 0xff0000 + +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_INGENIC_E1 0xe10000 + +/* + * Assigned Processor ID (implementation) values for bits 15:8 of the PRId + * register. In order to detect a certain CPU type exactly eventually additional + * registers may need to be examined. + */ +#define PRID_IMP_MASK 0xff00 + +#define PRID_IMP_XBURST_REV1 0x0200 /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */ + +#endif /* OPENOCD_TARGET_MIPS_CPU_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index a1a179216..5c92bf9ee 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -259,9 +259,12 @@ int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { struct pa_list pracc_list = {.instr = MIPS32_DRET(ejtag_info->isa), .addr = 0}; struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; + struct mips32_common *mips32 = container_of(ejtag_info, + struct mips32_common, ejtag_info); /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* shift out instr, omit last check */ + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, + mips32->cpu_quirks & EJTAG_QUIRK_PAD_DRET); /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 14e3f3b27..46d241cb3 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -100,6 +100,8 @@ static int mips_m4k_debug_entry(struct target *target) /* attempt to find halt reason */ mips_m4k_examine_debug_reason(target); + mips32_cpu_probe(target); + mips32_read_config_regs(target); /* default to mips32 isa, it will be changed below if required */ diff --git a/tcl/board/ti_am625_swd_native.cfg b/tcl/board/ti_am625_swd_native.cfg new file mode 100644 index 000000000..dc4b20579 --- /dev/null +++ b/tcl/board/ti_am625_swd_native.cfg @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments am625 +# Link: https://www.ti.com/product/AM625 +# +# This configuration file is used as a self hosted debug configuration that +# works on every AM625 platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside AM625 and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC am625 +} + +source [find target/ti_k3.cfg] diff --git a/tcl/board/ti_am62a7evm.cfg b/tcl/board/ti_am62a7evm.cfg new file mode 100644 index 000000000..e40790950 --- /dev/null +++ b/tcl/board/ti_am62a7evm.cfg @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments am62a7 EVM/SK +# Link: https://www.ti.com/tool/SK-AM62A-LP +# + +# AM62a7 EVM/SK has an xds110 onboard. +source [find interface/xds110.cfg] + +transport select jtag + +# default JTAG configuration has only SRST and no TRST +reset_config srst_only srst_push_pull + +# delay after SRST goes inactive +adapter srst delay 20 + +if { ![info exists SOC] } { + set SOC am62a7 +} + +source [find target/ti_k3.cfg] + +adapter speed 2500 diff --git a/tcl/board/ti_j721e_swd_native.cfg b/tcl/board/ti_j721e_swd_native.cfg new file mode 100644 index 000000000..3041c3c34 --- /dev/null +++ b/tcl/board/ti_j721e_swd_native.cfg @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022-2023 Texas Instruments Incorporated - http://www.ti.com/ +# +# Texas Instruments TDA4VM/J721E +# Link: https://www.ti.com/product/TDA4VM +# +# This configuration file is used as a self hosted debug configuration that +# works on every TDA4VM platform based on firewall configuration permitted +# in the system. +# +# In this system openOCD runs on one of the CPUs inside TDA4VM and provides +# network ports that can then be used to debug the microcontrollers on the +# SoC - either self hosted IDE OR remotely. + +# We are using dmem, which uses dapdirect_swd transport +adapter driver dmem + +if { ![info exists SOC] } { + set SOC j721e +} +source [find target/ti_k3.cfg] diff --git a/tcl/cpu/arc/v2.tcl b/tcl/cpu/arc/v2.tcl index d28b9d974..b24a67d0b 100644 --- a/tcl/cpu/arc/v2.tcl +++ b/tcl/cpu/arc/v2.tcl @@ -173,8 +173,8 @@ proc arc_v2_init_regs { } { r19 19 uint32 r20 20 uint32 r21 21 uint32 - r22 23 uint32 - r23 24 uint32 + r22 22 uint32 + r23 23 uint32 r24 24 uint32 r25 25 uint32 gp 26 data_ptr diff --git a/tcl/target/rtl872xd.cfg b/tcl/target/rtl872xd.cfg new file mode 100644 index 000000000..65730e217 --- /dev/null +++ b/tcl/target/rtl872xd.cfg @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0-or-later OR MIT +# Realtek RTL872xD (ARM Cortex-M33 + M23, wifi+bt dualband soc) + +# HLA does not support AP other than 0 +if { [using_hla] } { + echo "ERROR: HLA transport cannot work with this target." + shutdown +} + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME rtl872xd +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x6ba02477 +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME.km0 cortex_m -endian little -dap $_CHIPNAME.dap -ap-num 1 +target create $_TARGETNAME.km4 cortex_m -endian little -dap $_CHIPNAME.dap -ap-num 2 + +cortex_m reset_config sysresetreq + +adapter speed 1000 diff --git a/tcl/target/ti_k3.cfg b/tcl/target/ti_k3.cfg index 2454357fc..f0881cdff 100644 --- a/tcl/target/ti_k3.cfg +++ b/tcl/target/ti_k3.cfg @@ -8,8 +8,14 @@ # Has 2 ARMV8 Cores and 6 R5 Cores and an M3 # * J7200: https://www.ti.com/lit/pdf/spruiu1 # Has 2 ARMV8 Cores and 4 R5 Cores and an M3 +# * J721S2: https://www.ti.com/lit/pdf/spruj28 +# Has 2 ARMV8 Cores and 6 R5 Cores and an M4F # * AM642: https://www.ti.com/lit/pdf/spruim2 # Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3 +# * AM625: https://www.ti.com/lit/pdf/spruiv7a +# Has 4 ARMV8 Cores and 1 R5 Core and an M4F +# * AM62a7: https://www.ti.com/lit/pdf/spruj16a +# Has 4 ARMV8 Cores and 2 R5 Cores # source [find target/swj-dp.tcl] @@ -114,6 +120,37 @@ switch $_soc { # M4 processor set _gp_mcu_cores 1 set _gp_mcu_ap_unlock_offsets {0xf0 0x7c} + + # Setup DMEM access descriptions + # DAPBUS (Debugger) description + set _dmem_base_address 0x740002000 + set _dmem_ap_address_offset 0x100 + set _dmem_max_aps 10 + # Emulated AP description + set _dmem_emu_base_address 0x760000000 + set _dmem_emu_base_address_map_to 0x1d500000 + set _dmem_emu_ap_list 1 + } + am62a7 { + set _CHIPNAME am62a7 + set _K3_DAP_TAPID 0x0bb8d02f + + # AM62a7 has 1 clusters of 4 A53 cores. + set _armv8_cpu_name a53 + set _armv8_cores 4 + set ARMV8_DBGBASE {0x90010000 0x90110000 0x90210000 0x90310000} + set ARMV8_CTIBASE {0x90020000 0x90120000 0x90220000 0x90320000} + + # AM62a7 has 2 cluster of 1 R5s core. + set _r5_cores 2 + set R5_NAMES {main0_r5.0 mcu0_r5.0} + set R5_DBGBASE {0x9d410000 0x9d810000} + set R5_CTIBASE {0x9d418000 0x9d818000} + + # sysctrl CTI base + set CM3_CTIBASE {0x20001000} + # Sysctrl power-ap unlock offsets + set _sysctrl_ap_unlock_offsets {0xf0 0x78} } j721e { set _CHIPNAME j721e @@ -124,6 +161,16 @@ switch $_soc { # J721E has 3 clusters of 2 R5 cores each. set _r5_cores 6 + + # Setup DMEM access descriptions + # DAPBUS (Debugger) description + set _dmem_base_address 0x4c40002000 + set _dmem_ap_address_offset 0x100 + set _dmem_max_aps 8 + # Emulated AP description + set _dmem_emu_base_address 0x4c60000000 + set _dmem_emu_base_address_map_to 0x1d600000 + set _dmem_emu_ap_list 1 } j7200 { set _CHIPNAME j7200 @@ -302,3 +349,22 @@ if { $_gp_mcu_cores != 0 } { halt 1000 } } + +# In case of DMEM access, configure the dmem adapter with offsets from above. +if { 0 == [string compare [adapter name] dmem ] } { + if { [info exists _dmem_base_address] } { + # DAPBUS (Debugger) description + dmem base_address $_dmem_base_address + dmem ap_address_offset $_dmem_ap_address_offset + dmem max_aps $_dmem_max_aps + + # The following are the details of APs to be emulated for direct address access. + # Debug Config (Debugger) description + dmem emu_base_address_range $_dmem_emu_base_address $_dmem_emu_base_address_map_to + dmem emu_ap_list $_dmem_emu_ap_list + # We are going local bus, so speed is really dummy here. + adapter speed 2500 + } else { + puts "ERROR: ${SOC} data is missing to support dmem access!" + } +}