From 988a844b3345bfb152bcd6e81dc1e296c4d5a05a Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Sat, 10 Sep 2022 23:42:50 +0930 Subject: [PATCH 1/3] Inital support for mpsse vendor commands --- src/main.c | 245 +++++++++++++------------------------ src/tusb/tusb_config.h | 9 +- src/tusb/usb_descriptors.c | 201 +++++++++++++----------------- vendor/tinyusb/meson.build | 1 + 4 files changed, 176 insertions(+), 280 deletions(-) diff --git a/src/main.c b/src/main.c index 5998616..66f1d3d 100644 --- a/src/main.c +++ b/src/main.c @@ -262,25 +262,16 @@ void blink_task(){ static unsigned int _time; static bool _toggle; - if((board_millis() - _time) > 20){ + if((board_millis() - _time) > 200){ _time = board_millis(); - switch(blink_interval_ms){ - case BLINK_DFU_DOWNLOAD:{ - if(_toggle ^= 1){ - GPIO_ResetBits(GPIOC, GPIO_Pin_3); - GPIO_SetBits(GPIOC, GPIO_Pin_2); - }else{ - GPIO_SetBits(GPIOC, GPIO_Pin_3); - GPIO_ResetBits(GPIOC, GPIO_Pin_2); - } - } break; - - default:{ - GPIO_ResetBits(GPIOC, GPIO_Pin_3); - GPIO_ResetBits(GPIOC, GPIO_Pin_2); - } break; - } + if(_toggle ^= 1){ + GPIO_ResetBits(GPIOC, GPIO_Pin_3); + GPIO_SetBits(GPIOC, GPIO_Pin_2); + }else{ + GPIO_SetBits(GPIOC, GPIO_Pin_3); + GPIO_ResetBits(GPIOC, GPIO_Pin_2); + } } } @@ -324,165 +315,93 @@ void reset_task(){ } -//--------------------------------------------------------------------+ -// DFU callbacks -// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc. -//--------------------------------------------------------------------+ - -// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST) -// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation. -// During this period, USB host won't try to communicate with us. -uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state) -{ - if (state == DFU_DNBUSY) - { - return 0; /* Request we are polled in 1ms */ - } - else if (state == DFU_MANIFEST) - { - return 0; // since we don't buffer entire image and do any flashing in manifest stage - } - - return 0; -} - -void dfu_download_flash(uint16_t block_num, uint8_t const *data, uint16_t length); -void dfu_download_sram(uint16_t block_num, uint8_t const *data, uint16_t length); - -// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests -// This callback could be returned before flashing op is complete (async). -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const *data, uint16_t length) -{ - (void)alt; - (void)block_num; - - if(alt == 0){ - dfu_download_flash(block_num, data, length); - } - else{ - dfu_download_sram(block_num, data, length); - } - -} - -void dfu_download_flash(uint16_t block_num, uint8_t const *data, uint16_t length){ - if(!is_flash_spi_inited()){ - ice40_reset_hold(); - flash_spi_init(); - GPIO_SetBits(GPIOE, GPIO_Pin_13); - SPI_Flash_WAKEUP(); - } - - blink_interval_ms = BLINK_DFU_DOWNLOAD; - - if ((block_num * CFG_TUD_DFU_XFER_BUFSIZE) >= alt_offsets[0].length) - { - // flashing op for download length error - tud_dfu_finish_flashing(DFU_STATUS_ERR_ADDRESS); - - blink_interval_ms = BLINK_DFU_ERROR; - - return; - } - - uint32_t flash_address = alt_offsets[0].address + block_num * CFG_TUD_DFU_XFER_BUFSIZE; - - - for (int i = 0; i < CFG_TUD_DFU_XFER_BUFSIZE / 256; i++) - { - /* First block in 64K erase block */ - if ((flash_address & (FLASH_4K_BLOCK_ERASE_SIZE - 1)) == 0) - { - SPI_Flash_Erase_Sector(flash_address); - } - SPI_Flash_Write_Page((uint8_t*)data, flash_address, 256); - flash_address += 256; - data += 256; - } +enum mpsse_requests { + REQUEST_RESET =0x00, + REQUEST_MODEM_CTRL =0x01, + REQUEST_SET_FLOW_CTRL =0x02, + REQUEST_SET_BAUD_RATE =0x03, + REQUEST_SET_DATA =0x04, + REQUEST_GET_MODEM_STAT =0x05, + REQUEST_SET_EVENT_CHAR =0x06, + REQUEST_SET_ERROR_CHAR =0x07, + REQUEST_SET_LAT_TIMER =0x09, + REQUEST_GET_LAT_TIMER =0x0A, + REQUEST_SET_BITMODE =0x0B, + FTDI_SIO_READ_EEPROM =0x90, +}; - // flashing op for download complete without error - tud_dfu_finish_flashing(DFU_STATUS_OK); -} +uint8_t lat_timer = 0; +//--------------------------------------------------------------------+ +// MPSSE use vendor class +//--------------------------------------------------------------------+ -void dfu_download_sram(uint16_t block_num, uint8_t const *data, uint16_t length){ - - if(!is_ice40_spi_inited()){ - ice40_reset_hold(); - //GPIO_ResetBits(GPIOE, GPIO_Pin_13); /* Disconnect ice40 CS from FLASH CS */ - - ice40_spi_init(); - ice40_reset_release(); - delay_Ms(3); - GPIO_SetBits(GPIOB, GPIO_Pin_12); - delay_Ms(1); - - SPI_I2S_SendData(SPI2, 0xFF); /* 8 dummy clocks */ - while(!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)); - delay_Ms(1); - - GPIO_ResetBits(GPIOB, GPIO_Pin_12); +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) +{ + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) return true; - } + switch (request->bmRequestType_bit.type) + { + case TUSB_REQ_TYPE_VENDOR: + switch (request->bRequest) + { + case REQUEST_RESET: + return tud_control_xfer(rhport, request, NULL, 0); + + case REQUEST_GET_LAT_TIMER: + if(request->wLength == 1){ + return tud_control_xfer(rhport, request, (void*)(uint8_t[]){lat_timer}, 1); + } + return false; + + case REQUEST_SET_LAT_TIMER: + lat_timer = request->wValue; + return tud_control_xfer(rhport, request, NULL, 0); + + case REQUEST_SET_BAUD_RATE: + { + uint8_t baud_low = request->wValue & 0xFF; + uint8_t baud_high = (request->wValue >> 8) & 0xFF; + uint8_t port = request->wIndex & 0xFF; + uint8_t clock_div = (request->wIndex >> 8) & 0xFF; + } + return tud_control_xfer(rhport, request, NULL, 0); + + case REQUEST_SET_BITMODE: + return tud_control_xfer(rhport, request, NULL, 0); + + case FTDI_SIO_READ_EEPROM: + /* Return 0xFF bytes, like a real FTDI without EEPROM might */ + if(request->wLength == 2){ + return tud_control_xfer(rhport, request, (void*)(uint8_t[]){0xFF,0xFF}, 2); + } + return false; + + + + default: break; + } + break; - blink_interval_ms = BLINK_DFU_DOWNLOAD; - uint8_t const *c = data; - for(int i = 0; i < length; i++){ - - while(!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)); - SPI_I2S_SendData(SPI2, *c++); + default: break; } - // flashing op for download complete without error - tud_dfu_finish_flashing(DFU_STATUS_OK); + // stall unknown request + return false; } -// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest) -// Application can do checksum, or actual flashing if buffered entire image previously. -// Once finished flashing, application must call tud_dfu_finish_flashing() -void tud_dfu_manifest_cb(uint8_t alt) -{ - (void)alt; - blink_interval_ms = BLINK_DFU_IDLE; - // flashing op for manifest is complete without error - // Application can perform checksum, should it fail, use appropriate status such as errVERIFY. - tud_dfu_finish_flashing(DFU_STATUS_OK); -} +// Invoked when received new data +void tud_vendor_rx_cb(uint8_t itf){ -// Invoked when the Host has terminated a download or upload transfer -void tud_dfu_abort_cb(uint8_t alt) -{ - (void)alt; - blink_interval_ms = BLINK_DFU_ERROR; } -// Invoked when a DFU_DETACH request is received -void tud_dfu_detach_cb(void) -{ - blink_interval_ms = BLINK_DFU_SLEEP; - - if(is_ice40_spi_inited()){ - - for(int i = 0; i <= 149/8; i++){ - while(!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)); - SPI_I2S_SendData(SPI2, 0xFF); /* 149 dummy clocks */ - } - delay_Ms(2); - GPIO_SetBits(GPIOB, GPIO_Pin_12); - ice40_spi_deinit(); - - }else{ - - flash_spi_deinit(); - GPIO_SetBits(GPIOE, GPIO_Pin_13); - - ice40_reset_release(); - - } - - +// Invoked when last rx transfer finished +void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes){ } \ No newline at end of file diff --git a/src/tusb/tusb_config.h b/src/tusb/tusb_config.h index 4f4f752..bdc4dc4 100644 --- a/src/tusb/tusb_config.h +++ b/src/tusb/tusb_config.h @@ -90,13 +90,16 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -#define CFG_TUSB_DEBUG 1 +#define CFG_TUSB_DEBUG 3 //------------- CLASS -------------// -#define CFG_TUD_DFU 1 +#define CFG_TUD_VENDOR 1 // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR -#define CFG_TUD_DFU_XFER_BUFSIZE 512 +#define CFG_TUD_VENDOR_EPSIZE 512 + +#define CFG_TUD_VENDOR_RX_BUFSIZE 512 +#define CFG_TUD_VENDOR_TX_BUFSIZE 512 #ifdef __cplusplus } diff --git a/src/tusb/usb_descriptors.c b/src/tusb/usb_descriptors.c index a4698da..cdb2c45 100644 --- a/src/tusb/usb_descriptors.c +++ b/src/tusb/usb_descriptors.c @@ -24,7 +24,7 @@ */ #include "tusb.h" -#include "class/dfu/dfu_device.h" +#include "class/vendor/vendor_device.h" #include "flash.h" //--------------------------------------------------------------------+ @@ -36,23 +36,15 @@ tusb_desc_device_t const desc_device = .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, - #if CFG_TUD_CDC - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - #else .bDeviceClass = 0x00, .bDeviceSubClass = 0x00, .bDeviceProtocol = 0x00, - #endif .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0x1209, - .idProduct = 0x5af1, - .bcdDevice = 0x0100, + .idVendor = 0x0403, + .idProduct = 0x6014, + .bcdDevice = 0x0900, .iManufacturer = 0x01, .iProduct = 0x02, @@ -68,40 +60,108 @@ uint8_t const * tud_descriptor_device_cb(void) return (uint8_t const *) &desc_device; } + //--------------------------------------------------------------------+ -// Configuration Descriptor +// Generic Descriptor Templates //--------------------------------------------------------------------+ -// Number of Alternate Interface (each for 1 flash partition) -#define ALT_COUNT 2 +#define TUD_GEN_INTERFACE_DESCRIPTOR(_itfnum, _altsetting, _num_endpoints, _itfclass, _itfsubclass, _itfprotocol, _itfstridx) \ + 9, TUSB_DESC_INTERFACE, _itfnum, _altsetting, _num_endpoints, _itfclass, _itfsubclass, _itfprotocol, _itfstridx + +#define TUD_GEN_BULK_EP_DESCRIPTOR(_epnum, _epsize) \ + 7, TUSB_DESC_ENDPOINT, _epnum, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 + +#define TUD_GEN_INTERRUPT_EP_DESCRIPTOR(_epnum, _epsize, _interval) \ + 7, TUSB_DESC_ENDPOINT, _epnum, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _interval + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ enum { - ITF_NUM_DFU_MODE, + ITF_NUM_MPSSE_0, ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_DFU_DESC_LEN(ALT_COUNT)) +// 1x (interface + 2 endpoints) +#define TUD_MPSSE_DESC_LEN (9+7+7) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MPSSE_DESC_LEN) + +#define EPNUM_MPSSE_0_IN 0x81 +#define EPNUM_MPSSE_0_OUT 0x02 -#define FUNC_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_MANIFESTATION_TOLERANT) -uint8_t const desc_configuration[] = +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 200), + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x80, 100), + TUD_GEN_INTERFACE_DESCRIPTOR(0, 0, 2, 0xFF, 0xFF, 0xFF , 2), + TUD_GEN_BULK_EP_DESCRIPTOR(EPNUM_MPSSE_0_IN, CFG_TUD_VENDOR_EPSIZE), + TUD_GEN_BULK_EP_DESCRIPTOR(EPNUM_MPSSE_0_OUT, CFG_TUD_VENDOR_EPSIZE), + }; + - // Interface number, Alternate count, starting string index, attributes, detach timeout, transfer size - TUD_DFU_DESCRIPTOR(ITF_NUM_DFU_MODE, ALT_COUNT, 4, FUNC_ATTRS, 50, CFG_TUD_DFU_XFER_BUFSIZE), +uint8_t const desc_hs_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x80, 100), + TUD_GEN_INTERFACE_DESCRIPTOR(0, 0, 2, 0xFF, 0xFF, 0xFF , 2), + TUD_GEN_BULK_EP_DESCRIPTOR(EPNUM_MPSSE_0_IN, CFG_TUD_VENDOR_EPSIZE), + TUD_GEN_BULK_EP_DESCRIPTOR(EPNUM_MPSSE_0_OUT, CFG_TUD_VENDOR_EPSIZE), }; +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = +{ + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = 0x0200, + + .bDeviceClass = 0xFF, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) +{ + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; +} + + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations - return desc_configuration; + +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ @@ -112,75 +172,12 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) char const* string_desc_arr [] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "1BitSqured", // 1: Manufacturer - "iCEBreaker v1.99 (dfu)", // 2: Product - "", // 3: Serial, derived from FLASH UUID - "ice40 flash gateware", // 4: DFU alt0 name - "ice40 sram gateware", // 5: DFU alt0 name + "1BitSquared", // 1: Manufacturer + "iCEBreaker V1.99a", // 2: Product + "dev00001", // 3: Serial }; -// Microsoft Compatible ID Feature Descriptor -#define MSFT_VENDOR_CODE '~' // Arbitrary, but should be printable ASCII -#define MSFT_WCID_LEN 40 - -// Microsoft OS String Descriptor. See: https://github.com/pbatard/libwdi/wiki/WCID-Devices -static const uint16_t usb_string_microsoft[] = {0x0318, 'M','S','F','T','1','0','0', MSFT_VENDOR_CODE}; - -// Microsoft WCID -const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN] = { - MSFT_WCID_LEN, 0, 0, 0, // Length - 0x00, 0x01, // Version - 0x04, 0x00, // Compatibility ID descriptor index - 0x01, // Number of sections - 0, 0, 0, 0, 0, 0, 0, // Reserved (7 bytes) - - 0, // Interface number - 0x01, // Reserved - 'W','I','N','U','S','B',0,0, // Compatible ID - 0,0,0,0,0,0,0,0, // Sub-compatible ID (unused) - 0,0,0,0,0,0, // Reserved -}; - - -//--------------------------------------------------------------------+ -// WCID use vendor class -//--------------------------------------------------------------------+ -bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // nothing to with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; - - switch (request->bmRequestType_bit.type) - { - case TUSB_REQ_TYPE_VENDOR: - switch (request->bRequest) - { - case MSFT_VENDOR_CODE: - if ( request->wIndex == 0x0004 ) - { - // Return a Microsoft Compatible ID Feature Descriptor - return tud_control_xfer(rhport, request, (void*) usb_microsoft_wcid, MSFT_WCID_LEN); - } - break; - default: break; - } - break; - - - default: break; - } - - // stall unknown request - return false; -} - -static uint16_t _desc_str[40]; - -char hex(uint8_t d){ - if(d <= 0x9) - return d + '0'; - return d - 10 + 'a'; -} +static uint16_t _desc_str[32]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete @@ -195,32 +192,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; } - else if(index == 3){ - uint8_t uuid[8] = {0}; - - SPI_Flash_ReadUUID(uuid); - chr_count = 19; - - uint16_t* s = &_desc_str[1]; - // Convert ASCII string into UTF-16 - for(uint8_t i=0; i<8; i++) - { - /* Add dashes every 2 bytes */ - if(i && !(i & 1)){ - *s++ = '-'; - } - - *s++ = hex(uuid[i] >> 4); - *s++ = hex(uuid[i] & 0xF); - } - } else { - // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if(index == 0xEE){ - return usb_string_microsoft; - } if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; diff --git a/vendor/tinyusb/meson.build b/vendor/tinyusb/meson.build index 9033246..2e89839 100644 --- a/vendor/tinyusb/meson.build +++ b/vendor/tinyusb/meson.build @@ -27,6 +27,7 @@ tusb_src = files([ 'tinyusb_src/src/class/cdc/cdc_device.c', 'tinyusb_src/src/class/dfu/dfu_device.c', 'tinyusb_src/src/class/dfu/dfu_rt_device.c', + 'tinyusb_src/src/class/vendor/vendor_device.c', 'tinyusb_src/src/class/hid/hid_device.c', 'tinyusb_src/src/class/msc/msc_device.c', ]) \ No newline at end of file From 0b764b1c55b23684e70525575f8a1b2a6568822a Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Sun, 11 Sep 2022 15:24:11 +0930 Subject: [PATCH 2/3] Fix IN EP ACKs when not ready --- src/tusb/portable/wch/ch32v307/usb_dc_usbhs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tusb/portable/wch/ch32v307/usb_dc_usbhs.c b/src/tusb/portable/wch/ch32v307/usb_dc_usbhs.c index aba59e9..a085774 100644 --- a/src/tusb/portable/wch/ch32v307/usb_dc_usbhs.c +++ b/src/tusb/portable/wch/ch32v307/usb_dc_usbhs.c @@ -330,6 +330,8 @@ void dcd_int_handler(uint8_t rhport) { if (end_num == 0) { USBHSD->UEP0_RX_CTRL = (USBHSD->UEP0_RX_CTRL & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; memcpy(xfer->buffer, ep0_databuf, rx_len); + }else { + EP_RX_CTRL(end_num) = (EP_RX_CTRL(end_num) & ~(USBHS_EP_R_RES_MASK)) | USBHS_EP_R_RES_NAK; } if (xfer->short_packet || (xfer->queued_len == xfer->total_len)) { From 58ebef7f9eb6c60bafaa51aa64f7954b55a13303 Mon Sep 17 00:00:00 2001 From: Greg Davill Date: Sun, 11 Sep 2022 15:24:51 +0930 Subject: [PATCH 3/3] Inital commit of basic MPSSE functions --- src/main.c | 679 +++++++++++++++++++++++++++------------- src/platform/hw_1.99a.c | 2 +- src/tusb/tusb_config.h | 6 +- 3 files changed, 463 insertions(+), 224 deletions(-) diff --git a/src/main.c b/src/main.c index 66f1d3d..44472dc 100644 --- a/src/main.c +++ b/src/main.c @@ -17,27 +17,26 @@ #include -#include #include +#include #include -#include "tusb.h" #include "flash.h" -#include "time.h" #include "platform.h" +#include "time.h" +#include "tusb.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -typedef struct -{ - uint32_t address; - uint32_t length; +typedef struct { + uint32_t address; + uint32_t length; } memory_offest; memory_offest const alt_offsets[] = { - {.address = 0x000000, .length = 0x800000}, /* Main Gateware */ - {.address = 0x000000, .length = 0x800000}, /* Main Firmawre */ + { .address = 0x000000, .length = 0x800000 }, /* Main Gateware */ + { .address = 0x000000, .length = 0x800000 }, /* Main Firmawre */ }; /* Blink pattern @@ -46,18 +45,16 @@ memory_offest const alt_offsets[] = { * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum -{ - BLINK_DFU_IDLE, - BLINK_DFU_IDLE_BOOTLOADER, - BLINK_DFU_DOWNLOAD, - BLINK_DFU_ERROR, - BLINK_DFU_SLEEP, +enum { + BLINK_DFU_IDLE, + BLINK_DFU_IDLE_BOOTLOADER, + BLINK_DFU_DOWNLOAD, + BLINK_DFU_ERROR, + BLINK_DFU_SLEEP, }; static uint32_t blink_interval_ms = BLINK_DFU_IDLE; - void cdc_task(void); void blink_task(void); void reset_task(void); @@ -66,36 +63,30 @@ void reset_task(void); // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ - -__attribute__ ((naked,aligned(4))) void USBHS_IRQHandler(void) { - tud_int_handler(0); - __asm volatile ("mret"); +__attribute__((naked, aligned(4))) void USBHS_IRQHandler(void) { + tud_int_handler(0); + __asm volatile("mret"); } - -uint32_t SysTick_Config(uint32_t ticks) -{ - NVIC_EnableIRQ(SysTicK_IRQn); - SysTick->CTLR=0; - SysTick->SR=0; - SysTick->CNT=0; - SysTick->CMP=ticks-1; - SysTick->CTLR=0xF; - return 0; +uint32_t SysTick_Config(uint32_t ticks) { + NVIC_EnableIRQ(SysTicK_IRQn); + SysTick->CTLR = 0; + SysTick->SR = 0; + SysTick->CNT = 0; + SysTick->CMP = ticks - 1; + SysTick->CTLR = 0xF; + return 0; } void board_init(void) { - /* Disable interrupts during init */ __disable_irq(); - - #if CFG_TUSB_OS == OPT_OS_NONE SysTick_Config(SystemCoreClock / 1000); #endif - USART_Printf_Init(115200); + USART_Printf_Init(115200); RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); @@ -105,77 +96,62 @@ void board_init(void) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); - GPIO_Init( - GPIOC, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Pin = GPIO_Pin_2, - } - ); - - GPIO_Init( - GPIOC, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Pin = GPIO_Pin_3, - } - ); - - GPIO_Init( - GPIOE, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Pin = GPIO_Pin_3, - } - ); - GPIO_Init( - GPIOE, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Pin = GPIO_Pin_2, - } - ); - - GPIO_Init( - GPIOE, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Pin = GPIO_Pin_13, - } - ); + GPIO_Init(GPIOC, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Pin = GPIO_Pin_2, + }); + + GPIO_Init(GPIOC, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Pin = GPIO_Pin_3, + }); + + GPIO_Init(GPIOE, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Pin = GPIO_Pin_3, + }); + GPIO_Init(GPIOE, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Pin = GPIO_Pin_2, + }); + + GPIO_Init(GPIOE, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Pin = GPIO_Pin_13, + }); GPIO_SetBits(GPIOE, GPIO_Pin_13); - /* iCE Reset PA10 */ - GPIO_Init( - GPIOA, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Pin = GPIO_Pin_10, - } - ); + GPIO_Init(GPIOA, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Pin = GPIO_Pin_10, + }); GPIO_ResetBits(GPIOA, GPIO_Pin_10); /* iCE Clk PA8 */ - GPIO_Init( - GPIOA, - &(GPIO_InitTypeDef) { - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Pin = GPIO_Pin_8, - } - ); + GPIO_Init(GPIOA, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_8, + }); RCC_MCOConfig(RCC_MCO_XT1); - /* Enable interrupts globaly */ __enable_irq(); @@ -186,29 +162,28 @@ void board_init(void) { volatile uint32_t system_ticks = 0; /* Small workaround to support HW stack save/restore */ -void SysTick_Handler(void) __attribute__((naked,aligned(4))); -void SysTick_Handler(void) { - __asm volatile ("call SysTick_Handler_impl; mret"); +void SysTick_Handler(void) __attribute__((naked, aligned(4))); +void SysTick_Handler(void) { + __asm volatile("call SysTick_Handler_impl; mret"); } -__attribute__((used,aligned(4))) void SysTick_Handler_impl(void) { - SysTick->SR=0; +__attribute__((used, aligned(4))) void SysTick_Handler_impl(void) { + SysTick->SR = 0; system_ticks++; } -uint32_t board_millis(void) { return system_ticks; } +uint32_t board_millis(void) { + return system_ticks; +} #endif -__attribute__ ((aligned(4))) -int main() { - +__attribute__((aligned(4))) int main() { board_init(); - ice40_reset_hold(); flash_spi_init(); - + /* Read out UUID and cache it, used by USB system for descriptors */ SPI_Flash_WAKEUP(); SPI_Flash_ReadUUID(NULL); @@ -216,13 +191,11 @@ int main() { flash_spi_deinit(); ice40_reset_release(); - - tusb_init(); - + ice40_spi_init(); + tusb_init(); - while (1) - { + while (1) { tud_task(); // tinyusb device task blink_task(); @@ -235,48 +208,40 @@ int main() { //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ - -} +void tud_mount_cb(void) {} // Invoked when device is unmounted -void tud_umount_cb(void) -{ -} +void tud_umount_cb(void) {} // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ -} +void tud_resume_cb(void) {} -void blink_task(){ +void blink_task() { static unsigned int _time; static bool _toggle; - if((board_millis() - _time) > 200){ + if ((board_millis() - _time) > 200) { _time = board_millis(); - if(_toggle ^= 1){ - GPIO_ResetBits(GPIOC, GPIO_Pin_3); - GPIO_SetBits(GPIOC, GPIO_Pin_2); - }else{ - GPIO_SetBits(GPIOC, GPIO_Pin_3); - GPIO_ResetBits(GPIOC, GPIO_Pin_2); - } + if (_toggle ^= 1) { + GPIO_ResetBits(GPIOC, GPIO_Pin_3); + GPIO_SetBits(GPIOC, GPIO_Pin_2); + } else { + GPIO_SetBits(GPIOC, GPIO_Pin_3); + GPIO_ResetBits(GPIOC, GPIO_Pin_2); + } } } /* Implement a 4-press reset to bootloader, timeout from first press is 3s */ -void reset_task(){ +void reset_task() { enum reset_state { IDLE, WINDOW @@ -286,49 +251,47 @@ void reset_task(){ static uint32_t _count; static bool last_pin_value = false; - bool pin_value = (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)) ? true : false; + bool pin_value = GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3); bool edge = (pin_value == true) && (last_pin_value == false); - - switch(_state){ - case IDLE: - default: - if(edge){ - _state = WINDOW; - _timeout = board_millis(); - _count = 0; - } - break; - - case WINDOW: - if(edge){ - if(++_count >= 4){ - NVIC_SystemReset(); - } - } - if((board_millis() - _timeout) > 3000){ - _state = IDLE; + + switch (_state) { + case IDLE: + default: + if (edge) { + _state = WINDOW; + _timeout = board_millis(); + _count = 0; + } + break; + + case WINDOW: + if (edge) { + if (++_count >= 4) { + NVIC_SystemReset(); } - break; + } + if ((board_millis() - _timeout) > 3000) { + _state = IDLE; + } + break; } last_pin_value = pin_value; } - - enum mpsse_requests { - REQUEST_RESET =0x00, - REQUEST_MODEM_CTRL =0x01, - REQUEST_SET_FLOW_CTRL =0x02, - REQUEST_SET_BAUD_RATE =0x03, - REQUEST_SET_DATA =0x04, - REQUEST_GET_MODEM_STAT =0x05, - REQUEST_SET_EVENT_CHAR =0x06, - REQUEST_SET_ERROR_CHAR =0x07, - REQUEST_SET_LAT_TIMER =0x09, - REQUEST_GET_LAT_TIMER =0x0A, - REQUEST_SET_BITMODE =0x0B, - FTDI_SIO_READ_EEPROM =0x90, + REQUEST_RESET = 0x00, + REQUEST_MODEM_CTRL = 0x01, + REQUEST_SET_FLOW_CTRL = 0x02, + REQUEST_SET_BAUD_RATE = 0x03, + REQUEST_SET_DATA = 0x04, + REQUEST_GET_MODEM_STAT = 0x05, + REQUEST_SET_EVENT_CHAR = 0x06, + REQUEST_SET_ERROR_CHAR = 0x07, + REQUEST_SET_LAT_TIMER = 0x09, + REQUEST_GET_LAT_TIMER = 0x0A, + REQUEST_SET_BITMODE = 0x0B, + FTDI_SIO_READ_EEPROM = 0x90, }; uint8_t lat_timer = 0; @@ -340,68 +303,344 @@ uint8_t lat_timer = 0; // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ +bool tud_vendor_control_xfer_cb(uint8_t rhport, + uint8_t stage, + tusb_control_request_t const* request) { // nothing to with DATA & ACK stage - if (stage != CONTROL_STAGE_SETUP) return true; - - switch (request->bmRequestType_bit.type) - { - case TUSB_REQ_TYPE_VENDOR: - switch (request->bRequest) - { - case REQUEST_RESET: - return tud_control_xfer(rhport, request, NULL, 0); - - case REQUEST_GET_LAT_TIMER: - if(request->wLength == 1){ - return tud_control_xfer(rhport, request, (void*)(uint8_t[]){lat_timer}, 1); - } - return false; - - case REQUEST_SET_LAT_TIMER: - lat_timer = request->wValue; - return tud_control_xfer(rhport, request, NULL, 0); - - case REQUEST_SET_BAUD_RATE: - { - uint8_t baud_low = request->wValue & 0xFF; - uint8_t baud_high = (request->wValue >> 8) & 0xFF; - uint8_t port = request->wIndex & 0xFF; - uint8_t clock_div = (request->wIndex >> 8) & 0xFF; - } - return tud_control_xfer(rhport, request, NULL, 0); - - case REQUEST_SET_BITMODE: - return tud_control_xfer(rhport, request, NULL, 0); - - case FTDI_SIO_READ_EEPROM: - /* Return 0xFF bytes, like a real FTDI without EEPROM might */ - if(request->wLength == 2){ - return tud_control_xfer(rhport, request, (void*)(uint8_t[]){0xFF,0xFF}, 2); - } - return false; - - - - default: break; + if (stage != CONTROL_STAGE_SETUP) + return true; + + switch (request->bmRequestType_bit.type) { + case TUSB_REQ_TYPE_VENDOR: + switch (request->bRequest) { + case REQUEST_RESET: + return tud_control_xfer(rhport, request, NULL, 0); + + case REQUEST_GET_LAT_TIMER: + if (request->wLength == 1) { + return tud_control_xfer(rhport, request, (void*)(uint8_t[]){ lat_timer }, 1); } - break; + return false; + + case REQUEST_SET_LAT_TIMER: + lat_timer = request->wValue; + return tud_control_xfer(rhport, request, NULL, 0); + + case REQUEST_SET_BAUD_RATE: { + uint8_t baud_low = request->wValue & 0xFF; + uint8_t baud_high = (request->wValue >> 8) & 0xFF; + uint8_t port = request->wIndex & 0xFF; + uint8_t clock_div = (request->wIndex >> 8) & 0xFF; + } + return tud_control_xfer(rhport, request, NULL, 0); + + case REQUEST_SET_BITMODE: + return tud_control_xfer(rhport, request, NULL, 0); + case FTDI_SIO_READ_EEPROM: + /* Return 0xFF bytes, like a real FTDI without EEPROM might */ + if (request->wLength == 2) { + return tud_control_xfer(rhport, request, (void*)(uint8_t[]){ 0xFF, 0xFF }, 2); + } + return false; - default: break; + default: + break; + } + break; + + default: + break; } // stall unknown request return false; } +/* MPSSE engine command definitions */ +enum mpsse_cmd { + /* Mode commands */ + MC_SETB_LOW = 0x80, /* Set Data bits LowByte */ + MC_READB_LOW = 0x81, /* Read Data bits LowByte */ + MC_SETB_HIGH = 0x82, /* Set Data bits HighByte */ + MC_READB_HIGH = 0x83, /* Read data bits HighByte */ + MC_LOOPBACK_EN = 0x84, /* Enable loopback */ + MC_LOOPBACK_DIS = 0x85, /* Disable loopback */ + MC_SET_CLK_DIV = 0x86, /* Set clock divisor */ + MC_FLUSH = 0x87, /* Flush buffer fifos to the PC. */ + MC_WAIT_H = 0x88, /* Wait on GPIOL1 to go high. */ + MC_WAIT_L = 0x89, /* Wait on GPIOL1 to go low. */ + MC_TCK_X5 = 0x8A, /* Disable /5 div, enables 60MHz master clock */ + MC_TCK_D5 = 0x8B, /* Enable /5 div, backward compat to FT2232D */ + MC_EN_3PH_CLK = 0x8C, /* Enable 3 phase clk, DDR I2C */ + MC_DIS_3PH_CLK = 0x8D, /* Disable 3 phase clk */ + MC_CLK_N = 0x8E, /* Clock every bit, used for JTAG */ + MC_CLK_N8 = 0x8F, /* Clock every byte, used for JTAG */ + MC_CLK_TO_H = 0x94, /* Clock until GPIOL1 goes high */ + MC_CLK_TO_L = 0x95, /* Clock until GPIOL1 goes low */ + MC_EN_ADPT_CLK = 0x96, /* Enable adaptive clocking */ + MC_DIS_ADPT_CLK = 0x97, /* Disable adaptive clocking */ + MC_CLK8_TO_H = 0x9C, /* Clock until GPIOL1 goes high, count bytes */ + MC_CLK8_TO_L = 0x9D, /* Clock until GPIOL1 goes low, count bytes */ + MC_TRI = 0x9E, /* Set IO to only drive on 0 and tristate on 1 */ + /* CPU mode commands */ + MC_CPU_RS = 0x90, /* CPUMode read short address */ + MC_CPU_RE = 0x91, /* CPUMode read extended address */ + MC_CPU_WS = 0x92, /* CPUMode write short address */ + MC_CPU_WE = 0x93, /* CPUMode write extended address */ +}; -// Invoked when received new data -void tud_vendor_rx_cb(uint8_t itf){ +/* Transfer Command bits */ + +/* All byte based commands consist of: + * - Command byte + * - Length lsb + * - Length msb + * + * If data out is enabled the data follows after the above command bytes, + * otherwise no additional data is needed. + * - Data * n + * + * All bit based commands consist of: + * - Command byte + * - Length + * + * If data out is enabled a byte containing bitst to transfer follows. + * Otherwise no additional data is needed. Only up to 8 bits can be transferred + * per transaction when in bit mode. + */ + +/* b 0000 0000 + * |||| |||`- Data out negative enable. Update DO on negative clock edge. + * |||| ||`-- Bit count enable. When reset count represents bytes. + * |||| |`--- Data in negative enable. Latch DI on negative clock edge. + * |||| `---- LSB enable. When set clock data out LSB first. + * |||| + * |||`------ Data out enable + * ||`------- Data in enable + * |`-------- TMS mode enable + * `--------- Special command mode enable. See mpsse_cmd enum. + */ + +#define MC_DATA_TMS (0x40) /* When set use TMS mode */ +#define MC_DATA_IN (0x20) /* When set read data (Data IN) */ +#define MC_DATA_OUT (0x10) /* When set write data (Data OUT) */ +#define MC_DATA_LSB (0x08) /* When set input/output data LSB first. */ +#define MC_DATA_ICN (0x04) /* When set receive data on negative clock edge */ +#define MC_DATA_BITS (0x02) /* When set count bits not bytes */ +#define MC_DATA_OCN (0x01) /* When set update data on negative clock edge */ + +typedef enum { + OP_CODE = 0, + OP_PARAM0, + OP_PARAM1, + DATA_OUT +} mpsse_state_t; + +mpsse_state_t mpsse_state; +uint8_t current_op = 0; +uint8_t param0 = 0; +uint8_t param1 = 0; + +uint16_t out_cnt; + +void process_mpsse(uint8_t c) { + switch (mpsse_state) { + case OP_CODE: { + current_op = c; + if (c & 0x80) { + switch (c) { + case MC_READB_LOW: { + uint8_t gpio_l = (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) << 4) // CS + | (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) << 6) // CDONE + | (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) << 7); // CRESET + //printf("gpio: %02x\r\n", gpio_l); + tud_vendor_write((void*)(uint8_t[]){ gpio_l }, 1); + tud_vendor_flush(); + } break; + + case MC_TCK_D5: { + break; + } + + case MC_SETB_LOW: + case MC_SET_CLK_DIV: + case MC_CLK_N8: + case MC_CLK_N: + mpsse_state = OP_PARAM0; + break; + + default: + printf("Unknown OP: %02x\r\n", c); + break; + } + } else { + if (c & MC_DATA_OUT) { + mpsse_state = OP_PARAM0; + } + } + } break; + + case OP_PARAM0: + if (current_op & 0x80) { + switch (current_op) { + case MC_SETB_LOW: + case MC_CLK_N8: + param0 = c; + mpsse_state = OP_PARAM1; + break; + + case MC_SET_CLK_DIV: + mpsse_state = OP_PARAM1; + break; + + case MC_CLK_N: { + param0 = c; + GPIO_SetBits(GPIOB, GPIO_Pin_13); + GPIO_Init(GPIOB, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_13, + }); + + /* Transmit dummy bytes */ + for (int i = 0; i <= param0; i++) { + /* Toggle Clock line */ + GPIO_ResetBits(GPIOB, GPIO_Pin_13); + GPIO_SetBits(GPIOB, GPIO_Pin_13); + } + + GPIO_Init(GPIOB, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_13, + }); + mpsse_state = OP_CODE; + } break; + + default: + mpsse_state = OP_CODE; + break; + } + } else { + if (current_op & MC_DATA_OUT) { + param0 = c; + mpsse_state = OP_PARAM1; + } + } + break; + + case OP_PARAM1: + if (current_op & 0x80) { + switch (current_op) { + case MC_SETB_LOW: + param1 = c; + /* Set Pins */ + /* Param0 = GPIO, param1 = direction */ + + /* CS */ + if (param0 & 0x10) { + GPIO_SetBits(GPIOB, GPIO_Pin_12); + } else { + GPIO_ResetBits(GPIOB, GPIO_Pin_12); + } + if (param1 & 0x10) { + GPIO_Init(GPIOB, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_12, + }); + } else { + GPIO_Init(GPIOB, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_12, + }); + } + + /* Reset */ + if (param0 & 0x80) { + GPIO_SetBits(GPIOA, GPIO_Pin_10); + } else { + GPIO_ResetBits(GPIOA, GPIO_Pin_10); + } + + if (param1 & 0x80) { + GPIO_Init(GPIOA, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_10, + }); + } else { + GPIO_Init(GPIOA, + &(GPIO_InitTypeDef){ + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Pin = GPIO_Pin_10, + }); + } + + mpsse_state = OP_CODE; + break; + + case MC_SET_CLK_DIV: + mpsse_state = OP_CODE; + break; + + case MC_CLK_N8: { + mpsse_state = OP_CODE; + + for (int i = 0; i <= param0; i++) { + SPI_I2S_SendData(SPI2, 0xFF); /* 8 dummy clocks */ + while (!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)) + ; + } + } break; + + default: + mpsse_state = OP_CODE; + break; + } + } else { + if (current_op & MC_DATA_OUT) { + param1 = c; + mpsse_state = DATA_OUT; + out_cnt = (param0 + (param1 << 8)) + 1; + } + } + break; + case DATA_OUT: { + if (current_op & MC_DATA_OUT) { + SPI_I2S_SendData(SPI2, c); /* 8 dummy clocks */ + while (!SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)) + ; + + if (--out_cnt == 0) { + mpsse_state = OP_CODE; + } + } + + } break; + } +} + +// Invoked when received new data +void tud_vendor_rx_cb(uint8_t itf) { + while (1) { + uint8_t c; + if (tud_vendor_read(&c, 1)) { + process_mpsse(c); + } else { + break; + } + } } // Invoked when last rx transfer finished -void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes){ -} \ No newline at end of file +void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {} \ No newline at end of file diff --git a/src/platform/hw_1.99a.c b/src/platform/hw_1.99a.c index b9cd7ab..887dd6c 100644 --- a/src/platform/hw_1.99a.c +++ b/src/platform/hw_1.99a.c @@ -156,7 +156,7 @@ void ice40_spi_init(){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); - GPIO_ResetBits(GPIOB, GPIO_Pin_12); + //GPIO_SetBits(GPIOB, GPIO_Pin_12); GPIO_Init( GPIOB, &(GPIO_InitTypeDef) { diff --git a/src/tusb/tusb_config.h b/src/tusb/tusb_config.h index bdc4dc4..7a04614 100644 --- a/src/tusb/tusb_config.h +++ b/src/tusb/tusb_config.h @@ -90,7 +90,7 @@ #define CFG_TUD_ENDPOINT0_SIZE 64 #endif -#define CFG_TUSB_DEBUG 3 +#define CFG_TUSB_DEBUG 1 //------------- CLASS -------------// #define CFG_TUD_VENDOR 1 @@ -98,8 +98,8 @@ // DFU buffer size, it has to be set to the buffer size used in TUD_DFU_DESCRIPTOR #define CFG_TUD_VENDOR_EPSIZE 512 -#define CFG_TUD_VENDOR_RX_BUFSIZE 512 -#define CFG_TUD_VENDOR_TX_BUFSIZE 512 +#define CFG_TUD_VENDOR_RX_BUFSIZE 512 * 2 +#define CFG_TUD_VENDOR_TX_BUFSIZE 512 * 2 #ifdef __cplusplus }