Merge pull request #967 from riscv/from_upstream
Merge up to 4b1ea8511a
from upstream
This commit is contained in:
commit
e9484bab54
15
configure.ac
15
configure.ac
|
@ -243,6 +243,10 @@ AC_ARG_ENABLE([rshim],
|
||||||
AS_HELP_STRING([--enable-rshim], [Enable building the rshim driver]),
|
AS_HELP_STRING([--enable-rshim], [Enable building the rshim driver]),
|
||||||
[build_rshim=$enableval], [build_rshim=no])
|
[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_define([AC_ARG_ADAPTERS], [
|
||||||
m4_foreach([adapter], [$1],
|
m4_foreach([adapter], [$1],
|
||||||
[AC_ARG_ENABLE(ADAPTER_OPT([adapter]),
|
[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])
|
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],
|
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.])
|
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"], [
|
AS_IF([test "x$build_dummy" = "xyes"], [
|
||||||
build_bitbang=yes
|
build_bitbang=yes
|
||||||
AC_DEFINE([BUILD_DUMMY], [1], [1 if you want dummy driver.])
|
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_HIDAPI], [test "x$use_hidapi" = "xyes"])
|
||||||
AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"])
|
AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"])
|
||||||
AM_CONDITIONAL([RSHIM], [test "x$build_rshim" = "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([HAVE_CAPSTONE], [test "x$enable_capstone" != "xno"])
|
||||||
|
|
||||||
AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
|
AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"])
|
||||||
|
|
|
@ -226,6 +226,8 @@ ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1002", MODE="660", GROUP="plugdev",
|
||||||
|
|
||||||
# ANGIE USB-JTAG Adapter
|
# ANGIE USB-JTAG Adapter
|
||||||
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="424e", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
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"
|
ATTRS{idVendor}=="584e", ATTRS{idProduct}=="4a55", MODE="660", GROUP="plugdev", TAG+="uaccess"
|
||||||
|
|
||||||
# Marvell Sheevaplug
|
# Marvell Sheevaplug
|
||||||
|
|
|
@ -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
|
--xram-size $(XRAM_SIZE) --iram-size 256 --model-small
|
||||||
|
|
||||||
# list of base object files
|
# 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 \
|
HEADERS = $(INCLUDE_DIR)/usb.h \
|
||||||
$(INCLUDE_DIR)/protocol.h \
|
$(INCLUDE_DIR)/protocol.h \
|
||||||
$(INCLUDE_DIR)/jtag.h \
|
$(INCLUDE_DIR)/jtag.h \
|
||||||
|
@ -47,7 +47,8 @@ HEADERS = $(INCLUDE_DIR)/usb.h \
|
||||||
$(INCLUDE_DIR)/io.h \
|
$(INCLUDE_DIR)/io.h \
|
||||||
$(INCLUDE_DIR)/serial.h \
|
$(INCLUDE_DIR)/serial.h \
|
||||||
$(INCLUDE_DIR)/fx2macros.h \
|
$(INCLUDE_DIR)/fx2macros.h \
|
||||||
$(INCLUDE_DIR)/msgtypes.h
|
$(INCLUDE_DIR)/msgtypes.h \
|
||||||
|
$(INCLUDE_DIR)/i2c.h
|
||||||
|
|
||||||
# Disable all built-in rules.
|
# Disable all built-in rules.
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
@ -61,7 +62,7 @@ all: angie_firmware.ihx
|
||||||
angie_firmware.ihx: $(OBJECTS)
|
angie_firmware.ihx: $(OBJECTS)
|
||||||
$(CC) -mmcs51 $(LDFLAGS) -o $@ $^
|
$(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)
|
%.rel: $(SRC_DIR)/%.c $(HEADERS)
|
||||||
$(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
|
$(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
|
||||||
|
|
||||||
|
|
|
@ -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
|
distributions include SDCC in their official package repositories. The SDCC
|
||||||
source code can be found at http://sdcc.sourceforge.net/
|
source code can be found at http://sdcc.sourceforge.net/
|
||||||
|
|
||||||
Simply type "make hex" in the ANGIE directory to compile the firmware.
|
Simply type "make bin" in the ANGIE directory to compile the firmware.
|
||||||
"make clean" will remove all generated files except the Intel HEX file
|
"make clean" will remove all generated files except the BIN file
|
||||||
required for downloading the firmware to ANGIE.
|
required for downloading the firmware to ANGIE.
|
||||||
|
|
||||||
Note that the EZ-USB FX2 microcontroller does not have on-chip flash,
|
Note that the EZ-USB FX2 microcontroller does not have on-chip flash,
|
||||||
|
|
|
@ -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. *
|
||||||
|
<aboudjelida@nanoxplore.com> *
|
||||||
|
<ahmederrachedbjld@gmail.com> *
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __I2C_H
|
||||||
|
#define __I2C_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
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
|
|
@ -45,14 +45,14 @@
|
||||||
#define PIN_TDI IOB3
|
#define PIN_TDI IOB3
|
||||||
#define PIN_TDO IOB4
|
#define PIN_TDO IOB4
|
||||||
#define PIN_SRST IOB5
|
#define PIN_SRST IOB5
|
||||||
/* PA6 Not Connected */
|
/* PB6 Not Connected */
|
||||||
/* PA7 Not Connected */
|
/* PB7 Not Connected */
|
||||||
|
|
||||||
/* JTAG Signals with direction 'OUT' on port B */
|
/* JTAG Signals with direction 'OUT' on port B */
|
||||||
/* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */
|
/* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */
|
||||||
#define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5)
|
#define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5)
|
||||||
|
|
||||||
/* PORT C */ // Debug:
|
/* PORT C */
|
||||||
#define PIN_T0 IOC0
|
#define PIN_T0 IOC0
|
||||||
#define PIN_T1 IOC1
|
#define PIN_T1 IOC1
|
||||||
#define PIN_T2 IOC2
|
#define PIN_T2 IOC2
|
||||||
|
@ -62,4 +62,14 @@
|
||||||
/* PC6 Not Connected */
|
/* PC6 Not Connected */
|
||||||
/* PC7 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
|
#endif
|
||||||
|
|
|
@ -24,18 +24,19 @@
|
||||||
#define STALL_EP0() (EP0CS |= EPSTALL)
|
#define STALL_EP0() (EP0CS |= EPSTALL)
|
||||||
#define CLEAR_IRQ() (USBINT = 0)
|
#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 */
|
/* USB Descriptor Types. See USB 2.0 Spec */
|
||||||
#define DESCRIPTOR_TYPE_DEVICE 0x01
|
#define DESCRIPTOR_TYPE_DEVICE 0x01
|
||||||
#define DESCRIPTOR_TYPE_CONFIGURATION 0x02
|
#define DESCRIPTOR_TYPE_CONFIGURATION 0x02
|
||||||
#define DESCRIPTOR_TYPE_STRING 0x03
|
#define DESCRIPTOR_TYPE_STRING 0x03
|
||||||
#define DESCRIPTOR_TYPE_INTERFACE 0x04
|
#define DESCRIPTOR_TYPE_INTERFACE 0x04
|
||||||
#define DESCRIPTOR_TYPE_ENDPOINT 0x05
|
#define DESCRIPTOR_TYPE_ENDPOINT 0x05
|
||||||
|
#define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0B
|
||||||
|
|
||||||
#define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
|
#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 {
|
struct usb_device_descriptor {
|
||||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||||
uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */
|
uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */
|
||||||
|
@ -53,7 +54,7 @@ struct usb_device_descriptor {
|
||||||
uint8_t bnumconfigurations; /**< Number of possible configurations. */
|
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 {
|
struct usb_config_descriptor {
|
||||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||||
uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */
|
uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */
|
||||||
|
@ -65,7 +66,19 @@ struct usb_config_descriptor {
|
||||||
uint8_t maxpower; /**< Maximum power consumption in 2 mA units. */
|
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 {
|
struct usb_interface_descriptor {
|
||||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||||
uint8_t bdescriptortype; /**< INTERFACE descriptor type. */
|
uint8_t bdescriptortype; /**< INTERFACE descriptor type. */
|
||||||
|
@ -78,7 +91,7 @@ struct usb_interface_descriptor {
|
||||||
uint8_t iinterface; /**< Index of interface string 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 {
|
struct usb_endpoint_descriptor {
|
||||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||||
uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */
|
uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */
|
||||||
|
@ -88,14 +101,14 @@ struct usb_endpoint_descriptor {
|
||||||
uint8_t binterval; /**< Polling interval (in ms) for this endpoint. */
|
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 {
|
struct usb_language_descriptor {
|
||||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||||
uint8_t bdescriptortype; /**< STRING descriptor type. */
|
uint8_t bdescriptortype; /**< STRING descriptor type. */
|
||||||
uint16_t wlangid[]; /**< LANGID codes. */
|
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 {
|
struct usb_string_descriptor {
|
||||||
uint8_t blength; /**< Size of this descriptor in bytes. */
|
uint8_t blength; /**< Size of this descriptor in bytes. */
|
||||||
uint8_t bdescriptortype; /**< STRING descriptor type. */
|
uint8_t bdescriptortype; /**< STRING descriptor type. */
|
||||||
|
@ -104,7 +117,7 @@ struct usb_string_descriptor {
|
||||||
|
|
||||||
/********************** USB Control Endpoint 0 related *********************/
|
/********************** 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 {
|
struct setup_data {
|
||||||
uint8_t bmrequesttype; /**< Characteristics of a request. */
|
uint8_t bmrequesttype; /**< Characteristics of a request. */
|
||||||
uint8_t brequest; /**< Specific 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;
|
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
|
* Bit 7: Data transfer direction
|
||||||
* 0 = Host-to-device
|
* 0 = Host-to-device
|
||||||
* 1 = Device-to-host
|
* 1 = Device-to-host
|
||||||
* Bit 6...5: Type
|
* Bit 6...5: Type
|
||||||
* 0 = Standard
|
* 0 = Standard
|
||||||
* 1 = Class
|
* 1 = Class
|
||||||
* 2 = Vendor
|
* 2 = Vendor
|
||||||
* 3 = Reserved
|
* 3 = Reserved
|
||||||
* Bit 4...0: Recipient
|
* Bit 4...0: Recipient
|
||||||
* 0 = Device
|
* 0 = Device
|
||||||
* 1 = Interface
|
* 1 = Interface
|
||||||
* 2 = Endpoint
|
* 2 = Endpoint
|
||||||
* 3 = Other
|
* 3 = Other
|
||||||
* 4...31 = Reserved
|
* 4...31 = Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USB_DIR_OUT 0x00
|
#define USB_DIR_OUT 0x00
|
||||||
#define USB_DIR_IN 0x80
|
#define USB_DIR_IN 0x80
|
||||||
|
|
||||||
#define USB_REQ_TYPE_STANDARD (0x00 << 5)
|
#define USB_REQ_TYPE_STANDARD (0x00 << 5)
|
||||||
#define USB_REQ_TYPE_CLASS (0x01 << 5)
|
#define USB_REQ_TYPE_CLASS (0x01 << 5)
|
||||||
#define USB_REQ_TYPE_VENDOR (0x02 << 5)
|
#define USB_REQ_TYPE_VENDOR (0x02 << 5)
|
||||||
#define USB_REQ_TYPE_RESERVED (0x03 << 5)
|
#define USB_REQ_TYPE_RESERVED (0x03 << 5)
|
||||||
|
|
||||||
#define USB_RECIP_DEVICE 0x00
|
#define USB_RECIP_DEVICE 0x00
|
||||||
#define USB_RECIP_INTERFACE 0x01
|
#define USB_RECIP_INTERFACE 0x01
|
||||||
#define USB_RECIP_ENDPOINT 0x02
|
#define USB_RECIP_ENDPOINT 0x02
|
||||||
#define USB_RECIP_OTHER 0x03
|
#define USB_RECIP_OTHER 0x03
|
||||||
|
|
||||||
/* Clear Interface Request */
|
/* 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_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||||
#define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
#define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
||||||
|
|
||||||
/* Get Configuration Request */
|
/* 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 */
|
/* 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 */
|
/* Get Interface Request */
|
||||||
#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||||
|
|
||||||
/* Get Status Request: See USB 1.1 spec, page 190 */
|
/* 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_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||||
#define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
#define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
||||||
|
|
||||||
/* Set Address Request is handled by EZ-USB core */
|
/* Set Address Request is handled by EZ-USB core */
|
||||||
|
|
||||||
/* Set Configuration Request */
|
/* 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 */
|
/* 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 */
|
/* 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_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
|
||||||
#define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
#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 */
|
/* Synch Frame Request */
|
||||||
#define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
|
#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 */
|
/* USB Requests (bRequest): See USB 2.0 Spec */
|
||||||
#define GET_STATUS 0
|
#define GET_STATUS 0
|
||||||
#define CLEAR_FEATURE 1
|
#define CLEAR_FEATURE 1
|
||||||
/* Value '2' is reserved for future use */
|
/* Value '2' is reserved for future use */
|
||||||
#define SET_FEATURE 3
|
#define SET_FEATURE 3
|
||||||
/* Value '4' is reserved for future use */
|
/* Value '4' is reserved for future use */
|
||||||
#define SET_ADDRESS 5
|
#define SET_ADDRESS 5
|
||||||
#define GET_DESCRIPTOR 6
|
#define GET_DESCRIPTOR 6
|
||||||
#define SET_DESCRIPTOR 7
|
#define SET_DESCRIPTOR 7
|
||||||
#define GET_CONFIGURATION 8
|
#define GET_CONFIGURATION 8
|
||||||
#define SET_CONFIGURATION 9
|
#define SET_CONFIGURATION 9
|
||||||
#define GET_INTERFACE 10
|
#define GET_INTERFACE 10
|
||||||
#define SET_INTERFACE 11
|
#define SET_INTERFACE 11
|
||||||
#define SYNCH_FRAME 12
|
#define SYNCH_FRAME 12
|
||||||
|
|
||||||
/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
|
/* Standard Feature Selectors: See USB 2.0 Spec */
|
||||||
#define DEVICE_REMOTE_WAKEUP 1
|
#define DEVICE_REMOTE_WAKEUP 1
|
||||||
#define ENDPOINT_HALT 0
|
#define ENDPOINT_HALT 0
|
||||||
|
|
||||||
/************************** EZ-USB specific stuff **************************/
|
/************************** 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 {
|
enum usb_isr {
|
||||||
SUDAV_ISR = 13,
|
SUDAV_ISR = 13,
|
||||||
SOF_ISR,
|
SOF_ISR,
|
||||||
|
@ -265,7 +278,10 @@ bool usb_handle_set_feature(void);
|
||||||
bool usb_handle_get_descriptor(void);
|
bool usb_handle_get_descriptor(void);
|
||||||
void usb_handle_set_interface(void);
|
void usb_handle_set_interface(void);
|
||||||
void usb_handle_setup_data(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 ep_init(void);
|
||||||
void interrupt_init(void);
|
void interrupt_init(void);
|
||||||
void io_init(void);
|
void io_init(void);
|
||||||
|
|
|
@ -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. *
|
||||||
|
<aboudjelida@nanoxplore.com> *
|
||||||
|
<ahmederrachedbjld@gmail.com> *
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -139,15 +139,12 @@ bool execute_command(void)
|
||||||
payload_index_in += usb_in_bytecount;
|
payload_index_in += usb_in_bytecount;
|
||||||
|
|
||||||
/* Determine if this was the last command */
|
/* 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;
|
return true;
|
||||||
/* Line between return and else required by checkpatch: */
|
|
||||||
uint8_t a = 0;
|
/* Not the last command, update cmd_id_index */
|
||||||
} else {
|
cmd_id_index += (usb_out_bytecount + 1);
|
||||||
/* Not the last command, update cmd_id_index */
|
return false;
|
||||||
cmd_id_index += (usb_out_bytecount + 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <fx2macros.h>
|
#include <fx2macros.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "i2c.h"
|
||||||
|
|
||||||
/* Also update external declarations in "include/usb.h" if making changes to
|
/* Also update external declarations in "include/usb.h" if making changes to
|
||||||
* these variables!
|
* these variables!
|
||||||
|
@ -36,9 +37,9 @@ __code struct usb_device_descriptor device_descriptor = {
|
||||||
.blength = sizeof(struct usb_device_descriptor),
|
.blength = sizeof(struct usb_device_descriptor),
|
||||||
.bdescriptortype = DESCRIPTOR_TYPE_DEVICE,
|
.bdescriptortype = DESCRIPTOR_TYPE_DEVICE,
|
||||||
.bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
|
.bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
|
||||||
.bdeviceclass = 0xFF, /* 0xFF = vendor-specific */
|
.bdeviceclass = 0xEF,
|
||||||
.bdevicesubclass = 0xFF,
|
.bdevicesubclass = 0x02,
|
||||||
.bdeviceprotocol = 0xFF,
|
.bdeviceprotocol = 0x01,
|
||||||
.bmaxpacketsize0 = 64,
|
.bmaxpacketsize0 = 64,
|
||||||
.idvendor = 0x584e,
|
.idvendor = 0x584e,
|
||||||
.idproduct = 0x424e,
|
.idproduct = 0x424e,
|
||||||
|
@ -55,25 +56,36 @@ __code struct usb_config_descriptor config_descriptor = {
|
||||||
.blength = sizeof(struct usb_config_descriptor),
|
.blength = sizeof(struct usb_config_descriptor),
|
||||||
.bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION,
|
.bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION,
|
||||||
.wtotallength = sizeof(struct usb_config_descriptor) +
|
.wtotallength = sizeof(struct usb_config_descriptor) +
|
||||||
sizeof(struct usb_interface_descriptor) +
|
3 * sizeof(struct usb_interface_descriptor) +
|
||||||
(NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
|
((NUM_ENDPOINTS + 2) * sizeof(struct usb_endpoint_descriptor)),
|
||||||
.bnuminterfaces = 1,
|
.bnuminterfaces = 2,
|
||||||
.bconfigurationvalue = 1,
|
.bconfigurationvalue = 1,
|
||||||
.iconfiguration = 4, /* String describing this configuration */
|
.iconfiguration = 1, /* String describing this configuration */
|
||||||
.bmattributes = 0x80, /* Only MSB set according to USB spec */
|
.bmattributes = 0x80, /* Only MSB set according to USB spec */
|
||||||
.maxpower = 50 /* 100 mA */
|
.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 = {
|
__code struct usb_interface_descriptor interface_descriptor00 = {
|
||||||
.blength = sizeof(struct usb_interface_descriptor),
|
.blength = sizeof(struct usb_interface_descriptor),
|
||||||
.bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
|
.bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
|
||||||
.binterfacenumber = 0,
|
.binterfacenumber = 0,
|
||||||
.balternatesetting = 0,
|
.balternatesetting = 0,
|
||||||
.bnumendpoints = NUM_ENDPOINTS,
|
.bnumendpoints = NUM_ENDPOINTS,
|
||||||
.binterfaceclass = 0xFF,
|
.binterfaceclass = 0XFF,
|
||||||
.binterfacesubclass = 0xFF,
|
.binterfacesubclass = 0x00,
|
||||||
.binterfaceprotocol = 0xFF,
|
.binterfaceprotocol = 0x00,
|
||||||
.iinterface = 0
|
.iinterface = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
__code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = {
|
__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
|
.binterval = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = {
|
__code struct usb_interface_descriptor interface_descriptor01 = {
|
||||||
.blength = sizeof(struct usb_endpoint_descriptor),
|
.blength = sizeof(struct usb_interface_descriptor),
|
||||||
.bdescriptortype = 0x05,
|
.bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
|
||||||
.bendpointaddress = (4 | USB_DIR_IN),
|
.binterfacenumber = 1,
|
||||||
.bmattributes = 0x02,
|
.balternatesetting = 0,
|
||||||
.wmaxpacketsize = 512,
|
.bnumendpoints = 2,
|
||||||
.binterval = 0
|
.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),
|
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||||
.bdescriptortype = 0x05,
|
.bdescriptortype = 0x05,
|
||||||
.bendpointaddress = (6 | USB_DIR_OUT),
|
.bendpointaddress = (6 | USB_DIR_OUT),
|
||||||
|
@ -121,19 +136,18 @@ __code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = {
|
||||||
.binterval = 0
|
.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),
|
.blength = sizeof(struct usb_endpoint_descriptor),
|
||||||
.bdescriptortype = 0x05,
|
.bdescriptortype = 0x05,
|
||||||
.bendpointaddress = (8 | USB_DIR_OUT),
|
.bendpointaddress = (8 | USB_DIR_IN),
|
||||||
.bmattributes = 0x02,
|
.bmattributes = 0x02,
|
||||||
.wmaxpacketsize = 512,
|
.wmaxpacketsize = 512,
|
||||||
.binterval = 0
|
.binterval = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
__code struct usb_language_descriptor language_descriptor = {
|
__code struct usb_language_descriptor language_descriptor = {
|
||||||
.blength = 4,
|
.blength = 4,
|
||||||
.bdescriptortype = DESCRIPTOR_TYPE_STRING,
|
.bdescriptortype = DESCRIPTOR_TYPE_STRING,
|
||||||
.wlangid = {0x0409 /* US English */}
|
.wlangid = {0x0409} /* US English */
|
||||||
};
|
};
|
||||||
|
|
||||||
__code struct usb_string_descriptor strmanufacturer =
|
__code struct usb_string_descriptor strmanufacturer =
|
||||||
|
@ -212,9 +226,15 @@ void ep4_isr(void)__interrupt EP4_ISR
|
||||||
}
|
}
|
||||||
void ep6_isr(void)__interrupt EP6_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
|
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
|
void ibn_isr(void)__interrupt IBN_ISR
|
||||||
{
|
{
|
||||||
|
@ -411,21 +431,21 @@ bool usb_handle_clear_feature(void)
|
||||||
switch (setup_data.bmrequesttype) {
|
switch (setup_data.bmrequesttype) {
|
||||||
case CF_DEVICE:
|
case CF_DEVICE:
|
||||||
/* Clear remote wakeup not supported: stall EP0 */
|
/* Clear remote wakeup not supported: stall EP0 */
|
||||||
STALL_EP0();
|
STALL_EP0();
|
||||||
break;
|
break;
|
||||||
case CF_ENDPOINT:
|
case CF_ENDPOINT:
|
||||||
if (setup_data.wvalue == 0) {
|
if (setup_data.wvalue == 0) {
|
||||||
/* Unstall the endpoint specified in wIndex */
|
/* Unstall the endpoint specified in wIndex */
|
||||||
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
|
ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
|
||||||
if (!ep_cs)
|
if (!ep_cs)
|
||||||
return false;
|
return false;
|
||||||
*ep_cs &= ~EPSTALL;
|
*ep_cs &= ~EPSTALL;
|
||||||
} else {
|
} else {
|
||||||
/* Unsupported feature, stall EP0 */
|
/* Unsupported feature, stall EP0 */
|
||||||
STALL_EP0();
|
STALL_EP0();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Vendor commands... */
|
/* Vendor commands... */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -597,7 +617,6 @@ bool usb_handle_send_bitstream(void)
|
||||||
/* wait until GPIF transaction has been completed */
|
/* wait until GPIF transaction has been completed */
|
||||||
while ((GPIFTRIG & BMGPIFDONE) == 0) {
|
while ((GPIFTRIG & BMGPIFDONE) == 0) {
|
||||||
if (ix-- == 0) {
|
if (ix-- == 0) {
|
||||||
printf("GPIF done time out\n");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
delay_ms(1);
|
delay_ms(1);
|
||||||
|
@ -697,9 +716,9 @@ void ep_init(void)
|
||||||
syncdelay(3);
|
syncdelay(3);
|
||||||
EP4CFG = 0x00;
|
EP4CFG = 0x00;
|
||||||
syncdelay(3);
|
syncdelay(3);
|
||||||
EP6CFG = 0x00;
|
EP6CFG = 0xA2;
|
||||||
syncdelay(3);
|
syncdelay(3);
|
||||||
EP8CFG = 0x00;
|
EP8CFG = 0xE2;
|
||||||
syncdelay(3);
|
syncdelay(3);
|
||||||
|
|
||||||
/* arm EP1-OUT */
|
/* arm EP1-OUT */
|
||||||
|
@ -714,6 +733,12 @@ void ep_init(void)
|
||||||
EP1INBC = 0;
|
EP1INBC = 0;
|
||||||
syncdelay(3);
|
syncdelay(3);
|
||||||
|
|
||||||
|
/* arm EP6-OUT */
|
||||||
|
EP6BCL = 0x80;
|
||||||
|
syncdelay(3);
|
||||||
|
EP6BCL = 0x80;
|
||||||
|
syncdelay(3);
|
||||||
|
|
||||||
/* Standard procedure to reset FIFOs */
|
/* Standard procedure to reset FIFOs */
|
||||||
FIFORESET = BMNAKALL; /* NAK all transfers during the reset */
|
FIFORESET = BMNAKALL; /* NAK all transfers during the reset */
|
||||||
syncdelay(3);
|
syncdelay(3);
|
||||||
|
@ -727,9 +752,110 @@ void ep_init(void)
|
||||||
syncdelay(3);
|
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.
|
* Interrupt initialization. Configures USB interrupts.
|
||||||
*/
|
**/
|
||||||
void interrupt_init(void)
|
void interrupt_init(void)
|
||||||
{
|
{
|
||||||
/* Enable Interrupts */
|
/* Enable Interrupts */
|
||||||
|
@ -742,11 +868,11 @@ void interrupt_init(void)
|
||||||
/* Enable INT 2 & 4 Autovectoring */
|
/* Enable INT 2 & 4 Autovectoring */
|
||||||
INTSETUP |= (AV2EN | AV4EN);
|
INTSETUP |= (AV2EN | AV4EN);
|
||||||
|
|
||||||
/* Enable individual EP1OUT&IN interrupts */
|
/* Enable individual EP1OUT&IN & EP6&8 interrupts */
|
||||||
EPIE |= 0x0C;
|
EPIE |= 0xCC;
|
||||||
|
|
||||||
/* Clear individual USB interrupt IRQ */
|
/* Clear individual USB interrupt IRQ */
|
||||||
EPIRQ = 0x0C;
|
EPIRQ = 0xCC;
|
||||||
|
|
||||||
/* Enable SUDAV interrupt */
|
/* Enable SUDAV interrupt */
|
||||||
USBIEN |= SUDAVI;
|
USBIEN |= SUDAVI;
|
||||||
|
@ -777,8 +903,15 @@ void io_init(void)
|
||||||
PIN_TDI = 0;
|
PIN_TDI = 0;
|
||||||
PIN_SRST = 1;
|
PIN_SRST = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* PORT C */
|
/* PORT C */
|
||||||
PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */
|
PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */
|
||||||
OEC = 0xEF;
|
OEC = 0xFF;
|
||||||
IOC = 0xFF;
|
IOC = 0xFF;
|
||||||
|
|
||||||
|
/* PORT D */
|
||||||
|
OED = 0xFF;
|
||||||
|
IOD = 0xFF;
|
||||||
|
PIN_SDA_DIR = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
|
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
|
||||||
|
|
||||||
# Needed by timing test
|
# Needed by timing test
|
||||||
export PROJECT := angie_openocd
|
export PROJECT := angie_bitstream
|
||||||
TARGET_PART := xc6slx9-2tqg144
|
TARGET_PART := xc6slx9-2tqg144
|
||||||
export TOPLEVEL := S609
|
export TOPLEVEL := S609
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,31 @@ net TRST LOC = 'P48' ;
|
||||||
net TMS LOC = 'P43' ;
|
net TMS LOC = 'P43' ;
|
||||||
net TCK LOC = 'P44' ;
|
net TCK LOC = 'P44' ;
|
||||||
net TDI LOC = 'P45' ;
|
net TDI LOC = 'P45' ;
|
||||||
net TDO LOC = 'P46' ;
|
net TDO LOC = 'P46' ;
|
||||||
net SRST LOC = 'P61' ;
|
net SRST LOC = 'P61' ;
|
||||||
|
|
||||||
|
net SDA LOC = 'P50' ;
|
||||||
|
net SCL LOC = 'P51' ;
|
||||||
|
net SDA_DIR LOC = 'P56' ;
|
||||||
|
|
||||||
net SI_TDO LOC = 'P16' ;
|
net SI_TDO LOC = 'P16' ;
|
||||||
net SO_TRST LOC = 'P32' ;
|
net SO_TRST LOC = 'P32' ;
|
||||||
net SO_TMS LOC = 'P27' ;
|
net SO_TMS LOC = 'P27' ;
|
||||||
net SO_TCK LOC = 'P30' ;
|
net SO_TCK LOC = 'P30' ;
|
||||||
net SO_TDI LOC = 'P26' ;
|
net SO_TDI LOC = 'P26' ;
|
||||||
net SO_SRST LOC = 'P12' ;
|
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_0 LOC = 'P29' ;
|
||||||
net ST_1 LOC = 'P21' ;
|
net ST_1 LOC = 'P21' ;
|
||||||
net ST_2 LOC = 'P11' ;
|
net ST_2 LOC = 'P11' ;
|
||||||
|
|
||||||
|
net ST_4 LOC = 'P134' ;
|
||||||
|
net ST_5 LOC = 'P139' ;
|
||||||
|
|
||||||
net FTP<0> LOC = 'P121' ;
|
net FTP<0> LOC = 'P121' ;
|
||||||
net FTP<1> LOC = 'P120' ;
|
net FTP<1> LOC = 'P120' ;
|
||||||
net FTP<2> LOC = 'P119' ;
|
net FTP<2> LOC = 'P119' ;
|
|
@ -16,22 +16,35 @@ library UNISIM;
|
||||||
use UNISIM.VComponents.all;
|
use UNISIM.VComponents.all;
|
||||||
|
|
||||||
entity S609 is port(
|
entity S609 is port(
|
||||||
TRST : in std_logic;
|
TRST : in std_logic;
|
||||||
TMS : in std_logic;
|
TMS : in std_logic;
|
||||||
TCK : in std_logic;
|
TCK : in std_logic;
|
||||||
TDI : in std_logic;
|
TDI : in std_logic;
|
||||||
TDO : out std_logic;
|
TDO : out std_logic;
|
||||||
SRST : in std_logic;
|
SRST : in std_logic;
|
||||||
FTP : out std_logic_vector(7 downto 0); -- Test points
|
|
||||||
|
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;
|
SI_TDO : in std_logic;
|
||||||
ST_0 : out std_logic;
|
ST_0 : out std_logic;
|
||||||
ST_1 : out std_logic;
|
ST_1 : out std_logic;
|
||||||
ST_2 : 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_TRST : out std_logic;
|
||||||
SO_TMS : out std_logic;
|
SO_TMS : out std_logic;
|
||||||
SO_TCK : out std_logic;
|
SO_TCK : out std_logic;
|
||||||
SO_TDI : out std_logic;
|
SO_TDI : out std_logic;
|
||||||
SO_SRST :out std_logic
|
SO_SRST : out std_logic
|
||||||
);
|
);
|
||||||
end S609;
|
end S609;
|
||||||
|
|
||||||
|
@ -42,6 +55,8 @@ begin
|
||||||
ST_0 <= '0';
|
ST_0 <= '0';
|
||||||
ST_1 <= '1';
|
ST_1 <= '1';
|
||||||
|
|
||||||
|
ST_4 <= '0';
|
||||||
|
|
||||||
--TDO:
|
--TDO:
|
||||||
TDO <= not SI_TDO;
|
TDO <= not SI_TDO;
|
||||||
|
|
||||||
|
@ -53,11 +68,26 @@ SO_TDI <= TDI;
|
||||||
ST_2 <= SRST;
|
ST_2 <= SRST;
|
||||||
SO_SRST <= '0';
|
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:
|
--Points de test:
|
||||||
FTP(0) <= TRST;
|
FTP(0) <= SDA;
|
||||||
FTP(1) <= TMS;
|
FTP(1) <= SCL;
|
||||||
FTP(2) <= TCK;
|
FTP(2) <= not(SO_SDA_IN);
|
||||||
FTP(3) <= TDI;
|
FTP(3) <= SDA_DIR;
|
||||||
FTP(5) <= SRST;
|
FTP(5) <= SRST;
|
||||||
FTP(4) <= SI_TDO;
|
FTP(4) <= SI_TDO;
|
||||||
FTP(6) <= '1';
|
FTP(6) <= '1';
|
|
@ -1,60 +1,70 @@
|
||||||
/* Autogenerated with ../../../../src/helper/bin2char.sh */
|
/* Autogenerated with ../../../../src/helper/bin2char.sh */
|
||||||
0x08,0xb5,0xdf,0xf8,0x08,0xd0,0x00,0xf0,0x2f,0xf9,0x00,0x00,0x48,0x15,0x0c,0x20,
|
0x08,0xb5,0xdf,0xf8,0x08,0xd0,0x00,0xf0,0x95,0xf9,0x00,0x00,0xec,0x15,0x0c,0x20,
|
||||||
0x03,0x4b,0x18,0x70,0x19,0x72,0x08,0x33,0x1a,0x78,0xd2,0x09,0xfc,0xd1,0x70,0x47,
|
0x03,0x4b,0x18,0x70,0x08,0x33,0x19,0x70,0x1a,0x78,0xd2,0x09,0xfc,0xd1,0x70,0x47,
|
||||||
0x16,0x00,0x02,0x40,0x70,0xb5,0x11,0x4c,0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70,
|
0x16,0x00,0x02,0x40,0x13,0x4b,0x14,0x49,0x1a,0x68,0xea,0xb1,0x1a,0x68,0x01,0x2a,
|
||||||
0xc0,0x21,0x05,0x20,0xff,0xf7,0xec,0xff,0x0d,0x4a,0x0e,0x49,0x6f,0xf0,0x7f,0x43,
|
0x1e,0xd0,0x1b,0x68,0x02,0x2b,0x1b,0xd1,0x10,0x4b,0x1a,0x78,0x50,0xb1,0x02,0xf0,
|
||||||
0x6f,0xf0,0x2e,0x05,0x10,0x46,0x15,0x70,0x06,0x78,0xf6,0x09,0xfc,0xd1,0x0e,0x78,
|
0xf7,0x02,0x1a,0x70,0x01,0x22,0x08,0x78,0x01,0x23,0x93,0x40,0x03,0x43,0xdb,0xb2,
|
||||||
0xf6,0x07,0x01,0xd5,0x01,0x3b,0xf6,0xd1,0x22,0x78,0x42,0xf0,0x02,0x02,0x00,0x2b,
|
0x0b,0x70,0x70,0x47,0x42,0xf0,0x08,0x02,0x1a,0x70,0x01,0x22,0x08,0x78,0x01,0x23,
|
||||||
0x22,0x70,0x0c,0xbf,0x03,0x20,0x00,0x20,0x70,0xbd,0x00,0xbf,0x1f,0x00,0x02,0x40,
|
0x93,0x40,0x20,0xea,0x03,0x03,0xf3,0xe7,0x01,0x22,0x00,0x28,0xf6,0xd0,0xea,0xe7,
|
||||||
|
0x00,0x22,0xfa,0xe7,0x00,0x00,0x0c,0x20,0x1f,0x00,0x02,0x40,0x43,0x00,0x02,0x40,
|
||||||
|
0x73,0xb5,0x04,0x46,0x00,0x20,0x15,0x46,0x0e,0x46,0xff,0xf7,0xcb,0xff,0x0f,0x4b,
|
||||||
|
0x01,0x94,0xc4,0xf3,0x07,0x44,0x1c,0x70,0x9d,0xf8,0x05,0x20,0x5a,0x70,0x9d,0xf8,
|
||||||
|
0x04,0x20,0x9a,0x70,0xf3,0x21,0x02,0x20,0xff,0xf7,0xb2,0xff,0x2c,0x46,0x63,0x1b,
|
||||||
|
0xb3,0x42,0x05,0xd3,0x01,0x20,0x02,0xb0,0xbd,0xe8,0x70,0x40,0xff,0xf7,0xb2,0xbf,
|
||||||
|
0xe0,0x21,0x14,0xf8,0x01,0x0b,0xff,0xf7,0xa3,0xff,0xf0,0xe7,0x1a,0x00,0x02,0x40,
|
||||||
|
0x08,0x4b,0x1b,0x68,0x02,0x2b,0x08,0x4b,0x07,0xd1,0x08,0x4a,0x80,0x21,0x11,0x70,
|
||||||
|
0xc0,0x22,0x1a,0x70,0x00,0x22,0x1a,0x71,0x70,0x47,0x1a,0x78,0x42,0xf0,0x80,0x02,
|
||||||
|
0x1a,0x70,0x70,0x47,0x00,0x00,0x0c,0x20,0x10,0x30,0x0c,0x40,0x00,0x30,0x0c,0x40,
|
||||||
|
0x38,0xb5,0x00,0x20,0xff,0xf7,0x8e,0xff,0xc0,0x21,0x05,0x20,0xff,0xf7,0x80,0xff,
|
||||||
|
0x0b,0x4b,0x0c,0x4a,0x6f,0xf0,0x7f,0x44,0x6f,0xf0,0x2e,0x00,0x19,0x46,0x18,0x70,
|
||||||
|
0x0d,0x78,0xed,0x09,0xfc,0xd1,0x15,0x78,0xed,0x07,0x01,0xd5,0x01,0x3c,0xf6,0xd1,
|
||||||
|
0x01,0x20,0xff,0xf7,0x77,0xff,0x00,0x2c,0x0c,0xbf,0x03,0x20,0x00,0x20,0x38,0xbd,
|
||||||
0x1e,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x08,0xb5,0xc0,0x21,0x06,0x20,0xff,0xf7,
|
0x1e,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x08,0xb5,0xc0,0x21,0x06,0x20,0xff,0xf7,
|
||||||
0xc7,0xff,0xff,0xf7,0xcf,0xff,0x28,0xb9,0x03,0x4b,0x1b,0x78,0x13,0xf0,0x02,0x0f,
|
0x5f,0xff,0xff,0xf7,0xd5,0xff,0x28,0xb9,0x03,0x4b,0x1b,0x78,0x13,0xf0,0x02,0x0f,
|
||||||
0x08,0xbf,0x02,0x20,0x08,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,0xf8,0xb5,0x12,0x4c,
|
0x08,0xbf,0x02,0x20,0x08,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,0x70,0x47,0x00,0x00,
|
||||||
0x23,0x78,0x03,0xf0,0xfd,0x03,0x23,0x70,0x10,0x4b,0x17,0x46,0xc0,0xf3,0x07,0x42,
|
0x38,0xb5,0x17,0x4c,0xc1,0x21,0x05,0x20,0xff,0xf7,0x4a,0xff,0x25,0x78,0xc1,0x21,
|
||||||
0x1a,0x70,0xc0,0xf3,0x07,0x22,0xc0,0xb2,0x03,0xf8,0x01,0x2c,0x0e,0x46,0x03,0xf8,
|
0x35,0x20,0xff,0xf7,0x45,0xff,0x23,0x78,0xed,0xb2,0xdb,0xb2,0x05,0xb9,0xd3,0xb1,
|
||||||
0x02,0x0c,0xe8,0x21,0x02,0x20,0xff,0xf7,0xa3,0xff,0x00,0x25,0xae,0x42,0x04,0xd8,
|
0xff,0xf7,0xda,0xff,0xd0,0xb9,0x0f,0x4b,0x20,0x70,0xf2,0x21,0x18,0x70,0x01,0x20,
|
||||||
0x23,0x78,0x43,0xf0,0x02,0x03,0x23,0x70,0xf8,0xbd,0x78,0x5d,0xe0,0x21,0xff,0xf7,
|
0xff,0xf7,0x36,0xff,0xff,0xf7,0xac,0xff,0x80,0xb9,0xc1,0x21,0x05,0x20,0xff,0xf7,
|
||||||
0x97,0xff,0x01,0x35,0xf2,0xe7,0x00,0xbf,0x1f,0x00,0x02,0x40,0x19,0x00,0x02,0x40,
|
0x2f,0xff,0x25,0x78,0xc1,0x21,0x35,0x20,0xff,0xf7,0x2a,0xff,0x23,0x78,0xed,0xb2,
|
||||||
0x70,0x47,0x2d,0xe9,0xf0,0x41,0x00,0xf1,0xff,0x06,0x26,0xf0,0xff,0x06,0x34,0x1a,
|
0xdb,0xb2,0x15,0xb9,0x0b,0xb9,0x00,0x20,0x38,0xbd,0x02,0x20,0x38,0xbd,0x00,0xbf,
|
||||||
0x8c,0x42,0x28,0xbf,0x0c,0x46,0x80,0x46,0x0d,0x46,0x17,0x46,0x5c,0xb1,0xff,0xf7,
|
0x1a,0x00,0x02,0x40,0x1b,0x00,0x02,0x40,0x2d,0xe9,0xf8,0x43,0x81,0x46,0x0d,0x46,
|
||||||
0xb3,0xff,0x58,0xb9,0x3a,0x46,0xa1,0xb2,0x40,0x46,0xff,0xf7,0xbf,0xff,0xff,0xf7,
|
0x90,0x46,0xff,0xf7,0x75,0xff,0xff,0xf7,0xc3,0xff,0x06,0x46,0xb8,0xb9,0x09,0xf1,
|
||||||
0x81,0xff,0x18,0xb9,0x27,0x44,0x2c,0x1b,0x14,0xb9,0x20,0x46,0xbd,0xe8,0xf0,0x81,
|
0xff,0x07,0x27,0xf0,0xff,0x07,0xa7,0xeb,0x09,0x04,0xac,0x42,0x28,0xbf,0x2c,0x46,
|
||||||
0xb4,0xf5,0x80,0x7f,0x25,0x46,0x28,0xbf,0x4f,0xf4,0x80,0x75,0xff,0xf7,0x9c,0xff,
|
0x5c,0xb1,0xff,0xf7,0xa1,0xff,0x10,0xbb,0x42,0x46,0xa1,0xb2,0x48,0x46,0xff,0xf7,
|
||||||
0x00,0x28,0xf3,0xd1,0x3a,0x46,0xa9,0xb2,0x30,0x46,0xff,0xf7,0xa7,0xff,0xff,0xf7,
|
0x37,0xff,0xff,0xf7,0x75,0xff,0xd0,0xb9,0xa0,0x44,0x2c,0x1b,0x14,0xb9,0x30,0x46,
|
||||||
0x69,0xff,0x00,0x28,0xea,0xd1,0x2f,0x44,0x2e,0x44,0x64,0x1b,0xe4,0xe7,0x00,0x00,
|
0xbd,0xe8,0xf8,0x83,0xff,0xf7,0x90,0xff,0x88,0xb9,0xb4,0xf5,0x80,0x7f,0x25,0x46,
|
||||||
0x2d,0xe9,0xf0,0x47,0x14,0x4e,0x15,0x4f,0xdf,0xf8,0x54,0x80,0x05,0x46,0x0c,0x46,
|
0x28,0xbf,0x4f,0xf4,0x80,0x75,0x42,0x46,0xa9,0xb2,0x38,0x46,0xff,0xf7,0x20,0xff,
|
||||||
0x8a,0x46,0x05,0xeb,0x04,0x09,0xa9,0xeb,0x0a,0x09,0xba,0xf1,0x00,0x0f,0x02,0xd1,
|
0xff,0xf7,0x5e,0xff,0x18,0xb9,0xa8,0x44,0x2f,0x44,0x64,0x1b,0xe6,0xe7,0x06,0x46,
|
||||||
0x50,0x46,0xbd,0xe8,0xf0,0x87,0xff,0xf7,0x77,0xff,0x00,0x28,0xf9,0xd1,0xc9,0xf3,
|
0xe5,0xe7,0x00,0x00,0x2d,0xe9,0xf7,0x4f,0x06,0x46,0x0d,0x46,0xff,0xf7,0x38,0xff,
|
||||||
0x07,0x43,0x33,0x70,0xc9,0xf3,0x07,0x23,0x5f,0xfa,0x89,0xf9,0x3b,0x70,0xc8,0x21,
|
0xff,0xf7,0x86,0xff,0x82,0x46,0x58,0xb9,0x15,0x4f,0xdf,0xf8,0x58,0x80,0xdf,0xf8,
|
||||||
0x20,0x20,0x88,0xf8,0x00,0x90,0xff,0xf7,0x33,0xff,0xff,0xf7,0x3b,0xff,0x00,0x28,
|
0x58,0x90,0xab,0x46,0x74,0x19,0xa4,0xeb,0x0b,0x04,0xbb,0xf1,0x00,0x0f,0x03,0xd1,
|
||||||
0xe7,0xd1,0xaa,0xf5,0x80,0x5a,0xdc,0xe7,0x19,0x00,0x02,0x40,0x18,0x00,0x02,0x40,
|
0x50,0x46,0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0xff,0xf7,0x5e,0xff,0xa8,0xb9,0x01,0x94,
|
||||||
0x17,0x00,0x02,0x40,0x08,0xb5,0xff,0xf7,0x57,0xff,0x38,0xb9,0xc0,0x21,0xc7,0x20,
|
0xc4,0xf3,0x07,0x44,0x3c,0x70,0x9d,0xf8,0x05,0x30,0x88,0xf8,0x00,0x30,0x9d,0xf8,
|
||||||
0xff,0xf7,0x1e,0xff,0xbd,0xe8,0x08,0x40,0xff,0xf7,0x24,0xbf,0x08,0xbd,0x00,0x00,
|
0x04,0x30,0x89,0xf8,0x00,0x30,0xf3,0x21,0x20,0x20,0xff,0xf7,0xb1,0xfe,0xff,0xf7,
|
||||||
0x38,0xb5,0xff,0xf7,0x49,0xff,0x04,0x46,0xc0,0xb9,0x0d,0x4b,0x0d,0x4d,0xf2,0x21,
|
0x27,0xff,0x10,0xb9,0xab,0xf5,0x80,0x5b,0xdc,0xe7,0x82,0x46,0xe0,0xe7,0x00,0xbf,
|
||||||
0x28,0x70,0x18,0x70,0x01,0x20,0xff,0xf7,0x0b,0xff,0xff,0xf7,0x13,0xff,0x04,0x46,
|
0x1a,0x00,0x02,0x40,0x1b,0x00,0x02,0x40,0x1c,0x00,0x02,0x40,0x08,0xb5,0xff,0xf7,
|
||||||
0x60,0xb9,0xc1,0x21,0x05,0x20,0xff,0xf7,0x03,0xff,0x2b,0x78,0x2b,0xb9,0xc1,0x21,
|
0xff,0xfe,0xff,0xf7,0x4d,0xff,0x50,0xb9,0xff,0xf7,0x36,0xff,0x38,0xb9,0xc0,0x21,
|
||||||
0x35,0x20,0xff,0xf7,0xfd,0xfe,0x2b,0x78,0x03,0xb1,0x02,0x24,0x20,0x46,0x38,0xbd,
|
0xc7,0x20,0xff,0xf7,0x95,0xfe,0xbd,0xe8,0x08,0x40,0xff,0xf7,0x09,0xbf,0x08,0xbd,
|
||||||
0x1b,0x00,0x02,0x40,0x1a,0x00,0x02,0x40,0x10,0xb5,0xc3,0x21,0x04,0x46,0x9f,0x20,
|
0x10,0xb5,0x04,0x46,0xff,0xf7,0xec,0xfe,0xc3,0x21,0x9f,0x20,0xff,0xf7,0x88,0xfe,
|
||||||
0xff,0xf7,0xee,0xfe,0x06,0x4b,0x07,0x4a,0x19,0x78,0x01,0x33,0x00,0x20,0x1b,0x78,
|
0x06,0x4b,0x07,0x4a,0x19,0x78,0x01,0x33,0x00,0x20,0x1b,0x78,0x12,0x78,0x1b,0x02,
|
||||||
0x12,0x78,0x1b,0x02,0x43,0xea,0x01,0x43,0x13,0x43,0x23,0x60,0x10,0xbd,0x00,0xbf,
|
0x43,0xea,0x01,0x43,0x13,0x43,0x23,0x60,0x10,0xbd,0x00,0xbf,0x1a,0x00,0x02,0x40,
|
||||||
0x1a,0x00,0x02,0x40,0x1c,0x00,0x02,0x40,0x08,0xb5,0x10,0x22,0x00,0x21,0x00,0xf0,
|
0x1c,0x00,0x02,0x40,0x08,0xb5,0x14,0x22,0x00,0x21,0x00,0xf0,0x41,0xf8,0x00,0x20,
|
||||||
0x4d,0xf8,0x00,0x20,0x08,0xbd,0x00,0x00,0x73,0xb5,0x21,0x48,0x20,0x4c,0xff,0xf7,
|
0x08,0xbd,0x00,0x00,0x73,0xb5,0x1c,0x48,0x1b,0x4e,0x1c,0x4d,0xff,0xf7,0xf2,0xff,
|
||||||
0xf3,0xff,0x20,0x4a,0x13,0x78,0x43,0xf0,0x80,0x03,0x13,0x70,0xff,0xf7,0xb0,0xff,
|
0x34,0x46,0x33,0x69,0x00,0x2b,0xfc,0xd0,0xf3,0x68,0x01,0x3b,0x03,0x2b,0x29,0xd8,
|
||||||
0x05,0x46,0x58,0xb9,0x1c,0x4e,0xe3,0x68,0x00,0x2b,0xfc,0xd0,0xa3,0x68,0x01,0x3b,
|
0xdf,0xe8,0x03,0xf0,0x02,0x17,0x1f,0x22,0x01,0xa8,0xff,0xf7,0xc9,0xff,0xb0,0xb9,
|
||||||
0x03,0x2b,0x2a,0xd8,0xdf,0xe8,0x03,0xf0,0x04,0x18,0x20,0x23,0xe5,0x60,0xfd,0xe7,
|
0x01,0x9b,0x2b,0x70,0x19,0x0a,0x1b,0x0c,0x69,0x70,0xab,0x70,0xe8,0x70,0x23,0x7c,
|
||||||
0x01,0xa8,0xff,0xf7,0xc1,0xff,0xa8,0xb9,0x01,0x9b,0x33,0x70,0x1a,0x0a,0x1b,0x0c,
|
0x00,0x23,0x23,0x74,0x62,0x7c,0x63,0x74,0xa2,0x7c,0xa3,0x74,0xe2,0x7c,0xe3,0x74,
|
||||||
0x72,0x70,0xb3,0x70,0xf0,0x70,0x23,0x7b,0x25,0x73,0x63,0x7b,0x65,0x73,0xa3,0x7b,
|
0xdf,0xe7,0x60,0x68,0xa1,0x68,0xff,0xf7,0x65,0xff,0x00,0x28,0xef,0xd0,0x20,0x61,
|
||||||
0xa5,0x73,0xe3,0x7b,0xe5,0x73,0xde,0xe7,0x20,0x68,0x61,0x68,0xff,0xf7,0x48,0xff,
|
0xfe,0xe7,0xff,0xf7,0x9b,0xff,0xf8,0xe7,0x60,0x68,0xa1,0x68,0x2a,0x46,0xff,0xf7,
|
||||||
0x00,0x28,0xf0,0xd0,0xe0,0x60,0xfe,0xe7,0xff,0xf7,0x74,0xff,0xf8,0xe7,0x20,0x68,
|
0x1b,0xff,0xf2,0xe7,0x01,0x20,0xf2,0xe7,0x00,0x00,0x0c,0x20,0x14,0x00,0x0c,0x20,
|
||||||
0x61,0x68,0x32,0x46,0xff,0xf7,0x05,0xff,0xf2,0xe7,0x01,0x20,0xf2,0xe7,0x00,0xbf,
|
0xf0,0xb5,0x83,0x07,0x47,0xd0,0x54,0x1e,0x00,0x2a,0x41,0xd0,0x0d,0x06,0x2d,0x0e,
|
||||||
0x00,0x00,0x0c,0x20,0x10,0x30,0x0c,0x40,0x10,0x00,0x0c,0x20,0xf0,0xb5,0x05,0x00,
|
0x02,0x00,0x03,0x26,0x02,0xe0,0x1a,0x00,0x01,0x3c,0x39,0xd3,0x53,0x1c,0x15,0x70,
|
||||||
0x83,0x07,0x4e,0xd0,0x54,0x1e,0x00,0x2a,0x46,0xd0,0x0a,0x06,0x12,0x0e,0x03,0x00,
|
0x33,0x42,0xf8,0xd1,0x03,0x2c,0x2a,0xd9,0xff,0x22,0x0a,0x40,0x15,0x02,0x15,0x43,
|
||||||
0x03,0x26,0x02,0xe0,0x01,0x35,0x01,0x3c,0x3e,0xd3,0x01,0x33,0x2a,0x70,0x33,0x42,
|
0x2a,0x04,0x15,0x43,0x0f,0x2c,0x14,0xd9,0x27,0x00,0x1a,0x00,0x10,0x3f,0x3e,0x09,
|
||||||
0xf8,0xd1,0x03,0x2c,0x2f,0xd9,0xff,0x22,0x0a,0x40,0x15,0x02,0x15,0x43,0x2a,0x04,
|
0x01,0x36,0x36,0x01,0x9e,0x19,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,
|
||||||
0x15,0x43,0x0f,0x2c,0x38,0xd9,0x27,0x00,0x10,0x3f,0x3f,0x09,0x3e,0x01,0xb4,0x46,
|
0x96,0x42,0xf8,0xd1,0x0f,0x22,0x97,0x43,0x10,0x37,0xdb,0x19,0x14,0x40,0x03,0x2c,
|
||||||
0x1e,0x00,0x1a,0x00,0x10,0x36,0x66,0x44,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,
|
0x0d,0xd9,0x1a,0x00,0x27,0x1f,0xbe,0x08,0x01,0x36,0xb6,0x00,0x9e,0x19,0x20,0xc2,
|
||||||
0x10,0x32,0xb2,0x42,0xf8,0xd1,0x0f,0x26,0x0c,0x22,0x01,0x37,0x3f,0x01,0x26,0x40,
|
0xb2,0x42,0xfc,0xd1,0x03,0x22,0x97,0x43,0x04,0x37,0xdb,0x19,0x14,0x40,0x00,0x2c,
|
||||||
0xdb,0x19,0x37,0x00,0x22,0x42,0x1a,0xd0,0x3e,0x1f,0xb6,0x08,0xb4,0x00,0xa4,0x46,
|
0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,0x19,0x70,0x01,0x33,0x9c,0x42,0xfb,0xd1,
|
||||||
0x1a,0x00,0x1c,0x1d,0x64,0x44,0x20,0xc2,0xa2,0x42,0xfc,0xd1,0x03,0x24,0x01,0x36,
|
0xf0,0xbc,0x02,0xbc,0x08,0x47,0x14,0x00,0x03,0x00,0xc3,0xe7,
|
||||||
0xb6,0x00,0x9b,0x19,0x3c,0x40,0x00,0x2c,0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,
|
|
||||||
0x19,0x70,0x01,0x33,0x9c,0x42,0xfb,0xd1,0xf0,0xbc,0x02,0xbc,0x08,0x47,0x34,0x00,
|
|
||||||
0xf1,0xe7,0x14,0x00,0x03,0x00,0xbc,0xe7,0x27,0x00,0xdd,0xe7,
|
|
||||||
|
|
|
@ -10,9 +10,29 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "npcx_flash.h"
|
#include "npcx_flash.h"
|
||||||
|
|
||||||
|
/* flashloader parameter structure */
|
||||||
|
__attribute__ ((section(".buffers.g_cfg")))
|
||||||
|
static volatile struct npcx_flash_params g_cfg;
|
||||||
|
/* data buffer */
|
||||||
|
__attribute__ ((section(".buffers.g_buf")))
|
||||||
|
static uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE];
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* NPCX flash driver
|
* NPCX flash driver
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
|
static void flash_init(void)
|
||||||
|
{
|
||||||
|
if (g_cfg.fiu_ver == NPCX_FIU_NPCK) {
|
||||||
|
/* Set pinmux to SHD flash */
|
||||||
|
NPCX_DEVCNT = 0x80;
|
||||||
|
NPCX_DEVALT(0) = 0xC0;
|
||||||
|
NPCX_DEVALT(4) = 0x00;
|
||||||
|
} else {
|
||||||
|
/* Avoid F_CS0 toggles while programming the internal flash. */
|
||||||
|
NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void flash_execute_cmd(uint8_t code, uint8_t cts)
|
static void flash_execute_cmd(uint8_t code, uint8_t cts)
|
||||||
{
|
{
|
||||||
/* Set UMA code */
|
/* Set UMA code */
|
||||||
|
@ -26,11 +46,26 @@ static void flash_execute_cmd(uint8_t code, uint8_t cts)
|
||||||
|
|
||||||
static void flash_cs_level(uint8_t level)
|
static void flash_cs_level(uint8_t level)
|
||||||
{
|
{
|
||||||
|
int sw_cs = 0;
|
||||||
|
|
||||||
|
if (g_cfg.fiu_ver == NPCX_FIU_NPCX) {
|
||||||
|
sw_cs = 1;
|
||||||
|
} else if (g_cfg.fiu_ver == NPCX_FIU_NPCX_V2) {
|
||||||
|
sw_cs = 0;
|
||||||
|
} else if (g_cfg.fiu_ver == NPCX_FIU_NPCK) {
|
||||||
|
sw_cs = 1;
|
||||||
|
/* Unlock UMA before pulling down CS in NPCK series */
|
||||||
|
if (level)
|
||||||
|
NPCX_CLEAR_BIT(NPCX_FIU_MSR_IE_CFG, NPCX_FIU_MSR_IE_CFG_UMA_BLOCK);
|
||||||
|
else
|
||||||
|
NPCX_SET_BIT(NPCX_FIU_MSR_IE_CFG, NPCX_FIU_MSR_IE_CFG_UMA_BLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
/* Program chip select pin to high/low level */
|
/* Program chip select pin to high/low level */
|
||||||
if (level)
|
if (level)
|
||||||
NPCX_SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
|
NPCX_SET_BIT(NPCX_UMA_ECTS, sw_cs);
|
||||||
else
|
else
|
||||||
NPCX_CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
|
NPCX_CLEAR_BIT(NPCX_UMA_ECTS, sw_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flash_set_address(uint32_t dest_addr)
|
static void flash_set_address(uint32_t dest_addr)
|
||||||
|
@ -38,15 +73,15 @@ static void flash_set_address(uint32_t dest_addr)
|
||||||
uint8_t *addr = (uint8_t *)&dest_addr;
|
uint8_t *addr = (uint8_t *)&dest_addr;
|
||||||
|
|
||||||
/* Set target flash address */
|
/* Set target flash address */
|
||||||
NPCX_UMA_AB2 = addr[2];
|
NPCX_UMA_DB0 = addr[2];
|
||||||
NPCX_UMA_AB1 = addr[1];
|
NPCX_UMA_DB1 = addr[1];
|
||||||
NPCX_UMA_AB0 = addr[0];
|
NPCX_UMA_DB2 = addr[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void delay(uint32_t i)
|
static void delay(uint32_t i)
|
||||||
{
|
{
|
||||||
while (i--)
|
while (i--)
|
||||||
;
|
__asm__ volatile ("nop");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flash_wait_ready(uint32_t timeout)
|
static int flash_wait_ready(uint32_t timeout)
|
||||||
|
@ -104,7 +139,7 @@ static void flash_burst_write(uint32_t dest_addr, uint16_t bytes,
|
||||||
/* Set write address */
|
/* Set write address */
|
||||||
flash_set_address(dest_addr);
|
flash_set_address(dest_addr);
|
||||||
/* Start programming */
|
/* Start programming */
|
||||||
flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_ADR);
|
flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_3BYTE);
|
||||||
for (uint32_t i = 0; i < bytes; i++) {
|
for (uint32_t i = 0; i < bytes; i++) {
|
||||||
flash_execute_cmd(*data, NPCX_MASK_CMD_WR_ONLY);
|
flash_execute_cmd(*data, NPCX_MASK_CMD_WR_ONLY);
|
||||||
data++;
|
data++;
|
||||||
|
@ -114,6 +149,15 @@ static void flash_burst_write(uint32_t dest_addr, uint16_t bytes,
|
||||||
flash_cs_level(1);
|
flash_cs_level(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void flash_get_stsreg(uint8_t *reg1, uint8_t *reg2)
|
||||||
|
{
|
||||||
|
/* Read status register 1/2 for checking */
|
||||||
|
flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE);
|
||||||
|
*reg1 = NPCX_UMA_DB0;
|
||||||
|
flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE);
|
||||||
|
*reg2 = NPCX_UMA_DB0;
|
||||||
|
}
|
||||||
|
|
||||||
/* The data to write cannot cross 256 Bytes boundary */
|
/* The data to write cannot cross 256 Bytes boundary */
|
||||||
static int flash_program_write(uint32_t addr, uint32_t size,
|
static int flash_program_write(uint32_t addr, uint32_t size,
|
||||||
const uint8_t *data)
|
const uint8_t *data)
|
||||||
|
@ -126,7 +170,41 @@ static int flash_program_write(uint32_t addr, uint32_t size,
|
||||||
return flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
|
return flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data)
|
static int flash_physical_clear_stsreg(void)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
uint8_t reg1, reg2;
|
||||||
|
|
||||||
|
/* Read status register 1/2 for checking */
|
||||||
|
flash_get_stsreg(®1, ®2);
|
||||||
|
if (reg1 == 0x00 && reg2 == 0x00)
|
||||||
|
return NPCX_FLASH_STATUS_OK;
|
||||||
|
|
||||||
|
/* Enable write */
|
||||||
|
status = flash_write_enable();
|
||||||
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
NPCX_UMA_DB0 = 0x0;
|
||||||
|
NPCX_UMA_DB1 = 0x0;
|
||||||
|
|
||||||
|
/* Write status register 1/2 */
|
||||||
|
flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE);
|
||||||
|
|
||||||
|
/* Wait writing completed */
|
||||||
|
status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
|
||||||
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
/* Read status register 1/2 for checking */
|
||||||
|
flash_get_stsreg(®1, ®2);
|
||||||
|
if (reg1 != 0x00 || reg2 != 0x00)
|
||||||
|
return NPCX_FLASH_STATUS_FAILED;
|
||||||
|
|
||||||
|
return NPCX_FLASH_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
uint32_t trunk_start = (offset + 0xff) & ~0xff;
|
uint32_t trunk_start = (offset + 0xff) & ~0xff;
|
||||||
|
@ -135,6 +213,13 @@ int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data)
|
||||||
uint32_t dest_addr = offset;
|
uint32_t dest_addr = offset;
|
||||||
uint32_t write_len = ((trunk_start - offset) > size) ? size : (trunk_start - offset);
|
uint32_t write_len = ((trunk_start - offset) > size) ? size : (trunk_start - offset);
|
||||||
|
|
||||||
|
/* Configure fiu and clear status registers if needed */
|
||||||
|
flash_init();
|
||||||
|
status = flash_physical_clear_stsreg();
|
||||||
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
|
||||||
if (write_len) {
|
if (write_len) {
|
||||||
status = flash_program_write(dest_addr, write_len, data);
|
status = flash_program_write(dest_addr, write_len, data);
|
||||||
if (status != NPCX_FLASH_STATUS_OK)
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
@ -162,8 +247,16 @@ int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data)
|
||||||
return NPCX_FLASH_STATUS_OK;
|
return NPCX_FLASH_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flash_physical_erase(uint32_t offset, uint32_t size)
|
static int flash_physical_erase(uint32_t offset, uint32_t size)
|
||||||
{
|
{
|
||||||
|
/* Configure fiu */
|
||||||
|
flash_init();
|
||||||
|
|
||||||
|
/* clear flash status registers */
|
||||||
|
int status = flash_physical_clear_stsreg();
|
||||||
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
/* Alignment has been checked in upper layer */
|
/* Alignment has been checked in upper layer */
|
||||||
for (; size > 0; size -= NPCX_FLASH_ERASE_SIZE,
|
for (; size > 0; size -= NPCX_FLASH_ERASE_SIZE,
|
||||||
offset += NPCX_FLASH_ERASE_SIZE) {
|
offset += NPCX_FLASH_ERASE_SIZE) {
|
||||||
|
@ -175,7 +268,7 @@ int flash_physical_erase(uint32_t offset, uint32_t size)
|
||||||
/* Set erase address */
|
/* Set erase address */
|
||||||
flash_set_address(offset);
|
flash_set_address(offset);
|
||||||
/* Start erase */
|
/* Start erase */
|
||||||
flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_ADR);
|
flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_WR_3BYTE);
|
||||||
/* Wait erase completed */
|
/* Wait erase completed */
|
||||||
status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
|
status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
|
||||||
if (status != NPCX_FLASH_STATUS_OK)
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
@ -185,10 +278,18 @@ int flash_physical_erase(uint32_t offset, uint32_t size)
|
||||||
return NPCX_FLASH_STATUS_OK;
|
return NPCX_FLASH_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flash_physical_erase_all(void)
|
static int flash_physical_erase_all(void)
|
||||||
{
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* Configure fiu and clear status register if needed */
|
||||||
|
flash_init();
|
||||||
|
status = flash_physical_clear_stsreg();
|
||||||
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
/* Enable write */
|
/* Enable write */
|
||||||
int status = flash_write_enable();
|
status = flash_write_enable();
|
||||||
if (status != NPCX_FLASH_STATUS_OK)
|
if (status != NPCX_FLASH_STATUS_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -203,37 +304,10 @@ int flash_physical_erase_all(void)
|
||||||
return NPCX_FLASH_STATUS_OK;
|
return NPCX_FLASH_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flash_physical_clear_stsreg(void)
|
static int flash_get_id(uint32_t *id)
|
||||||
{
|
{
|
||||||
/* Enable write */
|
flash_init();
|
||||||
int status = flash_write_enable();
|
|
||||||
if (status != NPCX_FLASH_STATUS_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
NPCX_UMA_DB0 = 0x0;
|
|
||||||
NPCX_UMA_DB1 = 0x0;
|
|
||||||
|
|
||||||
/* Write status register 1/2 */
|
|
||||||
flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE);
|
|
||||||
|
|
||||||
/* Wait writing completed */
|
|
||||||
status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
|
|
||||||
if (status != NPCX_FLASH_STATUS_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
/* Read status register 1/2 for checking */
|
|
||||||
flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE);
|
|
||||||
if (NPCX_UMA_DB0 != 0x00)
|
|
||||||
return NPCX_FLASH_STATUS_FAILED;
|
|
||||||
flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE);
|
|
||||||
if (NPCX_UMA_DB0 != 0x00)
|
|
||||||
return NPCX_FLASH_STATUS_FAILED;
|
|
||||||
|
|
||||||
return NPCX_FLASH_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flash_get_id(uint32_t *id)
|
|
||||||
{
|
|
||||||
flash_execute_cmd(NPCX_CMD_READ_ID, NPCX_MASK_CMD_RD_3BYTE);
|
flash_execute_cmd(NPCX_CMD_READ_ID, NPCX_MASK_CMD_RD_3BYTE);
|
||||||
*id = NPCX_UMA_DB0 << 16 | NPCX_UMA_DB1 << 8 | NPCX_UMA_DB2;
|
*id = NPCX_UMA_DB0 << 16 | NPCX_UMA_DB1 << 8 | NPCX_UMA_DB2;
|
||||||
|
|
||||||
|
@ -243,7 +317,7 @@ int flash_get_id(uint32_t *id)
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* flash loader function
|
* flash loader function
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
uint32_t flashloader_init(struct npcx_flash_params *params)
|
static uint32_t flashloader_init(struct npcx_flash_params *params)
|
||||||
{
|
{
|
||||||
/* Initialize params buffers */
|
/* Initialize params buffers */
|
||||||
memset(params, 0, sizeof(struct npcx_flash_params));
|
memset(params, 0, sizeof(struct npcx_flash_params));
|
||||||
|
@ -254,30 +328,13 @@ uint32_t flashloader_init(struct npcx_flash_params *params)
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Functions
|
* Functions
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
/* flashloader parameter structure */
|
static int main(void)
|
||||||
__attribute__ ((section(".buffers.g_cfg")))
|
|
||||||
volatile struct npcx_flash_params g_cfg;
|
|
||||||
/* data buffer */
|
|
||||||
__attribute__ ((section(".buffers.g_buf")))
|
|
||||||
uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE];
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id, status;
|
||||||
|
|
||||||
/* set buffer */
|
/* set buffer */
|
||||||
flashloader_init((struct npcx_flash_params *)&g_cfg);
|
flashloader_init((struct npcx_flash_params *)&g_cfg);
|
||||||
|
|
||||||
/* Avoid F_CS0 toggles while programming the internal flash. */
|
|
||||||
NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
|
|
||||||
|
|
||||||
/* clear flash status registers */
|
|
||||||
int status = flash_physical_clear_stsreg();
|
|
||||||
if (status != NPCX_FLASH_STATUS_OK) {
|
|
||||||
while (1)
|
|
||||||
g_cfg.sync = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
/* wait command*/
|
/* wait command*/
|
||||||
while (g_cfg.sync == NPCX_FLASH_LOADER_WAIT)
|
while (g_cfg.sync == NPCX_FLASH_LOADER_WAIT)
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
#define NPCX_FIU_DMM_CYC NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x032)
|
#define NPCX_FIU_DMM_CYC NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x032)
|
||||||
#define NPCX_FIU_EXT_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x033)
|
#define NPCX_FIU_EXT_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x033)
|
||||||
#define NPCX_FIU_UMA_AB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x034)
|
#define NPCX_FIU_UMA_AB0_3 NPCX_HW_DWORD(NPCX_FIU_BASE_ADDR + 0x034)
|
||||||
|
#define NPCX_FIU_MSR_IE_CFG NPCX_HW_BYTE(NPCX_FIU_BASE_ADDR + 0x043)
|
||||||
|
|
||||||
/* FIU register fields */
|
/* FIU register fields */
|
||||||
#define NPCX_RESP_CFG_IAD_EN 0
|
#define NPCX_RESP_CFG_IAD_EN 0
|
||||||
|
@ -93,6 +94,7 @@
|
||||||
#define NPCX_UMA_ECTS_SW_CS1 1
|
#define NPCX_UMA_ECTS_SW_CS1 1
|
||||||
#define NPCX_UMA_ECTS_SEC_CS 2
|
#define NPCX_UMA_ECTS_SEC_CS 2
|
||||||
#define NPCX_UMA_ECTS_UMA_LOCK 3
|
#define NPCX_UMA_ECTS_UMA_LOCK 3
|
||||||
|
#define NPCX_FIU_MSR_IE_CFG_UMA_BLOCK 3
|
||||||
|
|
||||||
/* Flash UMA commands for npcx internal SPI flash */
|
/* Flash UMA commands for npcx internal SPI flash */
|
||||||
#define NPCX_CMD_READ_ID 0x9F
|
#define NPCX_CMD_READ_ID 0x9F
|
||||||
|
@ -130,7 +132,6 @@
|
||||||
#define NPCX_SPI_FLASH_SR1_BUSY (1 << 0)
|
#define NPCX_SPI_FLASH_SR1_BUSY (1 << 0)
|
||||||
|
|
||||||
#define NPCX_MASK_CMD_ONLY (0xC0)
|
#define NPCX_MASK_CMD_ONLY (0xC0)
|
||||||
#define NPCX_MASK_CMD_ADR (0xC0 | 0x08)
|
|
||||||
#define NPCX_MASK_CMD_ADR_WR (0xC0 | 0x20 | 0x08 | 0x01)
|
#define NPCX_MASK_CMD_ADR_WR (0xC0 | 0x20 | 0x08 | 0x01)
|
||||||
#define NPCX_MASK_RD_1BYTE (0xC0 | 0x10 | 0x01)
|
#define NPCX_MASK_RD_1BYTE (0xC0 | 0x10 | 0x01)
|
||||||
#define NPCX_MASK_RD_2BYTE (0xC0 | 0x10 | 0x02)
|
#define NPCX_MASK_RD_2BYTE (0xC0 | 0x10 | 0x02)
|
||||||
|
@ -143,10 +144,12 @@
|
||||||
#define NPCX_MASK_CMD_WR_ONLY (0xC0 | 0x20)
|
#define NPCX_MASK_CMD_WR_ONLY (0xC0 | 0x20)
|
||||||
#define NPCX_MASK_CMD_WR_1BYTE (0xC0 | 0x20 | 0x10 | 0x01)
|
#define NPCX_MASK_CMD_WR_1BYTE (0xC0 | 0x20 | 0x10 | 0x01)
|
||||||
#define NPCX_MASK_CMD_WR_2BYTE (0xC0 | 0x20 | 0x10 | 0x02)
|
#define NPCX_MASK_CMD_WR_2BYTE (0xC0 | 0x20 | 0x10 | 0x02)
|
||||||
#define NPCX_MASK_CMD_WR_ADR (0xC0 | 0x20 | 0x08)
|
#define NPCX_MASK_CMD_WR_3BYTE (0xC0 | 0x20 | 0x10 | 0x03)
|
||||||
|
#define NPCX_MASK_CMD_WR_4BYTE (0xC0 | 0x20 | 0x10 | 0x04)
|
||||||
|
|
||||||
/* Flash loader parameters */
|
/* Flash loader parameters */
|
||||||
struct __attribute__((__packed__)) npcx_flash_params {
|
struct __attribute__((__packed__)) npcx_flash_params {
|
||||||
|
uint32_t fiu_ver; /* Flash controller unit version */
|
||||||
uint32_t addr; /* Address in flash */
|
uint32_t addr; /* Address in flash */
|
||||||
uint32_t len; /* Number of bytes */
|
uint32_t len; /* Number of bytes */
|
||||||
uint32_t cmd; /* Command */
|
uint32_t cmd; /* Command */
|
||||||
|
@ -176,4 +179,10 @@ enum npcx_flash_status {
|
||||||
NPCX_FLASH_STATUS_FAILED_TIMEOUT,
|
NPCX_FLASH_STATUS_FAILED_TIMEOUT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum npcx_fiu_ver {
|
||||||
|
NPCX_FIU_NPCX = 0,
|
||||||
|
NPCX_FIU_NPCX_V2,
|
||||||
|
NPCX_FIU_NPCK,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H */
|
#endif /* OPENOCD_LOADERS_FLASH_NPCX_NPCX_FLASH_H */
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
/* NPCX flash loader information */
|
/* NPCX flash loader information */
|
||||||
#define NPCX_FLASH_LOADER_WORKING_ADDR 0x200C0000
|
#define NPCX_FLASH_LOADER_WORKING_ADDR 0x200C0000
|
||||||
#define NPCX_FLASH_LOADER_PARAMS_ADDR NPCX_FLASH_LOADER_WORKING_ADDR
|
#define NPCX_FLASH_LOADER_PARAMS_ADDR NPCX_FLASH_LOADER_WORKING_ADDR
|
||||||
#define NPCX_FLASH_LOADER_PARAMS_SIZE 16
|
#define NPCX_FLASH_LOADER_PARAMS_SIZE 20
|
||||||
#define NPCX_FLASH_LOADER_BUFFER_ADDR (NPCX_FLASH_LOADER_PARAMS_ADDR + NPCX_FLASH_LOADER_PARAMS_SIZE)
|
#define NPCX_FLASH_LOADER_BUFFER_ADDR (NPCX_FLASH_LOADER_PARAMS_ADDR + NPCX_FLASH_LOADER_PARAMS_SIZE)
|
||||||
#define NPCX_FLASH_LOADER_BUFFER_SIZE NPCX_FLASH_ERASE_SIZE
|
#define NPCX_FLASH_LOADER_BUFFER_SIZE NPCX_FLASH_ERASE_SIZE
|
||||||
#define NPCX_FLASH_LOADER_PROGRAM_ADDR (NPCX_FLASH_LOADER_BUFFER_ADDR + NPCX_FLASH_LOADER_BUFFER_SIZE)
|
#define NPCX_FLASH_LOADER_PROGRAM_ADDR (NPCX_FLASH_LOADER_BUFFER_ADDR + NPCX_FLASH_LOADER_BUFFER_SIZE)
|
||||||
|
|
|
@ -111,8 +111,8 @@ Finally, try to avoid lines of code that are longer than 72-80 columns:
|
||||||
@section stylenames Naming Rules
|
@section stylenames Naming Rules
|
||||||
|
|
||||||
- most identifiers must use lower-case letters (and digits) only.
|
- most identifiers must use lower-case letters (and digits) only.
|
||||||
- macros must use upper-case letters (and digits) only.
|
- macros and enumerators must use upper-case letters (and digits) only.
|
||||||
- OpenOCD identifiers should NEVER use @c MixedCaps.
|
- OpenOCD identifiers should NEVER use @c MixedCaps, aka @c CamelCase.
|
||||||
- @c typedef names must end with the '_t' suffix.
|
- @c typedef names must end with the '_t' suffix.
|
||||||
- This should be reserved for types that should be passed by value.
|
- This should be reserved for types that should be passed by value.
|
||||||
- Do @b not mix the typedef keyword with @c struct.
|
- Do @b not mix the typedef keyword with @c struct.
|
||||||
|
|
149
doc/openocd.texi
149
doc/openocd.texi
|
@ -3597,6 +3597,79 @@ espusbjtag chip_id 1
|
||||||
|
|
||||||
@end deffn
|
@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
|
@section Transport Configuration
|
||||||
@cindex Transport
|
@cindex Transport
|
||||||
As noted earlier, depending on the version of OpenOCD you use,
|
As noted earlier, depending on the version of OpenOCD you use,
|
||||||
|
@ -5856,24 +5929,42 @@ flash bank $_FLASHNAME cfi 0x00000000 0x02000000 2 4 $_TARGETNAME
|
||||||
@c "cfi part_id" disabled
|
@c "cfi part_id" disabled
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@anchor{jtagspi}
|
||||||
@deffn {Flash Driver} {jtagspi}
|
@deffn {Flash Driver} {jtagspi}
|
||||||
@cindex Generic JTAG2SPI driver
|
@cindex Generic JTAG2SPI driver
|
||||||
@cindex SPI
|
@cindex SPI
|
||||||
@cindex jtagspi
|
@cindex jtagspi
|
||||||
@cindex bscan_spi
|
@cindex bscan_spi
|
||||||
Several FPGAs and CPLDs can retrieve their configuration (bitstream) from a
|
Several FPGAs and CPLDs can retrieve their configuration (bitstream) from a
|
||||||
SPI flash connected to them. To access this flash from the host, the device
|
SPI flash connected to them. To access this flash from the host, some FPGA
|
||||||
is first programmed with a special proxy bitstream that
|
device provides dedicated JTAG instructions, while other FPGA devices should
|
||||||
exposes the SPI flash on the device's JTAG interface. The flash can then be
|
be programmed with a special proxy bitstream that exposes the SPI flash on
|
||||||
accessed through JTAG.
|
the device's JTAG interface. The flash can then be accessed through JTAG.
|
||||||
|
|
||||||
Since signaling between JTAG and SPI is compatible, all that is required for
|
Since signalling between JTAG and SPI is compatible, all that is required for
|
||||||
a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate
|
a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate
|
||||||
the flash chip select when the JTAG state machine is in SHIFT-DR. Such
|
the flash chip select when the JTAG state machine is in SHIFT-DR.
|
||||||
a bitstream for several Xilinx FPGAs can be found in
|
|
||||||
|
Such a bitstream for several Xilinx FPGAs can be found in
|
||||||
@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires
|
@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires
|
||||||
@uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build.
|
@uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build.
|
||||||
|
|
||||||
|
This mechanism with a proxy bitstream can also be used for FPGAs from Intel and
|
||||||
|
Efinix. FPGAs from Lattice and Cologne Chip have dedicated JTAG instructions
|
||||||
|
and procedure to connect the JTAG to the SPI signals and don't need a proxy
|
||||||
|
bitstream. Support for these devices with dedicated procedure is provided by
|
||||||
|
the pld drivers. For convenience the PLD drivers will provide the USERx code
|
||||||
|
for FPGAs with a proxy bitstream. Currently the following PLD drivers are able
|
||||||
|
to support jtagspi:
|
||||||
|
@itemize
|
||||||
|
@item Efinix: proxy-bitstream
|
||||||
|
@item Gatemate: dedicated procedure
|
||||||
|
@item Intel/Altera: proxy-bitstream
|
||||||
|
@item Lattice: dedicated procedure supporting ECP2, ECP3, ECP5, Certus and Certus Pro devices
|
||||||
|
@item AMD/Xilinx: proxy-bitstream
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
|
||||||
This flash bank driver requires a target on a JTAG tap and will access that
|
This flash bank driver requires a target on a JTAG tap and will access that
|
||||||
tap directly. Since no support from the target is needed, the target can be a
|
tap directly. Since no support from the target is needed, the target can be a
|
||||||
"testee" dummy. Since the target does not expose the flash memory
|
"testee" dummy. Since the target does not expose the flash memory
|
||||||
|
@ -5891,14 +5982,25 @@ command, see below.
|
||||||
@item @var{ir} ... is loaded into the JTAG IR to map the flash as the JTAG DR.
|
@item @var{ir} ... is loaded into the JTAG IR to map the flash as the JTAG DR.
|
||||||
For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the
|
For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the
|
||||||
@var{USER1} instruction.
|
@var{USER1} instruction.
|
||||||
@end itemize
|
@example
|
||||||
|
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
||||||
|
set _USER1_INSTR_CODE 0x02
|
||||||
|
flash bank $_FLASHNAME jtagspi 0x0 0 0 0 \
|
||||||
|
$_TARGETNAME $_USER1_INSTR_CODE
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@item The option @option{-pld} @var{name} is used to have support from the
|
||||||
|
PLD driver of pld device @var{name}. The name is the name of the pld device
|
||||||
|
given during creation of the pld device.
|
||||||
|
Pld device names are shown by the @command{pld devices} command.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
target create $_TARGETNAME testee -chain-position $_CHIPNAME.fpga
|
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
||||||
set _XILINX_USER1 0x02
|
set _JTAGSPI_CHAIN_ID $_CHIPNAME.pld
|
||||||
flash bank $_FLASHNAME spi 0x0 0 0 0 \
|
flash bank $_FLASHNAME jtagspi 0x0 0 0 0 \
|
||||||
$_TARGETNAME $_XILINX_USER1
|
$_TARGETNAME -pld $_JTAGSPI_CHAIN_ID
|
||||||
@end example
|
@end example
|
||||||
|
@end itemize
|
||||||
|
|
||||||
@deffn Command {jtagspi set} bank_id name total_size page_size read_cmd unused pprg_cmd mass_erase_cmd sector_size sector_erase_cmd
|
@deffn Command {jtagspi set} bank_id name total_size page_size read_cmd unused pprg_cmd mass_erase_cmd sector_size sector_erase_cmd
|
||||||
Sets flash parameters: @var{name} human readable string, @var{total_size}
|
Sets flash parameters: @var{name} human readable string, @var{total_size}
|
||||||
|
@ -7149,10 +7251,16 @@ Show information about flash driver.
|
||||||
All versions of the NPCX microcontroller families from Nuvoton include internal
|
All versions of the NPCX microcontroller families from Nuvoton include internal
|
||||||
flash. The NPCX flash driver supports the NPCX family of devices. The driver
|
flash. The NPCX flash driver supports the NPCX family of devices. The driver
|
||||||
automatically recognizes the specific version's flash parameters and
|
automatically recognizes the specific version's flash parameters and
|
||||||
autoconfigures itself. The flash bank starts at address 0x64000000.
|
autoconfigures itself. The flash bank starts at address 0x64000000. An optional additional
|
||||||
|
parameter sets the FIU version for the bank, with the default FIU is @var{npcx.fiu}.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
|
|
||||||
|
flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME npcx_v2.fiu
|
||||||
|
|
||||||
|
# FIU defaults to npcx.fiu
|
||||||
flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME
|
||||||
|
|
||||||
@end example
|
@end example
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -8618,7 +8726,8 @@ Accordingly, both are called PLDs here.
|
||||||
|
|
||||||
As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
|
As it does for JTAG TAPs, debug targets, and flash chips (both NOR and NAND),
|
||||||
OpenOCD maintains a list of PLDs available for use in various commands.
|
OpenOCD maintains a list of PLDs available for use in various commands.
|
||||||
Also, each such PLD requires a driver.
|
Also, each such PLD requires a driver. PLD drivers may also be needed to program
|
||||||
|
SPI flash connected to the FPGA to store the bitstream (@xref{jtagspi} for details).
|
||||||
|
|
||||||
They are referenced by the name which was given when the pld was created or
|
They are referenced by the name which was given when the pld was created or
|
||||||
the number shown by the @command{pld devices} command.
|
the number shown by the @command{pld devices} command.
|
||||||
|
@ -8684,8 +8793,8 @@ Change values for boundary scan instructions selecting the registers USER1 to US
|
||||||
Description of the arguments can be found at command @command{virtex2 set_instr_codes}.
|
Description of the arguments can be found at command @command{virtex2 set_instr_codes}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {virtex2 program} pld_name
|
@deffn {Command} {virtex2 refresh} pld_name
|
||||||
Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a. refresh.
|
Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a. program.
|
||||||
@end deffn
|
@end deffn
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@ -8716,6 +8825,10 @@ for FPGA @var{pld_name} with value @var{val}.
|
||||||
Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
|
Set the length of the register for the preload. This is needed when the JTAG ID of the device is not known by openocd (newer NX devices).
|
||||||
The load command for the FPGA @var{pld_name} will use a length for the preload of @var{length}.
|
The load command for the FPGA @var{pld_name} will use a length for the preload of @var{length}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Command} {lattice refresh} pld_name
|
||||||
|
Load the bitstream from external memory for FPGA @var{pld_name}. A.k.a program.
|
||||||
|
@end deffn
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@ -8770,9 +8883,9 @@ Reads and displays the user register
|
||||||
for FPGA @var{pld_name}.
|
for FPGA @var{pld_name}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Command} {gowin reload} pld_name
|
@deffn {Command} {gowin refresh} pld_name
|
||||||
Load the bitstream from external memory for
|
Load the bitstream from external memory for
|
||||||
FPGA @var{pld_name}. A.k.a. refresh.
|
FPGA @var{pld_name}. A.k.a. reload.
|
||||||
@end deffn
|
@end deffn
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
|
# 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:
|
Device Descriptor:
|
||||||
bLength 18
|
bLength 18
|
||||||
bDescriptorType 1
|
bDescriptorType 1
|
||||||
bcdUSB 2.00
|
bcdUSB 2.00
|
||||||
bDeviceClass 255 Vendor Specific Class
|
bDeviceClass 239 Miscellaneous Device
|
||||||
bDeviceSubClass 255 Vendor Specific Subclass
|
bDeviceSubClass 2
|
||||||
bDeviceProtocol 255 Vendor Specific Protocol
|
bDeviceProtocol 1 Interface Association
|
||||||
bMaxPacketSize0 64
|
bMaxPacketSize0 64
|
||||||
idVendor 0x584e
|
idVendor 0x584e
|
||||||
idProduct 0x424e
|
idProduct 0x424e
|
||||||
|
@ -19,13 +19,22 @@ Device Descriptor:
|
||||||
Configuration Descriptor:
|
Configuration Descriptor:
|
||||||
bLength 9
|
bLength 9
|
||||||
bDescriptorType 2
|
bDescriptorType 2
|
||||||
wTotalLength 0x0027
|
wTotalLength 0x0047
|
||||||
bNumInterfaces 1
|
bNumInterfaces 2
|
||||||
bConfigurationValue 1
|
bConfigurationValue 1
|
||||||
iConfiguration 4 (error)
|
iConfiguration 1 NanoXplore, SAS.
|
||||||
bmAttributes 0x80
|
bmAttributes 0x80
|
||||||
(Bus Powered)
|
(Bus Powered)
|
||||||
MaxPower 100mA
|
MaxPower 100mA
|
||||||
|
Interface Association:
|
||||||
|
bLength 8
|
||||||
|
bDescriptorType 11
|
||||||
|
bFirstInterface 1
|
||||||
|
bInterfaceCount 2
|
||||||
|
bFunctionClass 2 Communications
|
||||||
|
bFunctionSubClass 0
|
||||||
|
bFunctionProtocol 0
|
||||||
|
iFunction 0
|
||||||
Interface Descriptor:
|
Interface Descriptor:
|
||||||
bLength 9
|
bLength 9
|
||||||
bDescriptorType 4
|
bDescriptorType 4
|
||||||
|
@ -33,9 +42,9 @@ Device Descriptor:
|
||||||
bAlternateSetting 0
|
bAlternateSetting 0
|
||||||
bNumEndpoints 3
|
bNumEndpoints 3
|
||||||
bInterfaceClass 255 Vendor Specific Class
|
bInterfaceClass 255 Vendor Specific Class
|
||||||
bInterfaceSubClass 255 Vendor Specific Subclass
|
bInterfaceSubClass 0
|
||||||
bInterfaceProtocol 255 Vendor Specific Protocol
|
bInterfaceProtocol 0
|
||||||
iInterface 0
|
iInterface 4 JTAG Adapter
|
||||||
Endpoint Descriptor:
|
Endpoint Descriptor:
|
||||||
bLength 7
|
bLength 7
|
||||||
bDescriptorType 5
|
bDescriptorType 5
|
||||||
|
@ -66,3 +75,33 @@ Device Descriptor:
|
||||||
Usage Type Data
|
Usage Type Data
|
||||||
wMaxPacketSize 0x0200 1x 512 bytes
|
wMaxPacketSize 0x0200 1x 512 bytes
|
||||||
bInterval 0
|
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
|
||||||
|
|
|
@ -560,12 +560,22 @@ static int at91sam7_read_part_info(struct flash_bank *bank)
|
||||||
if (bnk > 0) {
|
if (bnk > 0) {
|
||||||
if (!t_bank->next) {
|
if (!t_bank->next) {
|
||||||
/* create a new flash bank element */
|
/* create a new flash bank element */
|
||||||
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
|
struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1);
|
||||||
|
if (!fb) {
|
||||||
|
LOG_ERROR("No memory for flash bank");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
fb->target = target;
|
fb->target = target;
|
||||||
fb->driver = bank->driver;
|
fb->driver = bank->driver;
|
||||||
|
fb->default_padded_value = 0xff;
|
||||||
|
fb->erased_value = 0xff;
|
||||||
fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank));
|
fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank));
|
||||||
fb->name = "sam7_probed";
|
if (!fb->driver_priv) {
|
||||||
fb->next = NULL;
|
free(fb);
|
||||||
|
LOG_ERROR("No memory for flash driver priv");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
fb->name = strdup("sam7_probed");
|
||||||
|
|
||||||
/* link created bank in 'flash_banks' list */
|
/* link created bank in 'flash_banks' list */
|
||||||
t_bank->next = fb;
|
t_bank->next = fb;
|
||||||
|
@ -738,12 +748,22 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
|
||||||
if (bnk > 0) {
|
if (bnk > 0) {
|
||||||
if (!t_bank->next) {
|
if (!t_bank->next) {
|
||||||
/* create a new bank element */
|
/* create a new bank element */
|
||||||
struct flash_bank *fb = malloc(sizeof(struct flash_bank));
|
struct flash_bank *fb = calloc(sizeof(struct flash_bank), 1);
|
||||||
|
if (!fb) {
|
||||||
|
LOG_ERROR("No memory for flash bank");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
fb->target = target;
|
fb->target = target;
|
||||||
fb->driver = bank->driver;
|
fb->driver = bank->driver;
|
||||||
|
fb->default_padded_value = 0xff;
|
||||||
|
fb->erased_value = 0xff;
|
||||||
fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank));
|
fb->driver_priv = malloc(sizeof(struct at91sam7_flash_bank));
|
||||||
fb->name = "sam7_probed";
|
if (!fb->driver_priv) {
|
||||||
fb->next = NULL;
|
free(fb);
|
||||||
|
LOG_ERROR("No memory for flash driver priv");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
fb->name = strdup("sam7_probed");
|
||||||
|
|
||||||
/* link created bank in 'flash_banks' list */
|
/* link created bank in 'flash_banks' list */
|
||||||
t_bank->next = fb;
|
t_bank->next = fb;
|
||||||
|
|
|
@ -261,7 +261,6 @@ FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
|
||||||
|
|
||||||
/* Finish initialization of bank */
|
/* Finish initialization of bank */
|
||||||
bank->driver_priv = cc26xx_bank;
|
bank->driver_priv = cc26xx_bank;
|
||||||
bank->next = NULL;
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,6 @@ FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command)
|
||||||
|
|
||||||
/* Finish initialization of flash bank */
|
/* Finish initialization of flash bank */
|
||||||
bank->driver_priv = cc3220sf_bank;
|
bank->driver_priv = cc3220sf_bank;
|
||||||
bank->next = NULL;
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
#include <flash/nor/spi.h>
|
#include <flash/nor/spi.h>
|
||||||
#include <helper/time_support.h>
|
#include <helper/time_support.h>
|
||||||
|
#include <pld/pld.h>
|
||||||
|
|
||||||
#define JTAGSPI_MAX_TIMEOUT 3000
|
#define JTAGSPI_MAX_TIMEOUT 3000
|
||||||
|
|
||||||
|
@ -21,19 +22,44 @@ struct jtagspi_flash_bank {
|
||||||
struct flash_device dev;
|
struct flash_device dev;
|
||||||
char devname[32];
|
char devname[32];
|
||||||
bool probed;
|
bool probed;
|
||||||
bool always_4byte; /* use always 4-byte address except for basic read 0x03 */
|
bool always_4byte; /* use always 4-byte address except for basic read 0x03 */
|
||||||
uint32_t ir;
|
unsigned int addr_len; /* address length in bytes */
|
||||||
unsigned int addr_len; /* address length in bytes */
|
struct pld_device *pld_device; /* if not NULL, the PLD has special instructions for JTAGSPI */
|
||||||
|
uint32_t ir; /* when !pld_device, this instruction code is used in
|
||||||
|
jtagspi_set_user_ir to connect through a proxy bitstream */
|
||||||
};
|
};
|
||||||
|
|
||||||
FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
|
FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct jtagspi_flash_bank *info;
|
|
||||||
|
|
||||||
if (CMD_ARGC < 7)
|
if (CMD_ARGC < 7)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
info = malloc(sizeof(struct jtagspi_flash_bank));
|
unsigned int ir = 0;
|
||||||
|
struct pld_device *device = NULL;
|
||||||
|
if (strcmp(CMD_ARGV[6], "-pld") == 0) {
|
||||||
|
if (CMD_ARGC < 8)
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
device = get_pld_device_by_name_or_numstr(CMD_ARGV[7]);
|
||||||
|
if (device) {
|
||||||
|
bool has_jtagspi_instruction = false;
|
||||||
|
int retval = pld_has_jtagspi_instruction(device, &has_jtagspi_instruction);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
if (!has_jtagspi_instruction) {
|
||||||
|
retval = pld_get_jtagspi_userircode(device, &ir);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
device = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("pld device '#%s' is out of bounds or unknown", CMD_ARGV[7]);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct jtagspi_flash_bank *info = calloc(1, sizeof(struct jtagspi_flash_bank));
|
||||||
if (!info) {
|
if (!info) {
|
||||||
LOG_ERROR("no memory for flash bank info");
|
LOG_ERROR("no memory for flash bank info");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -47,18 +73,19 @@ FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
|
||||||
}
|
}
|
||||||
info->tap = bank->target->tap;
|
info->tap = bank->target->tap;
|
||||||
info->probed = false;
|
info->probed = false;
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
|
|
||||||
|
info->ir = ir;
|
||||||
|
info->pld_device = device;
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void jtagspi_set_ir(struct flash_bank *bank)
|
static void jtagspi_set_user_ir(struct jtagspi_flash_bank *info)
|
||||||
{
|
{
|
||||||
struct jtagspi_flash_bank *info = bank->driver_priv;
|
|
||||||
struct scan_field field;
|
struct scan_field field;
|
||||||
uint8_t buf[4] = { 0 };
|
uint8_t buf[4] = { 0 };
|
||||||
|
|
||||||
LOG_DEBUG("loading jtagspi ir");
|
LOG_DEBUG("loading jtagspi ir(0x%" PRIx32 ")", info->ir);
|
||||||
buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
|
buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
|
||||||
field.num_bits = info->tap->ir_length;
|
field.num_bits = info->tap->ir_length;
|
||||||
field.out_value = buf;
|
field.out_value = buf;
|
||||||
|
@ -79,6 +106,7 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
assert(data_buffer || data_len == 0);
|
assert(data_buffer || data_len == 0);
|
||||||
|
|
||||||
struct scan_field fields[6];
|
struct scan_field fields[6];
|
||||||
|
struct jtagspi_flash_bank *info = bank->driver_priv;
|
||||||
|
|
||||||
LOG_DEBUG("cmd=0x%02x write_len=%d data_len=%d", cmd, write_len, data_len);
|
LOG_DEBUG("cmd=0x%02x write_len=%d data_len=%d", cmd, write_len, data_len);
|
||||||
|
|
||||||
|
@ -87,22 +115,34 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
if (is_read)
|
if (is_read)
|
||||||
data_len = -data_len;
|
data_len = -data_len;
|
||||||
|
|
||||||
|
unsigned int facing_read_bits = 0;
|
||||||
|
unsigned int trailing_write_bits = 0;
|
||||||
|
|
||||||
|
if (info->pld_device) {
|
||||||
|
int retval = pld_get_jtagspi_stuff_bits(info->pld_device, &facing_read_bits, &trailing_write_bits);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
const uint8_t marker = 1;
|
const uint8_t marker = 1;
|
||||||
fields[n].num_bits = 1;
|
|
||||||
fields[n].out_value = ▮
|
|
||||||
fields[n].in_value = NULL;
|
|
||||||
n++;
|
|
||||||
|
|
||||||
/* transfer length = cmd + address + read/write,
|
|
||||||
* -1 due to the counter implementation */
|
|
||||||
uint8_t xfer_bits[4];
|
uint8_t xfer_bits[4];
|
||||||
h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1);
|
if (!info->pld_device) { /* mode == JTAGSPI_MODE_PROXY_BITSTREAM */
|
||||||
flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits));
|
facing_read_bits = jtag_tap_count_enabled();
|
||||||
fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT;
|
fields[n].num_bits = 1;
|
||||||
fields[n].out_value = xfer_bits;
|
fields[n].out_value = ▮
|
||||||
fields[n].in_value = NULL;
|
fields[n].in_value = NULL;
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
|
/* transfer length = cmd + address + read/write,
|
||||||
|
* -1 due to the counter implementation */
|
||||||
|
h_u32_to_be(xfer_bits, ((sizeof(cmd) + write_len + data_len) * CHAR_BIT) - 1);
|
||||||
|
flip_u8(xfer_bits, xfer_bits, sizeof(xfer_bits));
|
||||||
|
fields[n].num_bits = sizeof(xfer_bits) * CHAR_BIT;
|
||||||
|
fields[n].out_value = xfer_bits;
|
||||||
|
fields[n].in_value = NULL;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
flip_u8(&cmd, &cmd, sizeof(cmd));
|
flip_u8(&cmd, &cmd, sizeof(cmd));
|
||||||
fields[n].num_bits = sizeof(cmd) * CHAR_BIT;
|
fields[n].num_bits = sizeof(cmd) * CHAR_BIT;
|
||||||
|
@ -120,10 +160,12 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
|
|
||||||
if (data_len > 0) {
|
if (data_len > 0) {
|
||||||
if (is_read) {
|
if (is_read) {
|
||||||
fields[n].num_bits = jtag_tap_count_enabled();
|
if (facing_read_bits) {
|
||||||
fields[n].out_value = NULL;
|
fields[n].num_bits = facing_read_bits;
|
||||||
fields[n].in_value = NULL;
|
fields[n].out_value = NULL;
|
||||||
n++;
|
fields[n].in_value = NULL;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
fields[n].out_value = NULL;
|
fields[n].out_value = NULL;
|
||||||
fields[n].in_value = data_buffer;
|
fields[n].in_value = data_buffer;
|
||||||
|
@ -135,16 +177,33 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
|
||||||
fields[n].num_bits = data_len * CHAR_BIT;
|
fields[n].num_bits = data_len * CHAR_BIT;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
if (!is_read && trailing_write_bits) {
|
||||||
|
fields[n].num_bits = trailing_write_bits;
|
||||||
|
fields[n].out_value = NULL;
|
||||||
|
fields[n].in_value = NULL;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->pld_device) {
|
||||||
|
int retval = pld_connect_spi_to_jtag(info->pld_device);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
} else {
|
||||||
|
jtagspi_set_user_ir(info);
|
||||||
|
}
|
||||||
|
|
||||||
jtagspi_set_ir(bank);
|
|
||||||
/* passing from an IR scan to SHIFT-DR clears BYPASS registers */
|
/* passing from an IR scan to SHIFT-DR clears BYPASS registers */
|
||||||
struct jtagspi_flash_bank *info = bank->driver_priv;
|
|
||||||
jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
|
jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
|
||||||
int retval = jtag_execute_queue();
|
int retval = jtag_execute_queue();
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
if (is_read)
|
if (is_read)
|
||||||
flip_u8(data_buffer, data_buffer, data_len);
|
flip_u8(data_buffer, data_buffer, data_len);
|
||||||
return retval;
|
|
||||||
|
if (info->pld_device)
|
||||||
|
return pld_disconnect_spi_from_jtag(info->pld_device);
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(jtagspi_handle_set)
|
COMMAND_HANDLER(jtagspi_handle_set)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 2020 by Nuvoton Technology Corporation
|
* Copyright (C) 2020 by Nuvoton Technology Corporation
|
||||||
* Mulin Chao <mlchao@nuvoton.com>
|
* Mulin Chao <mlchao@nuvoton.com>
|
||||||
* Wealian Liao <WHLIAO@nuvoton.com>
|
* Wealian Liao <WHLIAO@nuvoton.com>
|
||||||
|
* Luca Hung <YCHUNG0@nuvoton.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
|
@ -22,7 +23,6 @@ static const uint8_t npcx_algo[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NPCX_FLASH_TIMEOUT_MS 8000
|
#define NPCX_FLASH_TIMEOUT_MS 8000
|
||||||
#define NPCX_FLASH_BASE_ADDR 0x64000000
|
|
||||||
|
|
||||||
/* flash list */
|
/* flash list */
|
||||||
enum npcx_flash_device_index {
|
enum npcx_flash_device_index {
|
||||||
|
@ -33,7 +33,6 @@ enum npcx_flash_device_index {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct npcx_flash_bank {
|
struct npcx_flash_bank {
|
||||||
const char *family_name;
|
|
||||||
uint32_t sector_length;
|
uint32_t sector_length;
|
||||||
bool probed;
|
bool probed;
|
||||||
enum npcx_flash_device_index flash;
|
enum npcx_flash_device_index flash;
|
||||||
|
@ -44,6 +43,7 @@ struct npcx_flash_bank {
|
||||||
uint32_t algo_working_size;
|
uint32_t algo_working_size;
|
||||||
uint32_t buffer_addr;
|
uint32_t buffer_addr;
|
||||||
uint32_t params_addr;
|
uint32_t params_addr;
|
||||||
|
uint32_t fiu_ver;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct npcx_flash_info {
|
struct npcx_flash_info {
|
||||||
|
@ -90,7 +90,7 @@ static int npcx_init(struct flash_bank *bank)
|
||||||
|
|
||||||
/* Confirm the defined working address is the area we need to use */
|
/* Confirm the defined working address is the area we need to use */
|
||||||
if (npcx_bank->working_area->address != NPCX_FLASH_LOADER_WORKING_ADDR) {
|
if (npcx_bank->working_area->address != NPCX_FLASH_LOADER_WORKING_ADDR) {
|
||||||
LOG_ERROR("%s: Invalid working address", npcx_bank->family_name);
|
LOG_TARGET_ERROR(target, "Invalid working address");
|
||||||
LOG_INFO("Hint: Use '-work-area-phys 0x%" PRIx32 "' in your target configuration",
|
LOG_INFO("Hint: Use '-work-area-phys 0x%" PRIx32 "' in your target configuration",
|
||||||
NPCX_FLASH_LOADER_WORKING_ADDR);
|
NPCX_FLASH_LOADER_WORKING_ADDR);
|
||||||
target_free_working_area(target, npcx_bank->working_area);
|
target_free_working_area(target, npcx_bank->working_area);
|
||||||
|
@ -102,8 +102,7 @@ static int npcx_init(struct flash_bank *bank)
|
||||||
retval = target_write_buffer(target, NPCX_FLASH_LOADER_PROGRAM_ADDR,
|
retval = target_write_buffer(target, NPCX_FLASH_LOADER_PROGRAM_ADDR,
|
||||||
npcx_bank->algo_size, npcx_bank->algo_code);
|
npcx_bank->algo_size, npcx_bank->algo_code);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("%s: Failed to load flash helper algorithm",
|
LOG_TARGET_ERROR(target, "Failed to load flash helper algorithm");
|
||||||
npcx_bank->family_name);
|
|
||||||
target_free_working_area(target, npcx_bank->working_area);
|
target_free_working_area(target, npcx_bank->working_area);
|
||||||
npcx_bank->working_area = NULL;
|
npcx_bank->working_area = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -118,8 +117,7 @@ static int npcx_init(struct flash_bank *bank)
|
||||||
NPCX_FLASH_LOADER_PROGRAM_ADDR, 0,
|
NPCX_FLASH_LOADER_PROGRAM_ADDR, 0,
|
||||||
&npcx_bank->armv7m_info);
|
&npcx_bank->armv7m_info);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("%s: Failed to start flash helper algorithm",
|
LOG_TARGET_ERROR(target, "Failed to start flash helper algorithm");
|
||||||
npcx_bank->family_name);
|
|
||||||
target_free_working_area(target, npcx_bank->working_area);
|
target_free_working_area(target, npcx_bank->working_area);
|
||||||
npcx_bank->working_area = NULL;
|
npcx_bank->working_area = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -154,7 +152,6 @@ static int npcx_quit(struct flash_bank *bank)
|
||||||
static int npcx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
|
static int npcx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
|
||||||
{
|
{
|
||||||
struct target *target = bank->target;
|
struct target *target = bank->target;
|
||||||
struct npcx_flash_bank *npcx_bank = bank->driver_priv;
|
|
||||||
uint32_t status_addr = params_addr + offsetof(struct npcx_flash_params, sync);
|
uint32_t status_addr = params_addr + offsetof(struct npcx_flash_params, sync);
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
int64_t start_ms = timeval_ms();
|
int64_t start_ms = timeval_ms();
|
||||||
|
@ -172,9 +169,7 @@ static int npcx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
|
||||||
} while (status == NPCX_FLASH_LOADER_EXECUTE);
|
} while (status == NPCX_FLASH_LOADER_EXECUTE);
|
||||||
|
|
||||||
if (status != NPCX_FLASH_LOADER_WAIT) {
|
if (status != NPCX_FLASH_LOADER_WAIT) {
|
||||||
LOG_ERROR("%s: Flash operation failed, status=0x%" PRIx32,
|
LOG_TARGET_ERROR(target, "Flash operation failed, status (%0x" PRIX32 ") ", status);
|
||||||
npcx_bank->family_name,
|
|
||||||
status);
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +192,7 @@ static enum npcx_flash_device_index npcx_get_flash_id(struct flash_bank *bank, u
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Set up algorithm parameters for get flash ID command */
|
/* Set up algorithm parameters for get flash ID command */
|
||||||
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_GET_FLASH_ID);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_GET_FLASH_ID);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT);
|
||||||
|
|
||||||
|
@ -250,6 +246,7 @@ static int npcx_probe(struct flash_bank *bank)
|
||||||
npcx_bank->buffer_addr = NPCX_FLASH_LOADER_BUFFER_ADDR;
|
npcx_bank->buffer_addr = NPCX_FLASH_LOADER_BUFFER_ADDR;
|
||||||
npcx_bank->params_addr = NPCX_FLASH_LOADER_PARAMS_ADDR;
|
npcx_bank->params_addr = NPCX_FLASH_LOADER_PARAMS_ADDR;
|
||||||
|
|
||||||
|
|
||||||
int retval = npcx_get_flash_id(bank, &flash_id);
|
int retval = npcx_get_flash_id(bank, &flash_id);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -264,7 +261,6 @@ static int npcx_probe(struct flash_bank *bank)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bank->base = NPCX_FLASH_BASE_ADDR;
|
|
||||||
bank->num_sectors = num_sectors;
|
bank->num_sectors = num_sectors;
|
||||||
bank->size = num_sectors * sector_length;
|
bank->size = num_sectors * sector_length;
|
||||||
bank->write_start_alignment = 0;
|
bank->write_start_alignment = 0;
|
||||||
|
@ -300,7 +296,7 @@ FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command)
|
||||||
{
|
{
|
||||||
struct npcx_flash_bank *npcx_bank;
|
struct npcx_flash_bank *npcx_bank;
|
||||||
|
|
||||||
if (CMD_ARGC < 6)
|
if (CMD_ARGC < 6 || CMD_ARGC > 7)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
npcx_bank = calloc(1, sizeof(struct npcx_flash_bank));
|
npcx_bank = calloc(1, sizeof(struct npcx_flash_bank));
|
||||||
|
@ -309,13 +305,32 @@ FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *fiu;
|
||||||
|
if (CMD_ARGC == 6) {
|
||||||
|
LOG_WARNING("No FIU is selection, using default.");
|
||||||
|
npcx_bank->fiu_ver = NPCX_FIU_NPCX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CMD_ARGC == 7) {
|
||||||
|
fiu = CMD_ARGV[6];
|
||||||
|
if (strcmp(fiu, "npcx.fiu") == 0) {
|
||||||
|
npcx_bank->fiu_ver = NPCX_FIU_NPCX;
|
||||||
|
} else if (strcmp(fiu, "npcx_v2.fiu") == 0) {
|
||||||
|
npcx_bank->fiu_ver = NPCX_FIU_NPCX_V2;
|
||||||
|
} else if (strcmp(fiu, "npck.fiu") == 0) {
|
||||||
|
npcx_bank->fiu_ver = NPCX_FIU_NPCK;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("%s is not a valid fiu", fiu);
|
||||||
|
free(npcx_bank);
|
||||||
|
return ERROR_TARGET_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize private flash information */
|
/* Initialize private flash information */
|
||||||
npcx_bank->family_name = "npcx";
|
|
||||||
npcx_bank->sector_length = NPCX_FLASH_ERASE_SIZE;
|
npcx_bank->sector_length = NPCX_FLASH_ERASE_SIZE;
|
||||||
|
|
||||||
/* Finish initialization of bank */
|
/* Finish initialization of bank */
|
||||||
bank->driver_priv = npcx_bank;
|
bank->driver_priv = npcx_bank;
|
||||||
bank->next = NULL;
|
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
@ -341,6 +356,7 @@ static int npcx_chip_erase(struct flash_bank *bank)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Set up algorithm parameters for chip erase command */
|
/* Set up algorithm parameters for chip erase command */
|
||||||
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_ALL);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_ALL);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT);
|
||||||
|
|
||||||
|
@ -397,6 +413,7 @@ static int npcx_erase(struct flash_bank *bank, unsigned int first,
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* Set up algorithm parameters for erase command */
|
/* Set up algorithm parameters for erase command */
|
||||||
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.len, length);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.len, length);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_SECTORS);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.cmd, NPCX_FLASH_CMD_ERASE_SECTORS);
|
||||||
|
@ -464,6 +481,7 @@ static int npcx_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update algo parameters for flash write */
|
/* Update algo parameters for flash write */
|
||||||
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.fiu_ver, npcx_bank->fiu_ver);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.addr, address);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.len, size);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.len, size);
|
||||||
target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT);
|
target_buffer_set_u32(target, (uint8_t *)&algo_params.sync, NPCX_FLASH_LOADER_WAIT);
|
||||||
|
@ -502,7 +520,7 @@ static int npcx_info(struct flash_bank *bank, struct command_invocation *cmd)
|
||||||
struct npcx_flash_bank *npcx_bank = bank->driver_priv;
|
struct npcx_flash_bank *npcx_bank = bank->driver_priv;
|
||||||
|
|
||||||
command_print_sameline(cmd, "%s flash: %s\n",
|
command_print_sameline(cmd, "%s flash: %s\n",
|
||||||
npcx_bank->family_name,
|
target_name(bank->target),
|
||||||
flash_info[npcx_bank->flash].name);
|
flash_info[npcx_bank->flash].name);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -57,6 +57,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* STM32WBxxx series for reference.
|
/* STM32WBxxx series for reference.
|
||||||
|
*
|
||||||
|
* RM0493 (STM32WBA52x)
|
||||||
|
* http://www.st.com/resource/en/reference_manual/dm00821869.pdf
|
||||||
*
|
*
|
||||||
* RM0434 (STM32WB55/WB35x)
|
* RM0434 (STM32WB55/WB35x)
|
||||||
* http://www.st.com/resource/en/reference_manual/dm00318631.pdf
|
* http://www.st.com/resource/en/reference_manual/dm00318631.pdf
|
||||||
|
@ -346,6 +349,10 @@ static const struct stm32l4_rev stm32u57_u58xx_revs[] = {
|
||||||
{ 0x2001, "X" }, { 0x3000, "C" },
|
{ 0x2001, "X" }, { 0x3000, "C" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct stm32l4_rev stm32wba5x_revs[] = {
|
||||||
|
{ 0x1000, "A" },
|
||||||
|
};
|
||||||
|
|
||||||
static const struct stm32l4_rev stm32wb1xx_revs[] = {
|
static const struct stm32l4_rev stm32wb1xx_revs[] = {
|
||||||
{ 0x1000, "A" }, { 0x2000, "B" },
|
{ 0x1000, "A" }, { 0x2000, "B" },
|
||||||
};
|
};
|
||||||
|
@ -579,6 +586,18 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
|
||||||
.otp_base = 0x0BFA0000,
|
.otp_base = 0x0BFA0000,
|
||||||
.otp_size = 512,
|
.otp_size = 512,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.id = DEVID_STM32WBA5X,
|
||||||
|
.revs = stm32wba5x_revs,
|
||||||
|
.num_revs = ARRAY_SIZE(stm32wba5x_revs),
|
||||||
|
.device_str = "STM32WBA5x",
|
||||||
|
.max_flash_size_kb = 1024,
|
||||||
|
.flags = F_QUAD_WORD_PROG | F_HAS_TZ | F_HAS_L5_FLASH_REGS,
|
||||||
|
.flash_regs_base = 0x40022000,
|
||||||
|
.fsize_addr = 0x0FF907A0,
|
||||||
|
.otp_base = 0x0FF90000,
|
||||||
|
.otp_size = 512,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.id = DEVID_STM32WB1XX,
|
.id = DEVID_STM32WB1XX,
|
||||||
.revs = stm32wb1xx_revs,
|
.revs = stm32wb1xx_revs,
|
||||||
|
@ -1993,6 +2012,12 @@ static int stm32l4_probe(struct flash_bank *bank)
|
||||||
stm32l4_info->bank1_sectors = num_pages / 2;
|
stm32l4_info->bank1_sectors = num_pages / 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DEVID_STM32WBA5X:
|
||||||
|
/* single bank flash */
|
||||||
|
page_size_kb = 8;
|
||||||
|
num_pages = flash_size_kb / page_size_kb;
|
||||||
|
stm32l4_info->bank1_sectors = num_pages;
|
||||||
|
break;
|
||||||
case DEVID_STM32WB5XX:
|
case DEVID_STM32WB5XX:
|
||||||
case DEVID_STM32WB3XX:
|
case DEVID_STM32WB3XX:
|
||||||
/* single bank flash */
|
/* single bank flash */
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
#define DEVID_STM32L55_L56XX 0x472
|
#define DEVID_STM32L55_L56XX 0x472
|
||||||
#define DEVID_STM32G49_G4AXX 0x479
|
#define DEVID_STM32G49_G4AXX 0x479
|
||||||
#define DEVID_STM32U57_U58XX 0x482
|
#define DEVID_STM32U57_U58XX 0x482
|
||||||
|
#define DEVID_STM32WBA5X 0x492
|
||||||
#define DEVID_STM32WB1XX 0x494
|
#define DEVID_STM32WB1XX 0x494
|
||||||
#define DEVID_STM32WB5XX 0x495
|
#define DEVID_STM32WB5XX 0x495
|
||||||
#define DEVID_STM32WB3XX 0x496
|
#define DEVID_STM32WB3XX 0x496
|
||||||
|
|
|
@ -161,6 +161,9 @@ endif
|
||||||
if RSHIM
|
if RSHIM
|
||||||
DRIVERFILES += %D%/rshim.c
|
DRIVERFILES += %D%/rshim.c
|
||||||
endif
|
endif
|
||||||
|
if DMEM
|
||||||
|
DRIVERFILES += %D%/dmem.c
|
||||||
|
endif
|
||||||
if OSBDM
|
if OSBDM
|
||||||
DRIVERFILES += %D%/osbdm.c
|
DRIVERFILES += %D%/osbdm.c
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -184,7 +184,8 @@ static void initialize_gpio(enum adapter_gpio_config_index idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Direction for non push-pull is already set by set_gpio_value() */
|
/* 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)
|
||||||
AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[idx]);
|
AM335XGPIO_SET_OUTPUT(&adapter_gpio_config[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,10 @@
|
||||||
|
|
||||||
/** USB Product ID of ANGIE device in unconfigured state (no firmware loaded
|
/** USB Product ID of ANGIE device in unconfigured state (no firmware loaded
|
||||||
* yet) or with its firmware. */
|
* yet) or with its firmware. */
|
||||||
#define ANGIE_PID 0x424e
|
#define ANGIE_PID 0x424e
|
||||||
#define ANGIE_PID_2 0x4a55
|
#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
|
/** Address of EZ-USB ANGIE CPU Control & Status register. This register can be
|
||||||
* written by issuing a Control EP0 vendor request. */
|
* 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)
|
static int angie_usb_open(struct angie *device)
|
||||||
{
|
{
|
||||||
struct libusb_device_handle *usb_device_handle;
|
struct libusb_device_handle *usb_device_handle;
|
||||||
const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, 0};
|
const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0};
|
||||||
const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, 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);
|
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;
|
high |= SIGNAL_SRST;
|
||||||
|
|
||||||
int ret = angie_append_set_signals_cmd(device, low, high);
|
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);
|
ret = angie_execute_queued_commands(device, LIBUSB_TIMEOUT_MS);
|
||||||
if (ret == ERROR_OK)
|
if (ret == ERROR_OK)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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() */
|
/* 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);
|
OUT_GPIO(adapter_gpio_config[idx].gpio_num);
|
||||||
bcm2835_gpio_synchronize();
|
bcm2835_gpio_synchronize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <sys/mman.h>
|
||||||
|
|
||||||
|
#include <helper/align.h>
|
||||||
|
#include <helper/types.h>
|
||||||
|
#include <helper/system.h>
|
||||||
|
#include <helper/time_support.h>
|
||||||
|
#include <helper/list.h>
|
||||||
|
#include <jtag/interface.h>
|
||||||
|
|
||||||
|
#include <target/arm_adi_v5.h>
|
||||||
|
#include <transport/transport.h>
|
||||||
|
|
||||||
|
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,
|
||||||
|
};
|
|
@ -254,8 +254,8 @@ static int rshim_dp_q_write(struct adiv5_dap *dap, unsigned int reg,
|
||||||
dp_ctrl_stat = data;
|
dp_ctrl_stat = data;
|
||||||
break;
|
break;
|
||||||
case DP_SELECT:
|
case DP_SELECT:
|
||||||
ap_sel = (data & DP_SELECT_APSEL) >> 24;
|
ap_sel = (data & ADIV5_DP_SELECT_APSEL) >> 24;
|
||||||
ap_bank = (data & DP_SELECT_APBANK) >> 4;
|
ap_bank = (data & ADIV5_DP_SELECT_APBANK) >> 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_INFO("Unknown command");
|
LOG_INFO("Unknown command");
|
||||||
|
|
|
@ -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_DEBUG_PORT_ACCESS 0xffff
|
||||||
|
|
||||||
#define STLINK_TRACE_SIZE 4096
|
#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_TRACE_MAX_HZ 24000000
|
||||||
|
|
||||||
#define STLINK_V3_MAX_FREQ_NB 10
|
#define STLINK_V3_MAX_FREQ_NB 10
|
||||||
|
|
|
@ -1098,9 +1098,9 @@ static int vdebug_dap_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, ui
|
||||||
|
|
||||||
static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data)
|
static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data)
|
||||||
{
|
{
|
||||||
if ((reg & DP_SELECT_APBANK) != ap->dap->select) {
|
if ((reg & ADIV5_DP_SELECT_APBANK) != ap->dap->select) {
|
||||||
vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0);
|
vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & ADIV5_DP_SELECT_APBANK, VD_ASPACE_DP, 0);
|
||||||
ap->dap->select = reg & DP_SELECT_APBANK;
|
ap->dap->select = reg & ADIV5_DP_SELECT_APBANK;
|
||||||
}
|
}
|
||||||
|
|
||||||
vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0);
|
vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0);
|
||||||
|
@ -1110,9 +1110,9 @@ static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint3
|
||||||
|
|
||||||
static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data)
|
static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data)
|
||||||
{
|
{
|
||||||
if ((reg & DP_SELECT_APBANK) != ap->dap->select) {
|
if ((reg & ADIV5_DP_SELECT_APBANK) != ap->dap->select) {
|
||||||
vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0);
|
vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & ADIV5_DP_SELECT_APBANK, VD_ASPACE_DP, 0);
|
||||||
ap->dap->select = reg & DP_SELECT_APBANK;
|
ap->dap->select = reg & ADIV5_DP_SELECT_APBANK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0);
|
return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0);
|
||||||
|
|
|
@ -370,6 +370,7 @@ extern struct adapter_driver at91rm9200_adapter_driver;
|
||||||
extern struct adapter_driver bcm2835gpio_adapter_driver;
|
extern struct adapter_driver bcm2835gpio_adapter_driver;
|
||||||
extern struct adapter_driver buspirate_adapter_driver;
|
extern struct adapter_driver buspirate_adapter_driver;
|
||||||
extern struct adapter_driver cmsis_dap_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 dummy_adapter_driver;
|
||||||
extern struct adapter_driver ep93xx_adapter_driver;
|
extern struct adapter_driver ep93xx_adapter_driver;
|
||||||
extern struct adapter_driver esp_usb_adapter_driver;
|
extern struct adapter_driver esp_usb_adapter_driver;
|
||||||
|
|
|
@ -147,6 +147,9 @@ struct adapter_driver *adapter_drivers[] = {
|
||||||
#if BUILD_RSHIM == 1
|
#if BUILD_RSHIM == 1
|
||||||
&rshim_dap_adapter_driver,
|
&rshim_dap_adapter_driver,
|
||||||
#endif
|
#endif
|
||||||
|
#if BUILD_DMEM == 1
|
||||||
|
&dmem_dap_adapter_driver,
|
||||||
|
#endif
|
||||||
#if BUILD_AM335XGPIO == 1
|
#if BUILD_AM335XGPIO == 1
|
||||||
&am335xgpio_adapter_driver,
|
&am335xgpio_adapter_driver,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -231,3 +231,100 @@ int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattic
|
||||||
|
|
||||||
return lattice_certus_exit_programming_mode(tap);
|
return lattice_certus_exit_programming_mode(tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == PROGRAM_SPI)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
// erase configuration
|
||||||
|
int retval = lattice_preload(pld_device_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_certus_enable_programming(tap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_certus_erase_device(pld_device_info);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("erasing device failed");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = lattice_certus_exit_programming_mode(tap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
// connect jtag to spi pins
|
||||||
|
retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
struct scan_field field;
|
||||||
|
uint8_t buffer[2] = {0xfe, 0x68};
|
||||||
|
field.num_bits = 16;
|
||||||
|
field.out_value = buffer;
|
||||||
|
field.in_value = NULL;
|
||||||
|
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
/* Connecting it again takes way too long to do it multiple times for writing
|
||||||
|
a bitstream (ca. 0.4s each access).
|
||||||
|
We just leave it connected since SCS will not be active when not in shift_dr state.
|
||||||
|
So there is no need to change instruction, just make sure we are not in shift dr state. */
|
||||||
|
jtag_add_runtest(2, TAP_IDLE);
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
*facing_read_bits = 0;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_certus_refresh(struct lattice_pld_device *lattice_device)
|
||||||
|
{
|
||||||
|
struct jtag_tap *tap = lattice_device->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
int retval = lattice_preload(lattice_device);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
jtag_add_runtest(2, TAP_IDLE);
|
||||||
|
jtag_add_sleep(200000);
|
||||||
|
retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
jtag_add_runtest(100, TAP_IDLE);
|
||||||
|
jtag_add_sleep(1000);
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
|
@ -14,5 +14,9 @@ int lattice_certus_read_status(struct jtag_tap *tap, uint64_t *status, uint64_t
|
||||||
int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
|
int lattice_certus_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
|
||||||
int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
|
int lattice_certus_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
|
||||||
int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
int lattice_certus_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
||||||
|
int lattice_certus_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info);
|
||||||
|
int lattice_certus_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info);
|
||||||
|
int lattice_certus_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits);
|
||||||
|
int lattice_certus_refresh(struct lattice_pld_device *lattice_device);
|
||||||
|
|
||||||
#endif /* OPENOCD_PLD_CERTUS_H */
|
#endif /* OPENOCD_PLD_CERTUS_H */
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define ISC_DISABLE 0x1E
|
#define ISC_DISABLE 0x1E
|
||||||
#define LSCC_READ_STATUS 0x53
|
#define LSCC_READ_STATUS 0x53
|
||||||
#define LSCC_BITSTREAM_BURST 0x02
|
#define LSCC_BITSTREAM_BURST 0x02
|
||||||
|
#define PROGRAM_SPI 0x3A
|
||||||
|
|
||||||
#define STATUS_DONE_BIT 0x00020000
|
#define STATUS_DONE_BIT 0x00020000
|
||||||
#define STATUS_ERROR_BITS_ECP2 0x00040003
|
#define STATUS_ERROR_BITS_ECP2 0x00040003
|
||||||
|
@ -249,3 +250,68 @@ int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_
|
||||||
const uint32_t expected = STATUS_DONE_BIT;
|
const uint32_t expected = STATUS_DONE_BIT;
|
||||||
return lattice_verify_status_register_u32(lattice_device, out, expected, mask, false);
|
return lattice_verify_status_register_u32(lattice_device, out, expected, mask, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lattice_ecp2_3_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
// erase configuration
|
||||||
|
int retval = lattice_set_instr(tap, ISC_ENABLE, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = lattice_set_instr(tap, ISC_ERASE, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
retval = lattice_set_instr(tap, ISC_DISABLE, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
// connect jtag to spi pins
|
||||||
|
retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_ecp2_3_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
int retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_ecp2_3_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
*facing_read_bits = 1;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_ecp2_3_refresh(struct lattice_pld_device *lattice_device)
|
||||||
|
{
|
||||||
|
if (!lattice_device || !lattice_device->tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
int retval = lattice_set_instr(lattice_device->tap, LSCC_REFRESH, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
|
@ -15,5 +15,9 @@ int lattice_ecp2_3_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint3
|
||||||
int lattice_ecp2_3_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
|
int lattice_ecp2_3_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
|
||||||
int lattice_ecp2_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
int lattice_ecp2_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
||||||
int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
int lattice_ecp3_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
||||||
|
int lattice_ecp2_3_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info);
|
||||||
|
int lattice_ecp2_3_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info);
|
||||||
|
int lattice_ecp2_3_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits);
|
||||||
|
int lattice_ecp2_3_refresh(struct lattice_pld_device *lattice_device);
|
||||||
|
|
||||||
#endif /* OPENOCD_PLD_ECP2_3_H */
|
#endif /* OPENOCD_PLD_ECP2_3_H */
|
||||||
|
|
|
@ -205,3 +205,98 @@ int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_
|
||||||
const uint32_t mask3 = STATUS_DONE_BIT | STATUS_FAIL_FLAG;
|
const uint32_t mask3 = STATUS_DONE_BIT | STATUS_FAIL_FLAG;
|
||||||
return lattice_verify_status_register_u32(lattice_device, out, expected2, mask3, false);
|
return lattice_verify_status_register_u32(lattice_device, out, expected2, mask3, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lattice_ecp5_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == PROGRAM_SPI)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
// erase configuration
|
||||||
|
int retval = lattice_preload(pld_device_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_ecp5_enable_sram_programming(tap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_ecp5_erase_sram(tap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_ecp5_exit_programming_mode(tap);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
// connect jtag to spi pins
|
||||||
|
retval = lattice_set_instr(tap, PROGRAM_SPI, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
struct scan_field field;
|
||||||
|
uint8_t buffer[2] = {0xfe, 0x68};
|
||||||
|
field.num_bits = 16;
|
||||||
|
field.out_value = buffer;
|
||||||
|
field.in_value = NULL;
|
||||||
|
jtag_add_dr_scan(tap, 1, &field, TAP_IDLE);
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_ecp5_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
/* Connecting it again takes way too long to do it multiple times for writing
|
||||||
|
a bitstream (ca. 0.4s each access).
|
||||||
|
We just leave it connected since SCS will not be active when not in shift_dr state.
|
||||||
|
So there is no need to change instruction, just make sure we are not in shift dr state. */
|
||||||
|
jtag_add_runtest(2, TAP_IDLE);
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_ecp5_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
*facing_read_bits = 0;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lattice_ecp5_refresh(struct lattice_pld_device *lattice_device)
|
||||||
|
{
|
||||||
|
struct jtag_tap *tap = lattice_device->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
int retval = lattice_preload(lattice_device);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
retval = lattice_set_instr(tap, LSC_REFRESH, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
jtag_add_runtest(2, TAP_IDLE);
|
||||||
|
jtag_add_sleep(200000);
|
||||||
|
retval = lattice_set_instr(tap, BYPASS, TAP_IDLE);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
jtag_add_runtest(100, TAP_IDLE);
|
||||||
|
jtag_add_sleep(1000);
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
|
@ -14,5 +14,9 @@ int lattice_ecp5_read_status(struct jtag_tap *tap, uint32_t *status, uint32_t ou
|
||||||
int lattice_ecp5_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
|
int lattice_ecp5_read_usercode(struct jtag_tap *tap, uint32_t *usercode, uint32_t out);
|
||||||
int lattice_ecp5_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
|
int lattice_ecp5_write_usercode(struct lattice_pld_device *lattice_device, uint32_t usercode);
|
||||||
int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
int lattice_ecp5_load(struct lattice_pld_device *lattice_device, struct lattice_bit_file *bit_file);
|
||||||
|
int lattice_ecp5_connect_spi_to_jtag(struct lattice_pld_device *pld_device_info);
|
||||||
|
int lattice_ecp5_disconnect_spi_from_jtag(struct lattice_pld_device *pld_device_info);
|
||||||
|
int lattice_ecp5_get_facing_read_bits(struct lattice_pld_device *pld_device_info, unsigned int *facing_read_bits);
|
||||||
|
int lattice_ecp5_refresh(struct lattice_pld_device *lattice_device);
|
||||||
|
|
||||||
#endif /* OPENOCD_PLD_ECP5_H */
|
#endif /* OPENOCD_PLD_ECP5_H */
|
||||||
|
|
|
@ -249,6 +249,12 @@ static int efinix_get_ipdbg_hub(int user_num, struct pld_device *pld_device, str
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int efinix_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir)
|
||||||
|
{
|
||||||
|
*ir = USER1;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
|
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||||
|
@ -296,4 +302,5 @@ struct pld_driver efinix_pld = {
|
||||||
.pld_create_command = &efinix_pld_create_command,
|
.pld_create_command = &efinix_pld_create_command,
|
||||||
.load = &efinix_load,
|
.load = &efinix_load,
|
||||||
.get_ipdbg_hub = efinix_get_ipdbg_hub,
|
.get_ipdbg_hub = efinix_get_ipdbg_hub,
|
||||||
|
.get_jtagspi_userircode = efinix_get_jtagspi_userircode,
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include "raw_bit.h"
|
#include "raw_bit.h"
|
||||||
|
|
||||||
#define JTAG_CONFIGURE 0x06
|
#define JTAG_CONFIGURE 0x06
|
||||||
|
#define JTAG_SPI_BYPASS 0x05
|
||||||
|
#define BYPASS 0x3F
|
||||||
|
|
||||||
struct gatemate_pld_device {
|
struct gatemate_pld_device {
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
|
@ -209,6 +211,66 @@ static int gatemate_load(struct pld_device *pld_device, const char *filename)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int gatemate_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction)
|
||||||
|
{
|
||||||
|
*has_instruction = true;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gatemate_connect_spi_to_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct gatemate_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == JTAG_SPI_BYPASS)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
gatemate_set_instr(tap, JTAG_SPI_BYPASS);
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gatemate_disconnect_spi_from_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct gatemate_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
if (!pld_device_info)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct jtag_tap *tap = pld_device_info->tap;
|
||||||
|
if (!tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != JTAG_SPI_BYPASS)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
gatemate_set_instr(tap, BYPASS);
|
||||||
|
|
||||||
|
return jtag_execute_queue();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gatemate_get_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
*facing_read_bits = 1;
|
||||||
|
*trailing_write_bits = 1;
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command)
|
PLD_CREATE_COMMAND_HANDLER(gatemate_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 4)
|
if (CMD_ARGC != 4)
|
||||||
|
@ -239,4 +301,8 @@ struct pld_driver gatemate_pld = {
|
||||||
.name = "gatemate",
|
.name = "gatemate",
|
||||||
.pld_create_command = &gatemate_pld_create_command,
|
.pld_create_command = &gatemate_pld_create_command,
|
||||||
.load = &gatemate_load,
|
.load = &gatemate_load,
|
||||||
|
.has_jtagspi_instruction = gatemate_has_jtagspi_instruction,
|
||||||
|
.connect_spi_to_jtag = gatemate_connect_spi_to_jtag,
|
||||||
|
.disconnect_spi_from_jtag = gatemate_disconnect_spi_from_jtag,
|
||||||
|
.get_stuff_bits = gatemate_get_stuff_bits,
|
||||||
};
|
};
|
||||||
|
|
|
@ -543,10 +543,10 @@ static const struct command_registration gowin_exec_command_handlers[] = {
|
||||||
.help = "reading user register from FPGA",
|
.help = "reading user register from FPGA",
|
||||||
.usage = "pld_name",
|
.usage = "pld_name",
|
||||||
}, {
|
}, {
|
||||||
.name = "reload",
|
.name = "refresh",
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.handler = gowin_reload_command_handler,
|
.handler = gowin_reload_command_handler,
|
||||||
.help = "reloading bitstream from flash to SRAM",
|
.help = "reload bitstream from flash to SRAM",
|
||||||
.usage = "pld_name",
|
.usage = "pld_name",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
|
|
|
@ -362,6 +362,12 @@ static int intel_get_ipdbg_hub(int user_num, struct pld_device *pld_device, stru
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int intel_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir)
|
||||||
|
{
|
||||||
|
*ir = USER1;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(intel_set_bscan_command_handler)
|
COMMAND_HANDLER(intel_set_bscan_command_handler)
|
||||||
{
|
{
|
||||||
unsigned int boundary_scan_length;
|
unsigned int boundary_scan_length;
|
||||||
|
@ -412,7 +418,6 @@ COMMAND_HANDLER(intel_set_check_pos_command_handler)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command)
|
PLD_CREATE_COMMAND_HANDLER(intel_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||||
|
@ -498,4 +503,5 @@ struct pld_driver intel_pld = {
|
||||||
.pld_create_command = &intel_pld_create_command,
|
.pld_create_command = &intel_pld_create_command,
|
||||||
.load = &intel_load,
|
.load = &intel_load,
|
||||||
.get_ipdbg_hub = intel_get_ipdbg_hub,
|
.get_ipdbg_hub = intel_get_ipdbg_hub,
|
||||||
|
.get_jtagspi_userircode = intel_get_jtagspi_userircode,
|
||||||
};
|
};
|
||||||
|
|
|
@ -342,6 +342,76 @@ static int lattice_get_ipdbg_hub(int user_num, struct pld_device *pld_device, st
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lattice_connect_spi_to_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct lattice_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
int retval = lattice_check_device_family(pld_device_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3)
|
||||||
|
return lattice_ecp2_3_connect_spi_to_jtag(pld_device_info);
|
||||||
|
else if (pld_device_info->family == LATTICE_ECP5)
|
||||||
|
return lattice_ecp5_connect_spi_to_jtag(pld_device_info);
|
||||||
|
else if (pld_device_info->family == LATTICE_CERTUS)
|
||||||
|
return lattice_certus_connect_spi_to_jtag(pld_device_info);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lattice_disconnect_spi_from_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct lattice_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
int retval = lattice_check_device_family(pld_device_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3)
|
||||||
|
return lattice_ecp2_3_disconnect_spi_from_jtag(pld_device_info);
|
||||||
|
else if (pld_device_info->family == LATTICE_ECP5)
|
||||||
|
return lattice_ecp5_disconnect_spi_from_jtag(pld_device_info);
|
||||||
|
else if (pld_device_info->family == LATTICE_CERTUS)
|
||||||
|
return lattice_certus_disconnect_spi_from_jtag(pld_device_info);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lattice_get_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct lattice_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
int retval = lattice_check_device_family(pld_device_info);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (pld_device_info->family == LATTICE_ECP2 || pld_device_info->family == LATTICE_ECP3)
|
||||||
|
return lattice_ecp2_3_get_facing_read_bits(pld_device_info, facing_read_bits);
|
||||||
|
else if (pld_device_info->family == LATTICE_ECP5)
|
||||||
|
return lattice_ecp5_get_facing_read_bits(pld_device_info, facing_read_bits);
|
||||||
|
else if (pld_device_info->family == LATTICE_CERTUS)
|
||||||
|
return lattice_certus_get_facing_read_bits(pld_device_info, facing_read_bits);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lattice_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction)
|
||||||
|
{
|
||||||
|
*has_instruction = true;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
|
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||||
|
@ -505,6 +575,35 @@ COMMAND_HANDLER(lattice_read_status_command_handler)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMMAND_HANDLER(lattice_refresh_command_handler)
|
||||||
|
{
|
||||||
|
if (CMD_ARGC != 1)
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
|
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[0]);
|
||||||
|
if (!device) {
|
||||||
|
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[0]);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lattice_pld_device *lattice_device = device->driver_priv;
|
||||||
|
if (!lattice_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
int retval = lattice_check_device_family(lattice_device);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (lattice_device->family == LATTICE_ECP2 || lattice_device->family == LATTICE_ECP3)
|
||||||
|
return lattice_ecp2_3_refresh(lattice_device);
|
||||||
|
else if (lattice_device->family == LATTICE_ECP5)
|
||||||
|
return lattice_ecp5_refresh(lattice_device);
|
||||||
|
else if (lattice_device->family == LATTICE_CERTUS)
|
||||||
|
return lattice_certus_refresh(lattice_device);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct command_registration lattice_exec_command_handlers[] = {
|
static const struct command_registration lattice_exec_command_handlers[] = {
|
||||||
{
|
{
|
||||||
.name = "read_status",
|
.name = "read_status",
|
||||||
|
@ -530,6 +629,12 @@ static const struct command_registration lattice_exec_command_handlers[] = {
|
||||||
.handler = lattice_set_preload_command_handler,
|
.handler = lattice_set_preload_command_handler,
|
||||||
.help = "set length for preload (device specific)",
|
.help = "set length for preload (device specific)",
|
||||||
.usage = "pld_name value",
|
.usage = "pld_name value",
|
||||||
|
}, {
|
||||||
|
.name = "refresh",
|
||||||
|
.mode = COMMAND_EXEC,
|
||||||
|
.handler = lattice_refresh_command_handler,
|
||||||
|
.help = "refresh from configuration memory",
|
||||||
|
.usage = "pld_name",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
};
|
};
|
||||||
|
@ -551,4 +656,8 @@ struct pld_driver lattice_pld = {
|
||||||
.pld_create_command = &lattice_pld_create_command,
|
.pld_create_command = &lattice_pld_create_command,
|
||||||
.load = &lattice_load_command,
|
.load = &lattice_load_command,
|
||||||
.get_ipdbg_hub = lattice_get_ipdbg_hub,
|
.get_ipdbg_hub = lattice_get_ipdbg_hub,
|
||||||
|
.has_jtagspi_instruction = lattice_has_jtagspi_instruction,
|
||||||
|
.connect_spi_to_jtag = lattice_connect_spi_to_jtag,
|
||||||
|
.disconnect_spi_from_jtag = lattice_disconnect_spi_from_jtag,
|
||||||
|
.get_stuff_bits = lattice_get_stuff_bits,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,8 +10,10 @@
|
||||||
|
|
||||||
#define ISC_ERASE 0x0E
|
#define ISC_ERASE 0x0E
|
||||||
#define ISC_DISABLE 0x26
|
#define ISC_DISABLE 0x26
|
||||||
|
#define PROGRAM_SPI 0x3A
|
||||||
#define LSC_READ_STATUS 0x3C
|
#define LSC_READ_STATUS 0x3C
|
||||||
#define LSC_INIT_ADDRESS 0x46
|
#define LSC_INIT_ADDRESS 0x46
|
||||||
|
#define LSC_REFRESH 0x79
|
||||||
#define LSC_BITSTREAM_BURST 0x7A
|
#define LSC_BITSTREAM_BURST 0x7A
|
||||||
#define READ_USERCODE 0xC0
|
#define READ_USERCODE 0xC0
|
||||||
#define ISC_ENABLE 0xC6
|
#define ISC_ENABLE 0xC6
|
||||||
|
|
|
@ -69,8 +69,95 @@ struct pld_device *get_pld_device_by_name_or_numstr(const char *str)
|
||||||
return get_pld_device_by_num(dev_num);
|
return get_pld_device_by_num(dev_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @deffn {Config Command} {pld create} pld_name driver -chain-position tap_name [options]
|
|
||||||
*/
|
int pld_has_jtagspi_instruction(struct pld_device *pld_device, bool *has_instruction)
|
||||||
|
{
|
||||||
|
*has_instruction = false; /* default is using a proxy bitstream */
|
||||||
|
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->has_jtagspi_instruction)
|
||||||
|
return pld_driver->has_jtagspi_instruction(pld_device, has_instruction);
|
||||||
|
/* else, take the default (proxy bitstream) */
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->get_jtagspi_userircode)
|
||||||
|
return pld_driver->get_jtagspi_userircode(pld_device, ir);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->get_stuff_bits)
|
||||||
|
return pld_driver->get_stuff_bits(pld_device, facing_read_bits, trailing_write_bits);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_connect_spi_to_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->connect_spi_to_jtag)
|
||||||
|
return pld_driver->connect_spi_to_jtag(pld_device);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pld_disconnect_spi_from_jtag(struct pld_device *pld_device)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct pld_driver *pld_driver = pld_device->driver;
|
||||||
|
if (!pld_driver) {
|
||||||
|
LOG_ERROR("pld device has no associated driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pld_driver->disconnect_spi_from_jtag)
|
||||||
|
return pld_driver->disconnect_spi_from_jtag(pld_device);
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_pld_create_command)
|
COMMAND_HANDLER(handle_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 2)
|
if (CMD_ARGC < 2)
|
||||||
|
|
|
@ -20,12 +20,26 @@ struct pld_ipdbg_hub {
|
||||||
unsigned int user_ir_code;
|
unsigned int user_ir_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int pld_has_jtagspi_instruction(struct pld_device *device, bool *has_instruction);
|
||||||
|
int pld_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir);
|
||||||
|
|
||||||
|
int pld_get_jtagspi_stuff_bits(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits);
|
||||||
|
int pld_connect_spi_to_jtag(struct pld_device *pld_device);
|
||||||
|
int pld_disconnect_spi_from_jtag(struct pld_device *pld_device);
|
||||||
|
|
||||||
struct pld_driver {
|
struct pld_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
__PLD_CREATE_COMMAND((*pld_create_command));
|
__PLD_CREATE_COMMAND((*pld_create_command));
|
||||||
const struct command_registration *commands;
|
const struct command_registration *commands;
|
||||||
int (*load)(struct pld_device *pld_device, const char *filename);
|
int (*load)(struct pld_device *pld_device, const char *filename);
|
||||||
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
|
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
|
||||||
|
int (*has_jtagspi_instruction)(struct pld_device *device, bool *has_instruction);
|
||||||
|
int (*get_jtagspi_userircode)(struct pld_device *pld_device, unsigned int *ir);
|
||||||
|
int (*connect_spi_to_jtag)(struct pld_device *pld_device);
|
||||||
|
int (*disconnect_spi_from_jtag)(struct pld_device *pld_device);
|
||||||
|
int (*get_stuff_bits)(struct pld_device *pld_device, unsigned int *facing_read_bits,
|
||||||
|
unsigned int *trailing_write_bits);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
||||||
|
|
|
@ -265,7 +265,7 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(virtex2_handle_program_command)
|
COMMAND_HANDLER(virtex2_handle_refresh_command)
|
||||||
{
|
{
|
||||||
struct pld_device *device;
|
struct pld_device *device;
|
||||||
|
|
||||||
|
@ -326,6 +326,21 @@ static int xilinx_get_ipdbg_hub(int user_num, struct pld_device *pld_device, str
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xilinx_get_jtagspi_userircode(struct pld_device *pld_device, unsigned int *ir)
|
||||||
|
{
|
||||||
|
if (!pld_device || !pld_device->driver_priv)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
struct virtex2_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
if (pld_device_info->command_set.num_user < 1) {
|
||||||
|
LOG_ERROR("code for command 'select user1' is unknown");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ir = pld_device_info->command_set.user[0];
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
|
COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
|
if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
|
||||||
|
@ -434,10 +449,10 @@ static const struct command_registration virtex2_exec_command_handlers[] = {
|
||||||
.help = "set instructions codes used for jtag-hub",
|
.help = "set instructions codes used for jtag-hub",
|
||||||
.usage = "pld_name user1 [user2 [user3 [user4]]]",
|
.usage = "pld_name user1 [user2 [user3 [user4]]]",
|
||||||
}, {
|
}, {
|
||||||
.name = "program",
|
.name = "refresh",
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.handler = virtex2_handle_program_command,
|
.handler = virtex2_handle_refresh_command,
|
||||||
.help = "start loading of configuration (refresh)",
|
.help = "start loading of configuration (program)",
|
||||||
.usage = "pld_name",
|
.usage = "pld_name",
|
||||||
},
|
},
|
||||||
COMMAND_REGISTRATION_DONE
|
COMMAND_REGISTRATION_DONE
|
||||||
|
@ -460,4 +475,5 @@ struct pld_driver virtex2_pld = {
|
||||||
.pld_create_command = &virtex2_pld_create_command,
|
.pld_create_command = &virtex2_pld_create_command,
|
||||||
.load = &virtex2_load,
|
.load = &virtex2_load,
|
||||||
.get_ipdbg_hub = xilinx_get_ipdbg_hub,
|
.get_ipdbg_hub = xilinx_get_ipdbg_hub,
|
||||||
|
.get_jtagspi_userircode = xilinx_get_jtagspi_userircode,
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,6 +57,7 @@ enum zephyr_offsets {
|
||||||
OFFSET_T_ARCH,
|
OFFSET_T_ARCH,
|
||||||
OFFSET_T_PREEMPT_FLOAT,
|
OFFSET_T_PREEMPT_FLOAT,
|
||||||
OFFSET_T_COOP_FLOAT,
|
OFFSET_T_COOP_FLOAT,
|
||||||
|
OFFSET_T_ARM_EXC_RETURN,
|
||||||
OFFSET_MAX
|
OFFSET_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1253,6 +1253,27 @@ static void gdb_target_to_reg(struct target *target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get register value if needed and fill the buffer accordingly */
|
||||||
|
static int gdb_get_reg_value_as_str(struct target *target, char *tstr, struct reg *reg)
|
||||||
|
{
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
if (!reg->valid)
|
||||||
|
retval = reg->type->get(reg);
|
||||||
|
|
||||||
|
const unsigned int len = DIV_ROUND_UP(reg->size, 8) * 2;
|
||||||
|
switch (retval) {
|
||||||
|
case ERROR_OK:
|
||||||
|
gdb_str_to_target(target, tstr, reg);
|
||||||
|
return ERROR_OK;
|
||||||
|
case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
|
||||||
|
memset(tstr, 'x', len);
|
||||||
|
tstr[len] = '\0';
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
static int gdb_get_registers_packet(struct connection *connection,
|
static int gdb_get_registers_packet(struct connection *connection,
|
||||||
char const *packet, int packet_size)
|
char const *packet, int packet_size)
|
||||||
{
|
{
|
||||||
|
@ -1294,16 +1315,11 @@ static int gdb_get_registers_packet(struct connection *connection,
|
||||||
for (i = 0; i < reg_list_size; i++) {
|
for (i = 0; i < reg_list_size; i++) {
|
||||||
if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden)
|
if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden)
|
||||||
continue;
|
continue;
|
||||||
if (!reg_list[i]->valid) {
|
if (gdb_get_reg_value_as_str(target, reg_packet_p, reg_list[i]) != ERROR_OK) {
|
||||||
retval = reg_list[i]->type->get(reg_list[i]);
|
free(reg_packet);
|
||||||
if (retval != ERROR_OK && gdb_report_register_access_error) {
|
free(reg_list);
|
||||||
LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name);
|
return gdb_error(connection, retval);
|
||||||
free(reg_packet);
|
|
||||||
free(reg_list);
|
|
||||||
return gdb_error(connection, retval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gdb_str_to_target(target, reg_packet_p, reg_list[i]);
|
|
||||||
reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2;
|
reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,18 +1436,13 @@ static int gdb_get_register_packet(struct connection *connection,
|
||||||
return gdb_error(connection, ERROR_FAIL);
|
return gdb_error(connection, ERROR_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reg_list[reg_num]->valid) {
|
|
||||||
retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
|
|
||||||
if (retval != ERROR_OK && gdb_report_register_access_error) {
|
|
||||||
LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
|
|
||||||
free(reg_list);
|
|
||||||
return gdb_error(connection, retval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_packet = calloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1, 1); /* plus one for string termination null */
|
reg_packet = calloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1, 1); /* plus one for string termination null */
|
||||||
|
|
||||||
gdb_str_to_target(target, reg_packet, reg_list[reg_num]);
|
if (gdb_get_reg_value_as_str(target, reg_packet, reg_list[reg_num]) != ERROR_OK) {
|
||||||
|
free(reg_packet);
|
||||||
|
free(reg_list);
|
||||||
|
return gdb_error(connection, retval);
|
||||||
|
}
|
||||||
|
|
||||||
gdb_put_packet(connection, reg_packet, DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2);
|
gdb_put_packet(connection, reg_packet, DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2);
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,7 @@ ARC_SRC = \
|
||||||
%D%/image.h \
|
%D%/image.h \
|
||||||
%D%/mips32.h \
|
%D%/mips32.h \
|
||||||
%D%/mips64.h \
|
%D%/mips64.h \
|
||||||
|
%D%/mips_cpu.h \
|
||||||
%D%/mips_m4k.h \
|
%D%/mips_m4k.h \
|
||||||
%D%/mips_mips64.h \
|
%D%/mips_mips64.h \
|
||||||
%D%/mips_ejtag.h \
|
%D%/mips_ejtag.h \
|
||||||
|
|
|
@ -2047,6 +2047,11 @@ static int aarch64_write_cpu_memory_slow(struct target *target,
|
||||||
struct arm *arm = &armv8->arm;
|
struct arm *arm = &armv8->arm;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
if (size > 4 && arm->core_state != ARM_STATE_AARCH64) {
|
||||||
|
LOG_ERROR("memory write sizes greater than 4 bytes is only supported for AArch64 state");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
armv8_reg_current(arm, 1)->dirty = true;
|
armv8_reg_current(arm, 1)->dirty = true;
|
||||||
|
|
||||||
/* change DCC to normal mode if necessary */
|
/* change DCC to normal mode if necessary */
|
||||||
|
@ -2059,22 +2064,32 @@ static int aarch64_write_cpu_memory_slow(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
uint32_t data, opcode;
|
uint32_t opcode;
|
||||||
|
uint64_t data;
|
||||||
|
|
||||||
/* write the data to store into DTRRX */
|
/* write the data to store into DTRRX (and DTRTX for 64-bit) */
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
data = *buffer;
|
data = *buffer;
|
||||||
else if (size == 2)
|
else if (size == 2)
|
||||||
data = target_buffer_get_u16(target, buffer);
|
data = target_buffer_get_u16(target, buffer);
|
||||||
else
|
else if (size == 4)
|
||||||
data = target_buffer_get_u32(target, buffer);
|
data = target_buffer_get_u32(target, buffer);
|
||||||
|
else
|
||||||
|
data = target_buffer_get_u64(target, buffer);
|
||||||
|
|
||||||
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
armv8->debug_base + CPUV8_DBG_DTRRX, data);
|
armv8->debug_base + CPUV8_DBG_DTRRX, (uint32_t)data);
|
||||||
|
if (retval == ERROR_OK && size > 4)
|
||||||
|
retval = mem_ap_write_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->debug_base + CPUV8_DBG_DTRTX, (uint32_t)(data >> 32));
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (arm->core_state == ARM_STATE_AARCH64)
|
if (arm->core_state == ARM_STATE_AARCH64)
|
||||||
retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1));
|
if (size <= 4)
|
||||||
|
retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 1));
|
||||||
|
else
|
||||||
|
retval = dpm->instr_execute(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 1));
|
||||||
else
|
else
|
||||||
retval = dpm->instr_execute(dpm, ARMV4_5_MRC(14, 0, 1, 0, 5, 0));
|
retval = dpm->instr_execute(dpm, ARMV4_5_MRC(14, 0, 1, 0, 5, 0));
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
|
@ -2084,8 +2099,11 @@ static int aarch64_write_cpu_memory_slow(struct target *target,
|
||||||
opcode = armv8_opcode(armv8, ARMV8_OPC_STRB_IP);
|
opcode = armv8_opcode(armv8, ARMV8_OPC_STRB_IP);
|
||||||
else if (size == 2)
|
else if (size == 2)
|
||||||
opcode = armv8_opcode(armv8, ARMV8_OPC_STRH_IP);
|
opcode = armv8_opcode(armv8, ARMV8_OPC_STRH_IP);
|
||||||
else
|
else if (size == 4)
|
||||||
opcode = armv8_opcode(armv8, ARMV8_OPC_STRW_IP);
|
opcode = armv8_opcode(armv8, ARMV8_OPC_STRW_IP);
|
||||||
|
else
|
||||||
|
opcode = armv8_opcode(armv8, ARMV8_OPC_STRD_IP);
|
||||||
|
|
||||||
retval = dpm->instr_execute(dpm, opcode);
|
retval = dpm->instr_execute(dpm, opcode);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -2226,6 +2244,11 @@ static int aarch64_read_cpu_memory_slow(struct target *target,
|
||||||
struct arm *arm = &armv8->arm;
|
struct arm *arm = &armv8->arm;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
if (size > 4 && arm->core_state != ARM_STATE_AARCH64) {
|
||||||
|
LOG_ERROR("memory read sizes greater than 4 bytes is only supported for AArch64 state");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
armv8_reg_current(arm, 1)->dirty = true;
|
armv8_reg_current(arm, 1)->dirty = true;
|
||||||
|
|
||||||
/* change DCC to normal mode (if necessary) */
|
/* change DCC to normal mode (if necessary) */
|
||||||
|
@ -2238,36 +2261,56 @@ static int aarch64_read_cpu_memory_slow(struct target *target,
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
uint32_t opcode, data;
|
uint32_t opcode;
|
||||||
|
uint32_t lower;
|
||||||
|
uint32_t higher;
|
||||||
|
uint64_t data;
|
||||||
|
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRB_IP);
|
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRB_IP);
|
||||||
else if (size == 2)
|
else if (size == 2)
|
||||||
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRH_IP);
|
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRH_IP);
|
||||||
else
|
else if (size == 4)
|
||||||
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRW_IP);
|
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRW_IP);
|
||||||
|
else
|
||||||
|
opcode = armv8_opcode(armv8, ARMV8_OPC_LDRD_IP);
|
||||||
|
|
||||||
retval = dpm->instr_execute(dpm, opcode);
|
retval = dpm->instr_execute(dpm, opcode);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
if (arm->core_state == ARM_STATE_AARCH64)
|
if (arm->core_state == ARM_STATE_AARCH64)
|
||||||
retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1));
|
if (size <= 4)
|
||||||
|
retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 1));
|
||||||
|
else
|
||||||
|
retval = dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 1));
|
||||||
else
|
else
|
||||||
retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0));
|
retval = dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 1, 0, 5, 0));
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||||
armv8->debug_base + CPUV8_DBG_DTRTX, &data);
|
armv8->debug_base + CPUV8_DBG_DTRTX, &lower);
|
||||||
|
if (retval == ERROR_OK) {
|
||||||
|
if (size > 4)
|
||||||
|
retval = mem_ap_read_atomic_u32(armv8->debug_ap,
|
||||||
|
armv8->debug_base + CPUV8_DBG_DTRRX, &higher);
|
||||||
|
else
|
||||||
|
higher = 0;
|
||||||
|
}
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
data = (uint64_t)lower | (uint64_t)higher << 32;
|
||||||
|
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
*buffer = (uint8_t)data;
|
*buffer = (uint8_t)data;
|
||||||
else if (size == 2)
|
else if (size == 2)
|
||||||
target_buffer_set_u16(target, buffer, (uint16_t)data);
|
target_buffer_set_u16(target, buffer, (uint16_t)data);
|
||||||
|
else if (size == 4)
|
||||||
|
target_buffer_set_u32(target, buffer, (uint32_t)data);
|
||||||
else
|
else
|
||||||
target_buffer_set_u32(target, buffer, data);
|
target_buffer_set_u64(target, buffer, data);
|
||||||
|
|
||||||
/* Advance */
|
/* Advance */
|
||||||
buffer += size;
|
buffer += size;
|
||||||
|
|
|
@ -350,7 +350,7 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap,
|
||||||
{
|
{
|
||||||
uint8_t out_value_buf[4];
|
uint8_t out_value_buf[4];
|
||||||
int retval;
|
int retval;
|
||||||
uint64_t sel = (reg_addr >> 4) & 0xf;
|
uint64_t sel = (reg_addr >> 4) & DP_SELECT_DPBANK;
|
||||||
|
|
||||||
/* No need to change SELECT or RDBUFF as they are not banked */
|
/* No need to change SELECT or RDBUFF as they are not banked */
|
||||||
if (instr == JTAG_DP_DPACC && reg_addr != DP_SELECT && reg_addr != DP_RDBUFF &&
|
if (instr == JTAG_DP_DPACC && reg_addr != DP_SELECT && reg_addr != DP_RDBUFF &&
|
||||||
|
@ -775,7 +775,7 @@ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ADIv5 */
|
/* ADIv5 */
|
||||||
sel = (ap->ap_num << 24) | (reg & 0x000000F0);
|
sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK);
|
||||||
|
|
||||||
if (sel == dap->select)
|
if (sel == dap->select)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
|
@ -147,7 +147,7 @@ static int swd_queue_dp_write_inner(struct adiv5_dap *dap, unsigned int reg,
|
||||||
swd_finish_read(dap);
|
swd_finish_read(dap);
|
||||||
|
|
||||||
if (reg == DP_SELECT) {
|
if (reg == DP_SELECT) {
|
||||||
dap->select = data & (DP_SELECT_APSEL | DP_SELECT_APBANK | DP_SELECT_DPBANK);
|
dap->select = data & (ADIV5_DP_SELECT_APSEL | ADIV5_DP_SELECT_APBANK | DP_SELECT_DPBANK);
|
||||||
|
|
||||||
swd->write_reg(swd_cmd(false, false, reg), data, 0);
|
swd->write_reg(swd_cmd(false, false, reg), data, 0);
|
||||||
|
|
||||||
|
@ -523,7 +523,7 @@ static int swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ADIv5 */
|
/* ADIv5 */
|
||||||
sel = (ap->ap_num << 24) | (reg & 0x000000F0);
|
sel = (ap->ap_num << 24) | (reg & ADIV5_DP_SELECT_APBANK);
|
||||||
if (dap->select != DP_SELECT_INVALID)
|
if (dap->select != DP_SELECT_INVALID)
|
||||||
sel |= dap->select & DP_SELECT_DPBANK;
|
sel |= dap->select & DP_SELECT_DPBANK;
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ enum arm_arch {
|
||||||
/** Known ARM implementor IDs */
|
/** Known ARM implementor IDs */
|
||||||
enum arm_implementor {
|
enum arm_implementor {
|
||||||
ARM_IMPLEMENTOR_ARM = 0x41,
|
ARM_IMPLEMENTOR_ARM = 0x41,
|
||||||
|
ARM_IMPLEMENTOR_REALTEK = 0x72,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -97,16 +97,16 @@
|
||||||
|
|
||||||
#define DP_DLPIDR_PROTVSN 1u
|
#define DP_DLPIDR_PROTVSN 1u
|
||||||
|
|
||||||
#define DP_SELECT_APSEL 0xFF000000
|
#define ADIV5_DP_SELECT_APSEL 0xFF000000
|
||||||
#define DP_SELECT_APBANK 0x000000F0
|
#define ADIV5_DP_SELECT_APBANK 0x000000F0
|
||||||
#define DP_SELECT_DPBANK 0x0000000F
|
#define DP_SELECT_DPBANK 0x0000000F
|
||||||
#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
|
#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
|
||||||
|
|
||||||
#define DP_APSEL_MAX (255) /* for ADIv5 only */
|
#define DP_APSEL_MAX (255) /* Strict limit for ADIv5, number of AP buffers for ADIv6 */
|
||||||
#define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */
|
#define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */
|
||||||
|
|
||||||
#define DP_TARGETSEL_INVALID 0xFFFFFFFFU
|
#define DP_TARGETSEL_INVALID 0xFFFFFFFFU
|
||||||
#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU
|
#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU
|
||||||
#define DP_TARGETSEL_INSTANCEID_MASK 0xF0000000U
|
#define DP_TARGETSEL_INSTANCEID_MASK 0xF0000000U
|
||||||
#define DP_TARGETSEL_INSTANCEID_SHIFT 28
|
#define DP_TARGETSEL_INSTANCEID_SHIFT 28
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,11 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = {
|
||||||
[ARMV8_OPC_LDRB_IP] = ARMV8_LDRB_IP(1, 0),
|
[ARMV8_OPC_LDRB_IP] = ARMV8_LDRB_IP(1, 0),
|
||||||
[ARMV8_OPC_LDRH_IP] = ARMV8_LDRH_IP(1, 0),
|
[ARMV8_OPC_LDRH_IP] = ARMV8_LDRH_IP(1, 0),
|
||||||
[ARMV8_OPC_LDRW_IP] = ARMV8_LDRW_IP(1, 0),
|
[ARMV8_OPC_LDRW_IP] = ARMV8_LDRW_IP(1, 0),
|
||||||
|
[ARMV8_OPC_LDRD_IP] = ARMV8_LDRD_IP(1, 0),
|
||||||
[ARMV8_OPC_STRB_IP] = ARMV8_STRB_IP(1, 0),
|
[ARMV8_OPC_STRB_IP] = ARMV8_STRB_IP(1, 0),
|
||||||
[ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP(1, 0),
|
[ARMV8_OPC_STRH_IP] = ARMV8_STRH_IP(1, 0),
|
||||||
[ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP(1, 0),
|
[ARMV8_OPC_STRW_IP] = ARMV8_STRW_IP(1, 0),
|
||||||
|
[ARMV8_OPC_STRD_IP] = ARMV8_STRD_IP(1, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = {
|
static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = {
|
||||||
|
|
|
@ -155,6 +155,7 @@
|
||||||
#define ARMV8_LDRB_IP(rd, rn) (0x38401400 | (rn << 5) | rd)
|
#define ARMV8_LDRB_IP(rd, rn) (0x38401400 | (rn << 5) | rd)
|
||||||
#define ARMV8_LDRH_IP(rd, rn) (0x78402400 | (rn << 5) | rd)
|
#define ARMV8_LDRH_IP(rd, rn) (0x78402400 | (rn << 5) | rd)
|
||||||
#define ARMV8_LDRW_IP(rd, rn) (0xb8404400 | (rn << 5) | rd)
|
#define ARMV8_LDRW_IP(rd, rn) (0xb8404400 | (rn << 5) | rd)
|
||||||
|
#define ARMV8_LDRD_IP(rd, rn) (0xf8408400 | (rn << 5) | rd)
|
||||||
|
|
||||||
#define ARMV8_LDRB_IP_T3(rd, rn) (0xf8100b01 | (rn << 16) | (rd << 12))
|
#define ARMV8_LDRB_IP_T3(rd, rn) (0xf8100b01 | (rn << 16) | (rd << 12))
|
||||||
#define ARMV8_LDRH_IP_T3(rd, rn) (0xf8300b02 | (rn << 16) | (rd << 12))
|
#define ARMV8_LDRH_IP_T3(rd, rn) (0xf8300b02 | (rn << 16) | (rd << 12))
|
||||||
|
@ -163,6 +164,7 @@
|
||||||
#define ARMV8_STRB_IP(rd, rn) (0x38001400 | (rn << 5) | rd)
|
#define ARMV8_STRB_IP(rd, rn) (0x38001400 | (rn << 5) | rd)
|
||||||
#define ARMV8_STRH_IP(rd, rn) (0x78002400 | (rn << 5) | rd)
|
#define ARMV8_STRH_IP(rd, rn) (0x78002400 | (rn << 5) | rd)
|
||||||
#define ARMV8_STRW_IP(rd, rn) (0xb8004400 | (rn << 5) | rd)
|
#define ARMV8_STRW_IP(rd, rn) (0xb8004400 | (rn << 5) | rd)
|
||||||
|
#define ARMV8_STRD_IP(rd, rn) (0xf8008400 | (rn << 5) | rd)
|
||||||
|
|
||||||
#define ARMV8_STRB_IP_T3(rd, rn) (0xf8000b01 | (rn << 16) | (rd << 12))
|
#define ARMV8_STRB_IP_T3(rd, rn) (0xf8000b01 | (rn << 16) | (rd << 12))
|
||||||
#define ARMV8_STRH_IP_T3(rd, rn) (0xf8200b02 | (rn << 16) | (rd << 12))
|
#define ARMV8_STRH_IP_T3(rd, rn) (0xf8200b02 | (rn << 16) | (rd << 12))
|
||||||
|
@ -200,9 +202,11 @@ enum armv8_opcode {
|
||||||
ARMV8_OPC_STRB_IP,
|
ARMV8_OPC_STRB_IP,
|
||||||
ARMV8_OPC_STRH_IP,
|
ARMV8_OPC_STRH_IP,
|
||||||
ARMV8_OPC_STRW_IP,
|
ARMV8_OPC_STRW_IP,
|
||||||
|
ARMV8_OPC_STRD_IP,
|
||||||
ARMV8_OPC_LDRB_IP,
|
ARMV8_OPC_LDRB_IP,
|
||||||
ARMV8_OPC_LDRH_IP,
|
ARMV8_OPC_LDRH_IP,
|
||||||
ARMV8_OPC_LDRW_IP,
|
ARMV8_OPC_LDRW_IP,
|
||||||
|
ARMV8_OPC_LDRD_IP,
|
||||||
ARMV8_OPC_NUM,
|
ARMV8_OPC_NUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -278,7 +278,7 @@ int hybrid_breakpoint_add(struct target *target,
|
||||||
* that is currently unavailable, but the breakpoint also affects a target that
|
* that is currently unavailable, but the breakpoint also affects a target that
|
||||||
* is available.
|
* is available.
|
||||||
*/
|
*/
|
||||||
static void breakpoint_free(struct target *data_target, struct target *breakpoint_target,
|
static int breakpoint_free(struct target *data_target, struct target *breakpoint_target,
|
||||||
struct breakpoint *breakpoint_to_remove)
|
struct breakpoint *breakpoint_to_remove)
|
||||||
{
|
{
|
||||||
struct breakpoint *breakpoint = data_target->breakpoints;
|
struct breakpoint *breakpoint = data_target->breakpoints;
|
||||||
|
@ -293,36 +293,51 @@ static void breakpoint_free(struct target *data_target, struct target *breakpoin
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!breakpoint)
|
if (!breakpoint)
|
||||||
return;
|
return ERROR_BREAKPOINT_NOT_FOUND;
|
||||||
|
|
||||||
retval = target_remove_breakpoint(breakpoint_target, breakpoint);
|
retval = target_remove_breakpoint(breakpoint_target, breakpoint);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_TARGET_ERROR(breakpoint_target, "could not remove breakpoint #%d on this target",
|
||||||
|
breakpoint->number);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval);
|
LOG_DEBUG("free BPID: %" PRIu32 " --> %d", breakpoint->unique_id, retval);
|
||||||
(*breakpoint_p) = breakpoint->next;
|
(*breakpoint_p) = breakpoint->next;
|
||||||
free(breakpoint->orig_instr);
|
free(breakpoint->orig_instr);
|
||||||
free(breakpoint);
|
free(breakpoint);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void breakpoint_remove_all_internal(struct target *target)
|
static int breakpoint_remove_all_internal(struct target *target)
|
||||||
{
|
{
|
||||||
|
LOG_TARGET_DEBUG(target, "Delete all breakpoints");
|
||||||
|
|
||||||
struct breakpoint *breakpoint = target->breakpoints;
|
struct breakpoint *breakpoint = target->breakpoints;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
while (breakpoint) {
|
while (breakpoint) {
|
||||||
struct breakpoint *tmp = breakpoint;
|
struct breakpoint *tmp = breakpoint;
|
||||||
breakpoint = breakpoint->next;
|
breakpoint = breakpoint->next;
|
||||||
breakpoint_free(target, target, tmp);
|
int status = breakpoint_free(target, target, tmp);
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
retval = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_remove(struct target *target, target_addr_t address)
|
int breakpoint_remove(struct target *target, target_addr_t address)
|
||||||
{
|
{
|
||||||
if (!target->smp) {
|
if (!target->smp) {
|
||||||
struct breakpoint *breakpoint = breakpoint_find(target, address);
|
struct breakpoint *breakpoint = breakpoint_find(target, address);
|
||||||
if (breakpoint)
|
if (breakpoint)
|
||||||
breakpoint_free(target, target, breakpoint);
|
return breakpoint_free(target, target, breakpoint);
|
||||||
return;
|
return ERROR_BREAKPOINT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int retval = ERROR_OK;
|
||||||
unsigned int found = 0;
|
unsigned int found = 0;
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
/* Target where we found a software breakpoint. */
|
/* Target where we found a software breakpoint. */
|
||||||
|
@ -360,13 +375,15 @@ void breakpoint_remove(struct target *target, target_addr_t address)
|
||||||
software_breakpoint = breakpoint;
|
software_breakpoint = breakpoint;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
breakpoint_free(curr, curr, breakpoint);
|
int status = breakpoint_free(curr, curr, breakpoint);
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
retval = status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
|
LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address);
|
||||||
return;
|
return ERROR_BREAKPOINT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (software_breakpoint) {
|
if (software_breakpoint) {
|
||||||
|
@ -387,50 +404,59 @@ void breakpoint_remove(struct target *target, target_addr_t address)
|
||||||
/* Remove the software breakpoint through
|
/* Remove the software breakpoint through
|
||||||
* remove_target, but update the breakpoints structure
|
* remove_target, but update the breakpoints structure
|
||||||
* of software_breakpoint_target. */
|
* of software_breakpoint_target. */
|
||||||
/* TODO: If there is an error, can we try to remove the
|
int status = breakpoint_free(software_breakpoint_target, remove_target, software_breakpoint);
|
||||||
* same breakpoint from a different target? */
|
if (status != ERROR_OK)
|
||||||
breakpoint_free(software_breakpoint_target, remove_target, software_breakpoint);
|
/* TODO: If there is an error, can we try to remove the
|
||||||
|
* same breakpoint from a different target? */
|
||||||
|
retval = status;
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING("No halted target found to remove software breakpoint at "
|
LOG_WARNING("No halted target found to remove software breakpoint at "
|
||||||
TARGET_ADDR_FMT ".", address);
|
TARGET_ADDR_FMT ".", address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_remove_all(struct target *target)
|
int breakpoint_remove_all(struct target *target)
|
||||||
{
|
{
|
||||||
|
int retval = ERROR_OK;
|
||||||
if (target->smp) {
|
if (target->smp) {
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
|
|
||||||
foreach_smp_target(head, target->smp_targets) {
|
foreach_smp_target(head, target->smp_targets) {
|
||||||
struct target *curr = head->target;
|
struct target *curr = head->target;
|
||||||
breakpoint_remove_all_internal(curr);
|
int status = breakpoint_remove_all_internal(curr);
|
||||||
|
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
retval = status;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
breakpoint_remove_all_internal(target);
|
retval = breakpoint_remove_all_internal(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void breakpoint_clear_target_internal(struct target *target)
|
int breakpoint_clear_target(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Delete all breakpoints for target: %s",
|
int retval = ERROR_OK;
|
||||||
target_name(target));
|
|
||||||
while (target->breakpoints)
|
|
||||||
breakpoint_free(target, target, target->breakpoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
void breakpoint_clear_target(struct target *target)
|
|
||||||
{
|
|
||||||
if (target->smp) {
|
if (target->smp) {
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
|
|
||||||
foreach_smp_target(head, target->smp_targets) {
|
foreach_smp_target(head, target->smp_targets) {
|
||||||
struct target *curr = head->target;
|
struct target *curr = head->target;
|
||||||
breakpoint_clear_target_internal(curr);
|
int status = breakpoint_remove_all_internal(curr);
|
||||||
|
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
retval = status;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
breakpoint_clear_target_internal(target);
|
retval = breakpoint_remove_all_internal(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
|
struct breakpoint *breakpoint_find(struct target *target, target_addr_t address)
|
||||||
|
@ -536,7 +562,7 @@ int watchpoint_add(struct target *target, target_addr_t address,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
|
static int watchpoint_free(struct target *target, struct watchpoint *watchpoint_to_remove)
|
||||||
{
|
{
|
||||||
struct watchpoint *watchpoint = target->watchpoints;
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
struct watchpoint **watchpoint_p = &target->watchpoints;
|
struct watchpoint **watchpoint_p = &target->watchpoints;
|
||||||
|
@ -550,11 +576,19 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!watchpoint)
|
if (!watchpoint)
|
||||||
return;
|
return ERROR_WATCHPOINT_NOT_FOUND;
|
||||||
retval = target_remove_watchpoint(target, watchpoint);
|
retval = target_remove_watchpoint(target, watchpoint);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_TARGET_ERROR(target, "could not remove watchpoint #%d on this target",
|
||||||
|
watchpoint->number);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
|
LOG_DEBUG("free WPID: %d --> %d", watchpoint->unique_id, retval);
|
||||||
(*watchpoint_p) = watchpoint->next;
|
(*watchpoint_p) = watchpoint->next;
|
||||||
free(watchpoint);
|
free(watchpoint);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
|
static int watchpoint_remove_internal(struct target *target, target_addr_t address)
|
||||||
|
@ -568,38 +602,67 @@ static int watchpoint_remove_internal(struct target *target, target_addr_t addre
|
||||||
}
|
}
|
||||||
|
|
||||||
if (watchpoint) {
|
if (watchpoint) {
|
||||||
watchpoint_free(target, watchpoint);
|
return watchpoint_free(target, watchpoint);
|
||||||
return 1;
|
|
||||||
} else {
|
} else {
|
||||||
if (!target->smp)
|
return ERROR_WATCHPOINT_NOT_FOUND;
|
||||||
LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void watchpoint_remove(struct target *target, target_addr_t address)
|
int watchpoint_remove(struct target *target, target_addr_t address)
|
||||||
{
|
{
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
unsigned int num_found_watchpoints = 0;
|
||||||
if (target->smp) {
|
if (target->smp) {
|
||||||
unsigned int num_watchpoints = 0;
|
|
||||||
struct target_list *head;
|
struct target_list *head;
|
||||||
|
|
||||||
foreach_smp_target(head, target->smp_targets) {
|
foreach_smp_target(head, target->smp_targets) {
|
||||||
struct target *curr = head->target;
|
struct target *curr = head->target;
|
||||||
num_watchpoints += watchpoint_remove_internal(curr, address);
|
int status = watchpoint_remove_internal(curr, address);
|
||||||
|
|
||||||
|
if (status != ERROR_WATCHPOINT_NOT_FOUND) {
|
||||||
|
num_found_watchpoints++;
|
||||||
|
|
||||||
|
if (status != ERROR_OK) {
|
||||||
|
LOG_TARGET_ERROR(curr, "failed to remove watchpoint at address" TARGET_ADDR_FMT, address);
|
||||||
|
retval = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (num_watchpoints == 0)
|
|
||||||
LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " num_watchpoints", address);
|
|
||||||
} else {
|
} else {
|
||||||
watchpoint_remove_internal(target, address);
|
retval = watchpoint_remove_internal(target, address);
|
||||||
|
|
||||||
|
if (retval != ERROR_WATCHPOINT_NOT_FOUND) {
|
||||||
|
num_found_watchpoints++;
|
||||||
|
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
LOG_TARGET_ERROR(target, "failed to remove watchpoint at address" TARGET_ADDR_FMT, address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (num_found_watchpoints == 0) {
|
||||||
|
LOG_TARGET_ERROR(target, "no watchpoint at address " TARGET_ADDR_FMT " found", address);
|
||||||
|
return ERROR_WATCHPOINT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watchpoint_clear_target(struct target *target)
|
int watchpoint_clear_target(struct target *target)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Delete all watchpoints for target: %s",
|
LOG_DEBUG("Delete all watchpoints for target: %s",
|
||||||
target_name(target));
|
target_name(target));
|
||||||
while (target->watchpoints)
|
|
||||||
watchpoint_free(target, target->watchpoints);
|
struct watchpoint *watchpoint = target->watchpoints;
|
||||||
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
|
while (watchpoint) {
|
||||||
|
struct watchpoint *tmp = watchpoint;
|
||||||
|
watchpoint = watchpoint->next;
|
||||||
|
int status = watchpoint_free(target, tmp);
|
||||||
|
if (status != ERROR_OK)
|
||||||
|
retval = status;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
||||||
|
|
|
@ -50,15 +50,15 @@ struct watchpoint {
|
||||||
uint32_t unique_id;
|
uint32_t unique_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void breakpoint_clear_target(struct target *target);
|
int breakpoint_clear_target(struct target *target);
|
||||||
int breakpoint_add(struct target *target,
|
int breakpoint_add(struct target *target,
|
||||||
target_addr_t address, uint32_t length, enum breakpoint_type type);
|
target_addr_t address, uint32_t length, enum breakpoint_type type);
|
||||||
int context_breakpoint_add(struct target *target,
|
int context_breakpoint_add(struct target *target,
|
||||||
uint32_t asid, uint32_t length, enum breakpoint_type type);
|
uint32_t asid, uint32_t length, enum breakpoint_type type);
|
||||||
int hybrid_breakpoint_add(struct target *target,
|
int hybrid_breakpoint_add(struct target *target,
|
||||||
target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type);
|
target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type);
|
||||||
void breakpoint_remove(struct target *target, target_addr_t address);
|
int breakpoint_remove(struct target *target, target_addr_t address);
|
||||||
void breakpoint_remove_all(struct target *target);
|
int breakpoint_remove_all(struct target *target);
|
||||||
|
|
||||||
struct breakpoint *breakpoint_find(struct target *target, target_addr_t address);
|
struct breakpoint *breakpoint_find(struct target *target, target_addr_t address);
|
||||||
|
|
||||||
|
@ -68,11 +68,11 @@ static inline void breakpoint_hw_set(struct breakpoint *breakpoint, unsigned int
|
||||||
breakpoint->number = hw_number;
|
breakpoint->number = hw_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watchpoint_clear_target(struct target *target);
|
int watchpoint_clear_target(struct target *target);
|
||||||
int watchpoint_add(struct target *target,
|
int watchpoint_add(struct target *target,
|
||||||
target_addr_t address, uint32_t length,
|
target_addr_t address, uint32_t length,
|
||||||
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
enum watchpoint_rw rw, uint64_t value, uint64_t mask);
|
||||||
void watchpoint_remove(struct target *target, target_addr_t address);
|
int watchpoint_remove(struct target *target, target_addr_t address);
|
||||||
|
|
||||||
/* report type and address of just hit watchpoint */
|
/* report type and address of just hit watchpoint */
|
||||||
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
int watchpoint_hit(struct target *target, enum watchpoint_rw *rw,
|
||||||
|
@ -84,4 +84,7 @@ static inline void watchpoint_set(struct watchpoint *watchpoint, unsigned int nu
|
||||||
watchpoint->number = number;
|
watchpoint->number = number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ERROR_BREAKPOINT_NOT_FOUND (-1600)
|
||||||
|
#define ERROR_WATCHPOINT_NOT_FOUND (-1601)
|
||||||
|
|
||||||
#endif /* OPENOCD_TARGET_BREAKPOINTS_H */
|
#endif /* OPENOCD_TARGET_BREAKPOINTS_H */
|
||||||
|
|
|
@ -111,6 +111,17 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
|
||||||
.arch = ARM_ARCH_V8M,
|
.arch = ARM_ARCH_V8M,
|
||||||
.flags = CORTEX_M_F_HAS_FPV5,
|
.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 */
|
/* forward declarations */
|
||||||
|
@ -1948,7 +1959,8 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat
|
||||||
target_write_u32(target, comparator->dwt_comparator_address + 0,
|
target_write_u32(target, comparator->dwt_comparator_address + 0,
|
||||||
comparator->comp);
|
comparator->comp);
|
||||||
|
|
||||||
if ((cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M) {
|
if ((cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M_V2_0
|
||||||
|
&& (cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M_V2_1) {
|
||||||
uint32_t mask = 0, temp;
|
uint32_t mask = 0, temp;
|
||||||
|
|
||||||
/* watchpoint params were validated earlier */
|
/* watchpoint params were validated earlier */
|
||||||
|
|
|
@ -56,6 +56,8 @@ enum cortex_m_impl_part {
|
||||||
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
|
CORTEX_M33_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD21),
|
||||||
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
|
CORTEX_M35P_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD31),
|
||||||
CORTEX_M55_PARTNO = ARM_MAKE_CPUID(ARM_IMPLEMENTOR_ARM, 0xD22),
|
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 */
|
/* Relevant Cortex-M flags, used in struct cortex_m_part_info.flags */
|
||||||
|
@ -90,7 +92,8 @@ struct cortex_m_part_info {
|
||||||
#define DWT_FUNCTION0 0xE0001028
|
#define DWT_FUNCTION0 0xE0001028
|
||||||
#define DWT_DEVARCH 0xE0001FBC
|
#define DWT_DEVARCH 0xE0001FBC
|
||||||
|
|
||||||
#define DWT_DEVARCH_ARMV8M 0x101A02
|
#define DWT_DEVARCH_ARMV8M_V2_0 0x101A02
|
||||||
|
#define DWT_DEVARCH_ARMV8M_V2_1 0x111A02
|
||||||
|
|
||||||
#define FP_CTRL 0xE0002000
|
#define FP_CTRL 0xE0002000
|
||||||
#define FP_REMAP 0xE0002004
|
#define FP_REMAP 0xE0002004
|
||||||
|
|
|
@ -50,13 +50,16 @@ static int autodetect_image_type(struct image *image, const char *url)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
retval = fileio_read(fileio, 9, buffer, &read_bytes);
|
retval = fileio_read(fileio, 9, buffer, &read_bytes);
|
||||||
|
|
||||||
if (retval == ERROR_OK) {
|
|
||||||
if (read_bytes != 9)
|
|
||||||
retval = ERROR_FILEIO_OPERATION_FAILED;
|
|
||||||
}
|
|
||||||
fileio_close(fileio);
|
fileio_close(fileio);
|
||||||
|
|
||||||
|
/* If the file is smaller than 9 bytes, it can only be bin */
|
||||||
|
if (retval == ERROR_OK && read_bytes != 9) {
|
||||||
|
LOG_DEBUG("Less than 9 bytes in the image file found.");
|
||||||
|
LOG_DEBUG("BIN image detected.");
|
||||||
|
image->type = IMAGE_BINARY;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -82,8 +85,10 @@ static int autodetect_image_type(struct image *image, const char *url)
|
||||||
&& (buffer[1] >= '0') && (buffer[1] < '9')) {
|
&& (buffer[1] >= '0') && (buffer[1] < '9')) {
|
||||||
LOG_DEBUG("S19 image detected.");
|
LOG_DEBUG("S19 image detected.");
|
||||||
image->type = IMAGE_SRECORD;
|
image->type = IMAGE_SRECORD;
|
||||||
} else
|
} else {
|
||||||
|
LOG_DEBUG("BIN image detected.");
|
||||||
image->type = IMAGE_BINARY;
|
image->type = IMAGE_BINARY;
|
||||||
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mips32.h"
|
#include "mips32.h"
|
||||||
|
#include "mips_cpu.h"
|
||||||
#include "breakpoints.h"
|
#include "breakpoints.h"
|
||||||
#include "algorithm.h"
|
#include "algorithm.h"
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
|
@ -693,6 +694,63 @@ int mips32_enable_interrupts(struct target *target, int enable)
|
||||||
return ERROR_OK;
|
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 */
|
/* read config to config3 cp0 registers and log isa implementation */
|
||||||
int mips32_read_config_regs(struct target *target)
|
int mips32_read_config_regs(struct target *target)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#ifndef OPENOCD_TARGET_MIPS32_H
|
#ifndef OPENOCD_TARGET_MIPS32_H
|
||||||
#define OPENOCD_TARGET_MIPS32_H
|
#define OPENOCD_TARGET_MIPS32_H
|
||||||
|
|
||||||
|
#include <helper/bits.h>
|
||||||
|
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "mips32_pracc.h"
|
#include "mips32_pracc.h"
|
||||||
|
|
||||||
|
@ -55,6 +57,9 @@
|
||||||
|
|
||||||
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
|
#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 */
|
/* offsets into mips32 core register cache */
|
||||||
enum {
|
enum {
|
||||||
MIPS32_PC = 37,
|
MIPS32_PC = 37,
|
||||||
|
@ -91,6 +96,11 @@ struct mips32_common {
|
||||||
enum mips32_isa_mode isa_mode;
|
enum mips32_isa_mode isa_mode;
|
||||||
enum mips32_isa_imp isa_imp;
|
enum mips32_isa_imp isa_imp;
|
||||||
|
|
||||||
|
/* processor identification register */
|
||||||
|
uint32_t prid;
|
||||||
|
/* CPU specific quirks */
|
||||||
|
uint32_t cpu_quirks;
|
||||||
|
|
||||||
/* working area for fastdata access */
|
/* working area for fastdata access */
|
||||||
struct working_area *fast_data_area;
|
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_examine(struct target *target);
|
||||||
|
|
||||||
|
int mips32_cpu_probe(struct target *target);
|
||||||
|
|
||||||
int mips32_read_config_regs(struct target *target);
|
int mips32_read_config_regs(struct target *target);
|
||||||
|
|
||||||
int mips32_register_commands(struct command_context *cmd_ctx);
|
int mips32_register_commands(struct command_context *cmd_ctx);
|
||||||
|
|
|
@ -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 */
|
|
@ -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 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 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 */
|
/* 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 */
|
/* pic32mx workaround, false pending at low core clock */
|
||||||
jtag_add_sleep(1000);
|
jtag_add_sleep(1000);
|
||||||
|
|
|
@ -100,6 +100,8 @@ static int mips_m4k_debug_entry(struct target *target)
|
||||||
/* attempt to find halt reason */
|
/* attempt to find halt reason */
|
||||||
mips_m4k_examine_debug_reason(target);
|
mips_m4k_examine_debug_reason(target);
|
||||||
|
|
||||||
|
mips32_cpu_probe(target);
|
||||||
|
|
||||||
mips32_read_config_regs(target);
|
mips32_read_config_regs(target);
|
||||||
|
|
||||||
/* default to mips32 isa, it will be changed below if required */
|
/* default to mips32 isa, it will be changed below if required */
|
||||||
|
|
|
@ -3928,24 +3928,24 @@ static int handle_bp_command_list(struct command_invocation *cmd)
|
||||||
if (breakpoint->type == BKPT_SOFT) {
|
if (breakpoint->type == BKPT_SOFT) {
|
||||||
char *buf = buf_to_hex_str(breakpoint->orig_instr,
|
char *buf = buf_to_hex_str(breakpoint->orig_instr,
|
||||||
breakpoint->length);
|
breakpoint->length);
|
||||||
command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, 0x%s",
|
command_print(cmd, "Software breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, orig_instr=0x%s",
|
||||||
breakpoint->address,
|
breakpoint->address,
|
||||||
breakpoint->length,
|
breakpoint->length,
|
||||||
buf);
|
buf);
|
||||||
free(buf);
|
free(buf);
|
||||||
} else {
|
} else {
|
||||||
if ((breakpoint->address == 0) && (breakpoint->asid != 0))
|
if ((breakpoint->address == 0) && (breakpoint->asid != 0))
|
||||||
command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %u",
|
command_print(cmd, "Context breakpoint: asid=0x%8.8" PRIx32 ", len=0x%x, num=%u",
|
||||||
breakpoint->asid,
|
breakpoint->asid,
|
||||||
breakpoint->length, breakpoint->number);
|
breakpoint->length, breakpoint->number);
|
||||||
else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
|
else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
|
||||||
command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u",
|
command_print(cmd, "Hybrid breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, num=%u",
|
||||||
breakpoint->address,
|
breakpoint->address,
|
||||||
breakpoint->length, breakpoint->number);
|
breakpoint->length, breakpoint->number);
|
||||||
command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
|
command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
|
||||||
breakpoint->asid);
|
breakpoint->asid);
|
||||||
} else
|
} else
|
||||||
command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u",
|
command_print(cmd, "Hardware breakpoint(IVA): addr=" TARGET_ADDR_FMT ", len=0x%x, num=%u",
|
||||||
breakpoint->address,
|
breakpoint->address,
|
||||||
breakpoint->length, breakpoint->number);
|
breakpoint->length, breakpoint->number);
|
||||||
}
|
}
|
||||||
|
@ -4036,21 +4036,31 @@ COMMAND_HANDLER(handle_bp_command)
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_rbp_command)
|
COMMAND_HANDLER(handle_rbp_command)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
|
|
||||||
if (!strcmp(CMD_ARGV[0], "all")) {
|
if (!strcmp(CMD_ARGV[0], "all")) {
|
||||||
breakpoint_remove_all(target);
|
retval = breakpoint_remove_all(target);
|
||||||
|
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
command_print(CMD, "Error encountered during removal of all breakpoints.");
|
||||||
|
command_print(CMD, "Some breakpoints may have remained set.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
target_addr_t addr;
|
target_addr_t addr;
|
||||||
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
|
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
|
||||||
|
|
||||||
breakpoint_remove(target, addr);
|
retval = breakpoint_remove(target, addr);
|
||||||
|
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
command_print(CMD, "Error during removal of breakpoint at address " TARGET_ADDR_FMT, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR_OK;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(handle_wp_command)
|
COMMAND_HANDLER(handle_wp_command)
|
||||||
|
@ -4135,9 +4145,12 @@ COMMAND_HANDLER(handle_rwp_command)
|
||||||
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
|
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
|
||||||
|
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
watchpoint_remove(target, addr);
|
int retval = watchpoint_remove(target, addr);
|
||||||
|
|
||||||
return ERROR_OK;
|
if (retval != ERROR_OK)
|
||||||
|
command_print(CMD, "Error during removal of watchpoint at address " TARGET_ADDR_FMT, addr);
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,5 +16,9 @@ source [find fpga/altera-cycloneiii.cfg]
|
||||||
|
|
||||||
#quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf
|
#quartus_cpf --option=bitstream_compression=off -c output_files\cycloneiii_blinker.sof cycloneiii_blinker.rbf
|
||||||
|
|
||||||
#openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load 0 cycloneiii_blinker.rbf"
|
#openocd -f board/bemicro_cycloneiii.cfg -c "init" -c "pld load cycloneiii.pld cycloneiii_blinker.rbf"
|
||||||
# "ipdbg -start -tap cycloneiii.tap -hub 0x00e -tool 0 -port 5555"
|
# "ipdbg -start -tap cycloneiii.tap -hub 0x00e -tool 0 -port 5555"
|
||||||
|
|
||||||
|
|
||||||
|
set JTAGSPI_CHAIN_ID cycloneiii.pld
|
||||||
|
source [find cpld/jtagspi.cfg]
|
||||||
|
|
|
@ -12,3 +12,11 @@ transport select jtag
|
||||||
adapter speed 10000
|
adapter speed 10000
|
||||||
|
|
||||||
source [find fpga/lattice_certuspro.cfg]
|
source [find fpga/lattice_certuspro.cfg]
|
||||||
|
|
||||||
|
#openocd -f board/certuspro_evaluation.cfg -c "init" -c "pld load certuspro.pld shared_folder/certuspro_blinker_impl_1.bit"
|
||||||
|
|
||||||
|
set JTAGSPI_CHAIN_ID certuspro.pld
|
||||||
|
source [find cpld/jtagspi.cfg]
|
||||||
|
|
||||||
|
#jtagspi_init certuspro.pld "" -1
|
||||||
|
#jtagspi_program shared_folder/certuspro_blinker_impl1.bit 0
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# digilent CMOD S7
|
||||||
|
# https://digilent.com/reference/programmable-logic/cmod-s7/reference-manual
|
||||||
|
|
||||||
|
|
||||||
|
adapter driver ftdi
|
||||||
|
ftdi channel 0
|
||||||
|
ftdi layout_init 0x0008 0x008b
|
||||||
|
ftdi vid_pid 0x0403 0x6010
|
||||||
|
reset_config none
|
||||||
|
transport select jtag
|
||||||
|
|
||||||
|
adapter speed 10000
|
||||||
|
|
||||||
|
source [find cpld/xilinx-xc7.cfg]
|
||||||
|
|
||||||
|
# "ipdbg -start -tap xc7.tap -hub 0x02 -tool 0 -port 5555"
|
||||||
|
#openocd -f board/digilent_cmod_s7.cfg -c "init" -c "pld load xc7.pld shared_folder/cmod_s7_fast.bit"
|
||||||
|
|
||||||
|
set JTAGSPI_CHAIN_ID xc7.pld
|
||||||
|
source [find cpld/jtagspi.cfg]
|
||||||
|
|
||||||
|
#jtagspi_init xc7.pld "shared_folder/bscan_spi_xc7s25.bit" 0xab
|
||||||
|
#jtagspi_program shared_folder/cmod_s7_fast.bit 0
|
|
@ -15,5 +15,11 @@ adapter speed 6000
|
||||||
|
|
||||||
source [find fpga/lattice_ecp5.cfg]
|
source [find fpga/lattice_ecp5.cfg]
|
||||||
|
|
||||||
#openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load 0 shared_folder/ecp5_blinker_impl1.bit"
|
#openocd -f board/ecp5_evaluation.cfg -c "init" -c "pld load ecp5.pld shared_folder/ecp5_blinker_impl1.bit"
|
||||||
#ipdbg -start -tap ecp5.tap -hub 0x32 -port 5555 -tool 0
|
#ipdbg -start -tap ecp5.tap -hub 0x32 -port 5555 -tool 0
|
||||||
|
|
||||||
|
set JTAGSPI_CHAIN_ID ecp5.pld
|
||||||
|
source [find cpld/jtagspi.cfg]
|
||||||
|
|
||||||
|
#jtagspi_init ecp5.pld "" -1
|
||||||
|
#jtagspi_program shared_folder/ecp5_blinker_impl1_slow.bit 0
|
||||||
|
|
|
@ -14,3 +14,9 @@ transport select jtag
|
||||||
adapter speed 6000
|
adapter speed 6000
|
||||||
|
|
||||||
source [find fpga/gatemate.cfg]
|
source [find fpga/gatemate.cfg]
|
||||||
|
|
||||||
|
set JTAGSPI_CHAIN_ID gatemate.pld
|
||||||
|
source [find cpld/jtagspi.cfg]
|
||||||
|
|
||||||
|
#jtagspi_init gatemate.pld "" -1
|
||||||
|
#jtagspi_program workspace/blink/blink_slow.cfg.bit 0
|
||||||
|
|
|
@ -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]
|
|
@ -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
|
|
@ -0,0 +1,24 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
#
|
||||||
|
# Texas Instruments SK-AM62P: https://www.ti.com/lit/zip/sprr487
|
||||||
|
#
|
||||||
|
|
||||||
|
# AM62P SK/EVM 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 am62p
|
||||||
|
}
|
||||||
|
|
||||||
|
source [find target/ti_k3.cfg]
|
||||||
|
|
||||||
|
adapter speed 2500
|
|
@ -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]
|
|
@ -0,0 +1,25 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
# Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
#
|
||||||
|
# Texas Instruments J784S4 EVM: https://www.ti.com/tool/J784S4XEVM
|
||||||
|
# Texas Instruments SK-AM69: https://www.ti.com/tool/SK-AM69
|
||||||
|
#
|
||||||
|
|
||||||
|
# J784S4/AM69 SK/EVM 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 j784s4
|
||||||
|
}
|
||||||
|
|
||||||
|
source [find target/ti_k3.cfg]
|
||||||
|
|
||||||
|
adapter speed 2500
|
|
@ -19,6 +19,11 @@ adapter speed 6000
|
||||||
|
|
||||||
source [find fpga/efinix_trion.cfg]
|
source [find fpga/efinix_trion.cfg]
|
||||||
|
|
||||||
#openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load 0 outflow/trion_blinker.bit"
|
#openocd -f board/trion_t20_bga256.cfg -c "init" -c "pld load trion.pld outflow/trion_blinker.bit"
|
||||||
#ipdbg -start -tap trion.tap -hub 0x8 -port 5555 -tool 0
|
#ipdbg -start -tap trion.tap -hub 0x8 -port 5555 -tool 0
|
||||||
|
|
||||||
|
set JTAGSPI_CHAIN_ID trion.pld
|
||||||
|
source [find cpld/jtagspi.cfg]
|
||||||
|
|
||||||
|
#jtagspi_init trion.pld "trion_jtagspi/outflow/trion_jtagspi.bit" 0xAB
|
||||||
|
#jtagspi_program trion_blinker/outflow/trion_blinker.bin 0
|
||||||
|
|
|
@ -4,6 +4,8 @@ set _USER1 0x02
|
||||||
|
|
||||||
if { [info exists JTAGSPI_IR] } {
|
if { [info exists JTAGSPI_IR] } {
|
||||||
set _JTAGSPI_IR $JTAGSPI_IR
|
set _JTAGSPI_IR $JTAGSPI_IR
|
||||||
|
} elseif {[info exists JTAGSPI_CHAIN_ID]} {
|
||||||
|
set _JTAGSPI_CHAIN_ID $JTAGSPI_CHAIN_ID
|
||||||
} else {
|
} else {
|
||||||
set _JTAGSPI_IR $_USER1
|
set _JTAGSPI_IR $_USER1
|
||||||
}
|
}
|
||||||
|
@ -21,7 +23,11 @@ if { [info exists FLASHNAME] } {
|
||||||
}
|
}
|
||||||
|
|
||||||
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
target create $_TARGETNAME testee -chain-position $_CHIPNAME.tap
|
||||||
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
|
if { [info exists _JTAGSPI_IR] } {
|
||||||
|
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
|
||||||
|
} else {
|
||||||
|
flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME -pld $_JTAGSPI_CHAIN_ID
|
||||||
|
}
|
||||||
|
|
||||||
# initialize jtagspi flash
|
# initialize jtagspi flash
|
||||||
# chain_id: identifier of pld (you can get a list with 'pld devices')
|
# chain_id: identifier of pld (you can get a list with 'pld devices')
|
||||||
|
@ -33,7 +39,9 @@ flash bank $_FLASHNAME jtagspi 0 0 0 0 $_TARGETNAME $_JTAGSPI_IR
|
||||||
proc jtagspi_init {chain_id proxy_bit {release_from_pwr_down_cmd -1}} {
|
proc jtagspi_init {chain_id proxy_bit {release_from_pwr_down_cmd -1}} {
|
||||||
# load proxy bitstream $proxy_bit and probe spi flash
|
# load proxy bitstream $proxy_bit and probe spi flash
|
||||||
global _FLASHNAME
|
global _FLASHNAME
|
||||||
pld load $chain_id $proxy_bit
|
if { $proxy_bit ne "" } {
|
||||||
|
pld load $chain_id $proxy_bit
|
||||||
|
}
|
||||||
reset halt
|
reset halt
|
||||||
if {$release_from_pwr_down_cmd != -1} {
|
if {$release_from_pwr_down_cmd != -1} {
|
||||||
jtagspi cmd $_FLASHNAME 0 $release_from_pwr_down_cmd
|
jtagspi cmd $_FLASHNAME 0 $release_from_pwr_down_cmd
|
||||||
|
|
|
@ -173,8 +173,8 @@ proc arc_v2_init_regs { } {
|
||||||
r19 19 uint32
|
r19 19 uint32
|
||||||
r20 20 uint32
|
r20 20 uint32
|
||||||
r21 21 uint32
|
r21 21 uint32
|
||||||
r22 23 uint32
|
r22 22 uint32
|
||||||
r23 24 uint32
|
r23 23 uint32
|
||||||
r24 24 uint32
|
r24 24 uint32
|
||||||
r25 25 uint32
|
r25 25 uint32
|
||||||
gp 26 data_ptr
|
gp 26 data_ptr
|
||||||
|
|
|
@ -2,11 +2,17 @@
|
||||||
|
|
||||||
# this supports JTAG-HS2 (and apparently Nexys4 as well)
|
# this supports JTAG-HS2 (and apparently Nexys4 as well)
|
||||||
|
|
||||||
|
# ADBUS5 controls TMS tri-state buffer enable
|
||||||
|
# ACBUS6=SEL_TMS controls mux to TMS output buffer: 0=TMS 1=TDI
|
||||||
|
# ACBUS5=SEL_TDO controls mux to TDO input: 0=TDO 1=TMS
|
||||||
|
|
||||||
adapter driver ftdi
|
adapter driver ftdi
|
||||||
ftdi device_desc "Digilent Adept USB Device"
|
ftdi device_desc "Digilent Adept USB Device"
|
||||||
ftdi vid_pid 0x0403 0x6014
|
ftdi vid_pid 0x0403 0x6014
|
||||||
|
|
||||||
ftdi channel 0
|
ftdi channel 0
|
||||||
ftdi layout_init 0x00e8 0x60eb
|
ftdi layout_init 0x00e8 0x60eb
|
||||||
|
ftdi layout_signal SWD_EN -data 0x6000
|
||||||
|
ftdi layout_signal SWDIO_OE -data 0x20
|
||||||
|
|
||||||
reset_config none
|
reset_config none
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Cavium Octeon II CN61xx (PrID 0x000D9301)
|
||||||
|
|
||||||
|
jtag newtap cpu tap0 -irlen 5
|
||||||
|
jtag newtap cpu tap1 -irlen 5
|
||||||
|
|
||||||
|
target create cpu.core0 mips_mips64 -chain-position cpu.tap0 -endian big -rtos hwthread -coreid 0
|
||||||
|
target create cpu.core1 mips_mips64 -chain-position cpu.tap1 -endian big -rtos hwthread -coreid 1
|
||||||
|
target smp cpu.core0 cpu.core1
|
||||||
|
|
||||||
|
cpu.core0 configure -work-area-phys 0xffffffffa2000000 -work-area-size 0x20000
|
||||||
|
cpu.core1 configure -work-area-phys 0xffffffffa2000000 -work-area-size 0x20000
|
||||||
|
|
||||||
|
targets cpu.core0
|
|
@ -0,0 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Target: XLP304 processor by NetLogic Microsystems
|
||||||
|
#
|
||||||
|
|
||||||
|
set XLP_NT 4
|
||||||
|
source [find target/netl_xlp3xx.cfg]
|
|
@ -0,0 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Target: XLP308 processor by NetLogic Microsystems
|
||||||
|
#
|
||||||
|
|
||||||
|
set XLP_NT 8
|
||||||
|
source [find target/netl_xlp3xx.cfg]
|
|
@ -0,0 +1,7 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Target: XLP316 processor by NetLogic Microsystems
|
||||||
|
#
|
||||||
|
|
||||||
|
set XLP_NT 16
|
||||||
|
source [find target/netl_xlp3xx.cfg]
|
|
@ -0,0 +1,39 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#
|
||||||
|
# Target: XLP 300-series processors by NetLogic Microsystems
|
||||||
|
#
|
||||||
|
# See http://www.broadcom.com/products/Processors/Enterprise/XLP300-Series
|
||||||
|
#
|
||||||
|
# Use xlp304.cfg, xlp308.cfg, xlp316.cfg for particular processor model.
|
||||||
|
#
|
||||||
|
|
||||||
|
transport select jtag
|
||||||
|
|
||||||
|
global XLP_NT
|
||||||
|
|
||||||
|
for {set i $XLP_NT} {$i > 0} {incr i -1} {
|
||||||
|
jtag newtap xlp cpu_$i -irlen 5 -disable
|
||||||
|
if {$i != 1} {
|
||||||
|
jtag configure xlp.cpu_$i -event tap-enable {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jtag newtap xlp jrc -irlen 16 -expected-id 0x00011449
|
||||||
|
|
||||||
|
jtag configure xlp.cpu_1 -event tap-enable {
|
||||||
|
global XLP_NT
|
||||||
|
irscan xlp.jrc 0xe0
|
||||||
|
drscan xlp.jrc 1 1
|
||||||
|
for {set i $XLP_NT} {$i > 1} {incr i -1} {
|
||||||
|
jtag tapenable xlp.cpu_$i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc chipreset {} {
|
||||||
|
irscan xlp.jrc 0xab
|
||||||
|
drscan xlp.jrc 1 1
|
||||||
|
drscan xlp.jrc 1 0
|
||||||
|
}
|
||||||
|
|
||||||
|
jtag configure xlp.jrc -event setup "jtag tapenable xlp.cpu_1"
|
||||||
|
|
||||||
|
target create xlp.cpu_1 mips_mips64 -endian big -chain-position xlp.cpu_1
|
|
@ -9,7 +9,7 @@ source [find target/swj-dp.tcl]
|
||||||
if { [info exists CHIPNAME] } {
|
if { [info exists CHIPNAME] } {
|
||||||
set _CHIPNAME $CHIPNAME
|
set _CHIPNAME $CHIPNAME
|
||||||
} else {
|
} else {
|
||||||
set _CHIPNAME NPCX_M4
|
set _CHIPNAME npcx
|
||||||
}
|
}
|
||||||
|
|
||||||
# SWD DAP ID of Nuvoton NPCX Cortex-M4.
|
# SWD DAP ID of Nuvoton NPCX Cortex-M4.
|
||||||
|
@ -27,6 +27,12 @@ if { [info exists WORKAREASIZE] } {
|
||||||
set _WORKAREASIZE 0x8000
|
set _WORKAREASIZE 0x8000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if { [info exists FIUNAME]} {
|
||||||
|
set _FIUNAME $FIUNAME
|
||||||
|
} else {
|
||||||
|
set _FIUNAME npcx.fiu
|
||||||
|
}
|
||||||
|
|
||||||
# Debug Adapter Target Settings
|
# Debug Adapter Target Settings
|
||||||
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUDAPID
|
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUDAPID
|
||||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||||
|
@ -48,4 +54,4 @@ cortex_m reset_config sysresetreq
|
||||||
|
|
||||||
# flash configuration
|
# flash configuration
|
||||||
set _FLASHNAME $_CHIPNAME.flash
|
set _FLASHNAME $_CHIPNAME.flash
|
||||||
flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME
|
flash bank $_FLASHNAME npcx 0x64000000 0 0 0 $_TARGETNAME $_FIUNAME
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,106 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
# script for stm32wbax family
|
||||||
|
|
||||||
|
#
|
||||||
|
# stm32wba devices support both JTAG and SWD transports.
|
||||||
|
#
|
||||||
|
source [find target/swj-dp.tcl]
|
||||||
|
source [find mem_helper.tcl]
|
||||||
|
|
||||||
|
if { [info exists CHIPNAME] } {
|
||||||
|
set _CHIPNAME $CHIPNAME
|
||||||
|
} else {
|
||||||
|
set _CHIPNAME stm32wbax
|
||||||
|
}
|
||||||
|
|
||||||
|
# Work-area is a space in RAM used for flash programming
|
||||||
|
# By default use 64kB
|
||||||
|
if { [info exists WORKAREASIZE] } {
|
||||||
|
set _WORKAREASIZE $WORKAREASIZE
|
||||||
|
} else {
|
||||||
|
set _WORKAREASIZE 0x10000
|
||||||
|
}
|
||||||
|
|
||||||
|
#jtag scan chain
|
||||||
|
if { [info exists CPUTAPID] } {
|
||||||
|
set _CPUTAPID $CPUTAPID
|
||||||
|
} else {
|
||||||
|
if { [using_jtag] } {
|
||||||
|
set _CPUTAPID 0x6ba00477
|
||||||
|
} else {
|
||||||
|
# SWD IDCODE (single drop, arm)
|
||||||
|
set _CPUTAPID 0x6ba02477
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||||
|
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||||
|
|
||||||
|
if {[using_jtag]} {
|
||||||
|
jtag newtap $_CHIPNAME bs -irlen 5
|
||||||
|
}
|
||||||
|
|
||||||
|
set _TARGETNAME $_CHIPNAME.cpu
|
||||||
|
target create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap -ap-num 1
|
||||||
|
|
||||||
|
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||||
|
|
||||||
|
flash bank $_CHIPNAME.flash stm32l4x 0x08000000 0 0 0 $_TARGETNAME
|
||||||
|
flash bank $_CHIPNAME.otp stm32l4x 0x0FF90000 0 0 0 $_TARGETNAME
|
||||||
|
|
||||||
|
# Common knowledges tells JTAG speed should be <= F_CPU/6.
|
||||||
|
# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on
|
||||||
|
# the safe side.
|
||||||
|
#
|
||||||
|
# Note that there is a pretty wide band where things are
|
||||||
|
# more or less stable, see http://openocd.zylin.com/#/c/3366/
|
||||||
|
adapter speed 500
|
||||||
|
|
||||||
|
adapter srst delay 100
|
||||||
|
if {[using_jtag]} {
|
||||||
|
jtag_ntrst_delay 100
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_config srst_nogate
|
||||||
|
|
||||||
|
if {![using_hla]} {
|
||||||
|
# if srst is not fitted use SYSRESETREQ to
|
||||||
|
# perform a soft reset
|
||||||
|
cortex_m reset_config sysresetreq
|
||||||
|
}
|
||||||
|
|
||||||
|
$_TARGETNAME configure -event reset-init {
|
||||||
|
# CPU comes out of reset with HSION | HSIRDY.
|
||||||
|
# Use HSI 16 MHz clock, compliant even with VOS == 2.
|
||||||
|
# 1 WS compliant with VOS == 2 and 16 MHz.
|
||||||
|
mmw 0x40022000 0x00000001 0x0000000E ;# FLASH_ACR: Latency = 1
|
||||||
|
mmw 0x56020C00 0x00000100 0x00000000 ;# RCC_CR |= HSION
|
||||||
|
mmw 0x56020C1C 0x00000000 0x00000002 ;# RCC_CFGR1: SW=HSI16
|
||||||
|
# Boost JTAG frequency
|
||||||
|
adapter speed 4000
|
||||||
|
}
|
||||||
|
|
||||||
|
$_TARGETNAME configure -event reset-start {
|
||||||
|
# Reset clock is HSI (16 MHz)
|
||||||
|
adapter speed 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
$_TARGETNAME configure -event examine-end {
|
||||||
|
# Enable debug during low power modes (uses more power)
|
||||||
|
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
|
||||||
|
mmw 0xE0042004 0x00000006 0
|
||||||
|
|
||||||
|
# Stop watchdog counters during halt
|
||||||
|
# DBGMCU_APB1LFZR |= DBG_IWDG_STOP | DBG_WWDG_STOP
|
||||||
|
mmw 0xE0042008 0x00001800 0
|
||||||
|
}
|
||||||
|
|
||||||
|
tpiu create $_CHIPNAME.tpiu -dap $_CHIPNAME.dap -ap-num 0 -baseaddr 0xE0040000
|
||||||
|
|
||||||
|
lappend _telnet_autocomplete_skip _proc_pre_enable_$_CHIPNAME.tpiu
|
||||||
|
proc _proc_pre_enable_$_CHIPNAME.tpiu {_targetname} {
|
||||||
|
targets $_targetname
|
||||||
|
}
|
||||||
|
|
||||||
|
$_CHIPNAME.tpiu configure -event pre-enable "_proc_pre_enable_$_CHIPNAME.tpiu $_TARGETNAME"
|
|
@ -8,8 +8,18 @@
|
||||||
# Has 2 ARMV8 Cores and 6 R5 Cores and an M3
|
# Has 2 ARMV8 Cores and 6 R5 Cores and an M3
|
||||||
# * J7200: https://www.ti.com/lit/pdf/spruiu1
|
# * J7200: https://www.ti.com/lit/pdf/spruiu1
|
||||||
# Has 2 ARMV8 Cores and 4 R5 Cores and an M3
|
# 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
|
||||||
|
# * J784S4/AM69: http://www.ti.com/lit/zip/spruj52
|
||||||
|
# Has 8 ARMV8 Cores and 8 R5 Cores
|
||||||
# * AM642: https://www.ti.com/lit/pdf/spruim2
|
# * AM642: https://www.ti.com/lit/pdf/spruim2
|
||||||
# Has 2 ARMV8 Cores and 4 R5 Cores, M4F and an M3
|
# 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
|
||||||
|
# * AM62P: https://www.ti.com/lit/pdf/spruj83
|
||||||
|
# Has 4 ARMV8 Cores and 2 R5 Cores
|
||||||
#
|
#
|
||||||
|
|
||||||
source [find target/swj-dp.tcl]
|
source [find target/swj-dp.tcl]
|
||||||
|
@ -57,7 +67,6 @@ set _gp_mcu_ap_unlock_offsets {0xf0 0x60}
|
||||||
# Set configuration overrides for each SOC
|
# Set configuration overrides for each SOC
|
||||||
switch $_soc {
|
switch $_soc {
|
||||||
am654 {
|
am654 {
|
||||||
set _CHIPNAME am654
|
|
||||||
set _K3_DAP_TAPID 0x0bb5a02f
|
set _K3_DAP_TAPID 0x0bb5a02f
|
||||||
|
|
||||||
# AM654 has 2 clusters of 2 A53 cores each.
|
# AM654 has 2 clusters of 2 A53 cores each.
|
||||||
|
@ -72,7 +81,6 @@ switch $_soc {
|
||||||
set _sysctrl_ap_unlock_offsets {0xf0 0x50}
|
set _sysctrl_ap_unlock_offsets {0xf0 0x50}
|
||||||
}
|
}
|
||||||
am642 {
|
am642 {
|
||||||
set _CHIPNAME am642
|
|
||||||
set _K3_DAP_TAPID 0x0bb3802f
|
set _K3_DAP_TAPID 0x0bb3802f
|
||||||
|
|
||||||
# AM642 has 1 clusters of 2 A53 cores each.
|
# AM642 has 1 clusters of 2 A53 cores each.
|
||||||
|
@ -91,7 +99,6 @@ switch $_soc {
|
||||||
set _gp_mcu_cores 1
|
set _gp_mcu_cores 1
|
||||||
}
|
}
|
||||||
am625 {
|
am625 {
|
||||||
set _CHIPNAME am625
|
|
||||||
set _K3_DAP_TAPID 0x0bb7e02f
|
set _K3_DAP_TAPID 0x0bb7e02f
|
||||||
|
|
||||||
# AM625 has 1 clusters of 4 A53 cores.
|
# AM625 has 1 clusters of 4 A53 cores.
|
||||||
|
@ -114,9 +121,45 @@ switch $_soc {
|
||||||
# M4 processor
|
# M4 processor
|
||||||
set _gp_mcu_cores 1
|
set _gp_mcu_cores 1
|
||||||
set _gp_mcu_ap_unlock_offsets {0xf0 0x7c}
|
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
|
||||||
|
}
|
||||||
|
am62p -
|
||||||
|
am62a7 {
|
||||||
|
set _K3_DAP_TAPID 0x0bb8d02f
|
||||||
|
|
||||||
|
# AM62a7/AM62P has 1 cluster 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/AM62P has 2 cluster of 1 R5 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}
|
||||||
|
|
||||||
|
# Overrides for am62p
|
||||||
|
if { "$_soc" == "am62p" } {
|
||||||
|
set _K3_DAP_TAPID 0x0bb9d02f
|
||||||
|
set R5_NAMES {wkup0_r5.0 mcu0_r5.0}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
j721e {
|
j721e {
|
||||||
set _CHIPNAME j721e
|
|
||||||
set _K3_DAP_TAPID 0x0bb6402f
|
set _K3_DAP_TAPID 0x0bb6402f
|
||||||
# J721E has 1 cluster of 2 A72 cores.
|
# J721E has 1 cluster of 2 A72 cores.
|
||||||
set _armv8_cpu_name a72
|
set _armv8_cpu_name a72
|
||||||
|
@ -124,9 +167,18 @@ switch $_soc {
|
||||||
|
|
||||||
# J721E has 3 clusters of 2 R5 cores each.
|
# J721E has 3 clusters of 2 R5 cores each.
|
||||||
set _r5_cores 6
|
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 {
|
j7200 {
|
||||||
set _CHIPNAME j7200
|
|
||||||
set _K3_DAP_TAPID 0x0bb6d02f
|
set _K3_DAP_TAPID 0x0bb6d02f
|
||||||
|
|
||||||
# J7200 has 1 cluster of 2 A72 cores.
|
# J7200 has 1 cluster of 2 A72 cores.
|
||||||
|
@ -142,7 +194,6 @@ switch $_soc {
|
||||||
set CM3_CTIBASE {0x20001000}
|
set CM3_CTIBASE {0x20001000}
|
||||||
}
|
}
|
||||||
j721s2 {
|
j721s2 {
|
||||||
set _CHIPNAME j721s2
|
|
||||||
set _K3_DAP_TAPID 0x0bb7502f
|
set _K3_DAP_TAPID 0x0bb7502f
|
||||||
|
|
||||||
# J721s2 has 1 cluster of 2 A72 cores.
|
# J721s2 has 1 cluster of 2 A72 cores.
|
||||||
|
@ -161,11 +212,44 @@ switch $_soc {
|
||||||
set _gp_mcu_cores 1
|
set _gp_mcu_cores 1
|
||||||
set _gp_mcu_ap_unlock_offsets {0xf0 0x7c}
|
set _gp_mcu_ap_unlock_offsets {0xf0 0x7c}
|
||||||
}
|
}
|
||||||
|
j784s4 {
|
||||||
|
set _K3_DAP_TAPID 0x0bb8002f
|
||||||
|
|
||||||
|
# j784s4 has 2 cluster of 4 A72 cores each.
|
||||||
|
set _armv8_cpu_name a72
|
||||||
|
set _armv8_cores 8
|
||||||
|
set ARMV8_DBGBASE {0x90410000 0x90510000 0x90610000 0x90710000
|
||||||
|
0x90810000 0x90910000 0x90a10000 0x90b10000}
|
||||||
|
set ARMV8_CTIBASE {0x90420000 0x90520000 0x90620000 0x90720000
|
||||||
|
0x90820000 0x90920000 0x90a20000 0x90b20000}
|
||||||
|
|
||||||
|
# J721s2 has 4 clusters of 2 R5 cores each.
|
||||||
|
set _r5_cores 8
|
||||||
|
set R5_DBGBASE {0x9d010000 0x9d012000
|
||||||
|
0x9d410000 0x9d412000
|
||||||
|
0x9d510000 0x9d512000
|
||||||
|
0x9d610000 0x9d612000}
|
||||||
|
set R5_CTIBASE {0x9d018000 0x9d019000
|
||||||
|
0x9d418000 0x9d419000
|
||||||
|
0x9d518000 0x9d519000
|
||||||
|
0x9d618000 0x9d619000}
|
||||||
|
set R5_NAMES {mcu_r5.0 mcu_r5.1
|
||||||
|
main0_r5.0 main0_r5.1
|
||||||
|
main1_r5.0 main1_r5.1
|
||||||
|
main2_r5.0 main2_r5.1}
|
||||||
|
|
||||||
|
# sysctrl CTI base
|
||||||
|
set CM3_CTIBASE {0x20001000}
|
||||||
|
# Sysctrl power-ap unlock offsets
|
||||||
|
set _sysctrl_ap_unlock_offsets {0xf0 0x78}
|
||||||
|
}
|
||||||
default {
|
default {
|
||||||
echo "'$_soc' is invalid!"
|
echo "'$_soc' is invalid!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set _CHIPNAME $_soc
|
||||||
|
|
||||||
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_K3_DAP_TAPID -ignore-version
|
swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_K3_DAP_TAPID -ignore-version
|
||||||
|
|
||||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||||
|
@ -302,3 +386,22 @@ if { $_gp_mcu_cores != 0 } {
|
||||||
halt 1000
|
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!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue