|
|
|
@@ -14,17 +14,188 @@
|
|
|
|
|
#include "soc/usb_serial_jtag_struct.h"
|
|
|
|
|
#include "hal/usb_serial_jtag_types.h"
|
|
|
|
|
|
|
|
|
|
// This header is temporarily disabled until USJ is supported on the P4 (IDF-7496)
|
|
|
|
|
#if SOC_USB_SERIAL_JTAG_SUPPORTED
|
|
|
|
|
|
|
|
|
|
/* ----------------------------- Macros & Types ----------------------------- */
|
|
|
|
|
|
|
|
|
|
#define USB_SERIAL_JTAG_LL_SELECT_PHY_SUPPORTED 1 // Can route to an external FSLS PHY
|
|
|
|
|
|
|
|
|
|
#define USB_SERIAL_JTAG_LL_INTR_MASK (0x7ffff) // All interrupts mask
|
|
|
|
|
|
|
|
|
|
// Define USB_SERIAL_JTAG interrupts
|
|
|
|
|
// Note the hardware has more interrupts, but they're only useful for debugging
|
|
|
|
|
// the hardware.
|
|
|
|
|
typedef enum {
|
|
|
|
|
USB_SERIAL_JTAG_INTR_SOF = (1 << 1),
|
|
|
|
|
USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT = (1 << 2),
|
|
|
|
|
USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY = (1 << 3),
|
|
|
|
|
USB_SERIAL_JTAG_INTR_TOKEN_REC_IN_EP1 = (1 << 8),
|
|
|
|
|
USB_SERIAL_JTAG_INTR_BUS_RESET = (1 << 9),
|
|
|
|
|
USB_SERIAL_JTAG_INTR_EP1_ZERO_PAYLOAD = (1 << 10),
|
|
|
|
|
} usb_serial_jtag_ll_intr_t;
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* ----------------------------- USJ Peripheral ----------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Enable the USB_SERIAL_JTAG interrupt based on the given mask.
|
|
|
|
|
*
|
|
|
|
|
* @param mask The bitmap of the interrupts need to be enabled.
|
|
|
|
|
*
|
|
|
|
|
* @return None
|
|
|
|
|
*/
|
|
|
|
|
static inline void usb_serial_jtag_ll_ena_intr_mask(uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
USB_SERIAL_JTAG.int_ena.val |= mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Disable the USB_SERIAL_JTAG interrupt based on the given mask.
|
|
|
|
|
*
|
|
|
|
|
* @param mask The bitmap of the interrupts need to be disabled.
|
|
|
|
|
*
|
|
|
|
|
* @return None
|
|
|
|
|
*/
|
|
|
|
|
static inline void usb_serial_jtag_ll_disable_intr_mask(uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
USB_SERIAL_JTAG.int_ena.val &= (~mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get the USB_SERIAL_JTAG interrupt status.
|
|
|
|
|
*
|
|
|
|
|
* @return The USB_SERIAL_JTAG interrupt status.
|
|
|
|
|
*/
|
|
|
|
|
static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void)
|
|
|
|
|
{
|
|
|
|
|
return USB_SERIAL_JTAG.int_st.val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get the USB_SERIAL_JTAG raw interrupt status.
|
|
|
|
|
*
|
|
|
|
|
* @return The USB_SERIAL_JTAG raw interrupt status.
|
|
|
|
|
*/
|
|
|
|
|
static inline __attribute__((always_inline)) uint32_t usb_serial_jtag_ll_get_intraw_mask(void)
|
|
|
|
|
{
|
|
|
|
|
return USB_SERIAL_JTAG.int_raw.val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Clear the USB_SERIAL_JTAG interrupt status based on the given mask.
|
|
|
|
|
*
|
|
|
|
|
* @param mask The bitmap of the interrupts need to be cleared.
|
|
|
|
|
*
|
|
|
|
|
* @return None
|
|
|
|
|
*/
|
|
|
|
|
static inline __attribute__((always_inline)) void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
USB_SERIAL_JTAG.int_clr.val = mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Get status of enabled interrupt.
|
|
|
|
|
*
|
|
|
|
|
* @return interrupt enable value
|
|
|
|
|
*/
|
|
|
|
|
static inline uint32_t usb_serial_jtag_ll_get_intr_ena_status(void)
|
|
|
|
|
{
|
|
|
|
|
return USB_SERIAL_JTAG.int_ena.val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Read the bytes from the USB_SERIAL_JTAG rxfifo.
|
|
|
|
|
*
|
|
|
|
|
* @param buf The data buffer.
|
|
|
|
|
* @param rd_len The data length needs to be read.
|
|
|
|
|
*
|
|
|
|
|
* @return amount of bytes read
|
|
|
|
|
*/
|
|
|
|
|
static inline int usb_serial_jtag_ll_read_rxfifo(uint8_t *buf, uint32_t rd_len)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < (int)rd_len; i++) {
|
|
|
|
|
if (!USB_SERIAL_JTAG.ep1_conf.serial_out_ep_data_avail) break;
|
|
|
|
|
buf[i] = USB_SERIAL_JTAG.ep1.rdwr_byte;
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Write byte to the USB_SERIAL_JTAG txfifo. Only writes bytes as long / if there
|
|
|
|
|
* is room in the buffer.
|
|
|
|
|
*
|
|
|
|
|
* @param buf The data buffer.
|
|
|
|
|
* @param wr_len The data length needs to be written.
|
|
|
|
|
*
|
|
|
|
|
* @return Amount of bytes actually written. May be less than wr_len.
|
|
|
|
|
*/
|
|
|
|
|
static inline int usb_serial_jtag_ll_write_txfifo(const uint8_t *buf, uint32_t wr_len)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < (int)wr_len; i++) {
|
|
|
|
|
if (!USB_SERIAL_JTAG.ep1_conf.serial_in_ep_data_free) break;
|
|
|
|
|
USB_SERIAL_JTAG.ep1.rdwr_byte = buf[i];
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Returns 1 if the USB_SERIAL_JTAG rxfifo has data available.
|
|
|
|
|
*
|
|
|
|
|
* @return 0 if no data available, 1 if data available
|
|
|
|
|
*/
|
|
|
|
|
static inline int usb_serial_jtag_ll_rxfifo_data_available(void)
|
|
|
|
|
{
|
|
|
|
|
return USB_SERIAL_JTAG.ep1_conf.serial_out_ep_data_avail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Returns 1 if the USB_SERIAL_JTAG txfifo has room.
|
|
|
|
|
*
|
|
|
|
|
* @return 0 if no data available, 1 if data available
|
|
|
|
|
*/
|
|
|
|
|
static inline int usb_serial_jtag_ll_txfifo_writable(void)
|
|
|
|
|
{
|
|
|
|
|
return USB_SERIAL_JTAG.ep1_conf.serial_in_ep_data_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Flushes the TX buffer, that is, make it available for the
|
|
|
|
|
* host to pick up.
|
|
|
|
|
*
|
|
|
|
|
* @note When fifo is full (with 64 byte), HW will flush the buffer automatically,
|
|
|
|
|
* if this function is called directly after, this effectively turns into a
|
|
|
|
|
* no-op. Because a 64-byte packet will be interpreted as a not-complete USB
|
|
|
|
|
* transaction, you need to transfer either more data or a zero-length packet
|
|
|
|
|
* for the data to actually end up at the program listening to the CDC-ACM
|
|
|
|
|
* serial port. To send a zero-length packet, call
|
|
|
|
|
* usb_serial_jtag_ll_txfifo_flush() again when
|
|
|
|
|
* usb_serial_jtag_ll_txfifo_writable() returns true.
|
|
|
|
|
*
|
|
|
|
|
* @return na
|
|
|
|
|
*/
|
|
|
|
|
static inline void usb_serial_jtag_ll_txfifo_flush(void)
|
|
|
|
|
{
|
|
|
|
|
USB_SERIAL_JTAG.ep1_conf.wr_done=1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Enable USJ JTAG bridge
|
|
|
|
|
*
|
|
|
|
|
* If enabled, USJ is disconnected from internal JTAG interface. JTAG interface
|
|
|
|
|
* is routed through GPIO matrix instead.
|
|
|
|
|
*
|
|
|
|
|
* @param enable Enable USJ JTAG bridge
|
|
|
|
|
*/
|
|
|
|
|
FORCE_INLINE_ATTR void usb_serial_jtag_ll_phy_set_jtag_bridge(bool enable)
|
|
|
|
|
{
|
|
|
|
|
USB_SERIAL_JTAG.conf0.usb_jtag_bridge_en = enable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------- USB PHY Control ---------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|