├── .github └── workflows │ └── build_firmware.yml ├── .gitignore ├── .gitmodules ├── README.md ├── firmware └── app │ ├── usb2dualuart │ ├── CMakeLists.txt │ ├── dev_cfg.h │ ├── ftdi │ │ ├── ftdi_eeprom.c │ │ ├── usbd_ftdi.c │ │ └── usbd_ftdi.h │ ├── main.c │ ├── main.h │ ├── uart_interface.c │ ├── uart_interface.h │ └── usb_descriptor.c │ └── usb2uartjtag │ ├── CMakeLists.txt │ ├── io_cfg.h │ ├── jtag_process.c │ ├── jtag_process.c.gowin │ ├── main.c │ ├── mpsse_cmd.md │ ├── uart_interface.c │ ├── uart_interface.h │ ├── usb_descriptor.c │ ├── usbd_ftdi.c │ └── usbd_ftdi.h ├── hardware ├── BL702_USB2JTAG_3610_asm.pdf └── BL702_USB2JTAG_3610_sch.pdf └── res ├── MPSSE.pdf └── rv-debugger.png /.github/workflows/build_firmware.yml: -------------------------------------------------------------------------------- 1 | name: Debugger Firmware CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths: 7 | - '.github/workflows/build_firmware.yml' 8 | - 'firmware/**' 9 | pull_request: 10 | branches: [ main ] 11 | paths: 12 | - '.github/workflows/build_firmware.yml' 13 | - 'firmware/**' 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | 23 | - name: Cache toolchain 24 | id: cache 25 | uses: actions/cache@v1 26 | with: 27 | path: /opt/riscv64-unknown-elf 28 | key : ${{runner.OS}}-riscv64-unknown-elf-caches-${{ hashFiles('bin/riscv64-unknown-elf-gcc') }} 29 | 30 | - name: Download toolchain 31 | if: steps.cache.outputs.cache-hit != 'true' 32 | run: | 33 | wget -c https://dev.bouffalolab.com/media/upload/download/riscv64-elf-x86_64-20210120.tar.gz 34 | mkdir /opt/riscv64-unknown-elf 35 | tar -zxvf riscv64-elf-x86_64-20210120.tar.gz -C /opt/riscv64-unknown-elf 36 | - name: Make firmware 37 | run: | 38 | git submodule update --init 39 | cd firmware/bl_mcu_sdk 40 | PATH="/opt/riscv64-unknown-elf/bin:$PATH" 41 | make BOARD=bl702_debugger APP_DIR=../app APP=usb2uartjtag 42 | make BOARD=bl702_debugger_dualuart APP_DIR=../app APP=usb2dualuart 43 | - name: Archive firmware 44 | uses: actions/upload-artifact@v2 45 | with: 46 | name: sipeed_rv_debuger_plus_firmware 47 | path: | 48 | firmware/bl_mcu_sdk/out/app/usb2uartjtag/* 49 | firmware/bl_mcu_sdk/out/app/usb2dualuart/* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | **/submodule_commit_info.txt -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "firmware/bl_mcu_sdk"] 2 | path = firmware/bl_mcu_sdk 3 | url = https://github.com/sipeed/bl_mcu_sdk.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | **RV-Debugger-BL702** is an opensource project that implement a JTAG+UART debugger with BL702C-A0. 4 | 5 | [BL702](https://www.bouffalolab.com/bl70X) is highly integrated BLE and Zigbee combo chipset for IoT applications, contains **32-bit RISC-V** CPU with FPU, frequency up to **144MHz**, with **132KB RAM** and **192 KB ROM**, 1Kb eFuse, **512KB embedded Flash**, USB2.0 FS device interface, and many other features. 6 | 7 | The firmware implement is inspired by [open-ec](https://github.com/rgwan/open-ec), implement by Sipeed teams and community developers. 8 | 9 | The firmware emulate an [FT2232D](https://ftdichip.com/products/ft2232d/) device, defaultly implement an JTAG+UART debugger, and can be implement as a Dual-Serial Port debugger, a bluetooth debugger, etc. 10 | 11 | Community Forum: bbs.sipeed.com 12 | 13 | # Hardware 14 | ## Offical Board 15 | 16 | Sipeed RV-Debugger-Plus (BL702C-A0) 17 | 18 | Purchase link: Aliexpress 19 | 20 | Schematic: [BL702_USB2JTAG_3610_sch.pdf](hardware/BL702_USB2JTAG_3610_sch.pdf) 21 | 22 | Assembly: [BL702_USB2JTAG_3610_asm.pdf](hardware/BL702_USB2JTAG_3610_asm.pdf) 23 | 24 | (LED0 is the led close to edge, indicate for RX) 25 | 26 | 27 |
28 | 29 | ## Third-party Hardware 30 | 31 | TODO 32 | 33 | # Firmware 34 | ## build firmware 35 | 36 | To build usb2uartjtag firmware: 37 | 38 | ~~~ 39 | cd firmware/bl_mcu_sdk 40 | make clean 41 | make BOARD=bl702_debugger APP_DIR=../app APP=usb2uartjtag 42 | ~~~ 43 | 44 | The firmware is './out/app/usb2uartjtag/usb2uartjtag_bl702.bin'. 45 | 46 | To build usb2dualuart firmware: 47 | 48 | ~~~ 49 | cd firmware/bl_mcu_sdk 50 | make clean 51 | make BOARD=bl702_debugger APP_DIR=../app APP=usb2dualuart 52 | ~~~ 53 | The firmware is './out/app/usb2dualuart/usb2dualuart_bl702.bin'. 54 | 55 | ## flash firmware 56 | 57 | Hold "boot" button down, then plug usb cable to PC USB port, and you will see "CDC Virtual ComPort" in device manager , remember the com number. 58 | 59 | The flash tool is in tools/bflb_flash_tool directory, and input the command (replace port number and firmware name): 60 | 61 | Windows: 62 | ~~~ 63 | .\bflb_mcu_tool.exe --chipname=bl702 --port=COM9 --xtal=32M --firmware="" 64 | ~~~ 65 | 66 | Linux: 67 | ~~~ 68 | ./bflb_mcu_tool --chipname=bl702 --port=/dev/ttyACM0 --xtal=32M --firmware="" 69 | ~~~ 70 | 71 | The output looks like: 72 | ~~~ 73 | tools\bflb_flash_tool> .\bflb_mcu_tool.exe --chipname=bl702 --port=COM9 --xtal=32M --firmware="main.bin" 74 | [22:07:28.296] - ================================================== 75 | [22:07:28.296] - Chip name is bl702 76 | [22:07:28.297] - Serial port is COM9 77 | [22:07:28.299] - Baudrate is 115200 78 | [22:07:28.299] - Firmware is main.bin 79 | [22:07:28.300] - Default flash clock is 72M 80 | [22:07:28.300] - Default pll clock is 144M 81 | [22:07:28.311] - ================================================== 82 | [22:07:28.483] - Update flash cfg finished 83 | [22:07:28.500] - EFUSE_CFG 84 | [22:07:28.500] - BOOTHEADER_CFG 85 | ...... 86 | [22:07:31.274] - Load 53856/53856 {"progress":100} 87 | [22:07:31.274] - Write check 88 | [22:07:31.274] - Flash load time cost(ms): 267.942626953125 89 | [22:07:31.275] - Finished 90 | [22:07:31.276] - Sha caled by host: 825d198270c2cf509acda8f8e0830751c532da802060c324a4479e1fe599ae1f 91 | [22:07:31.276] - xip mode Verify 92 | [22:07:31.288] - Read Sha256/53856 93 | [22:07:31.288] - Flash xip readsha time cost(ms): 12.508056640625 94 | [22:07:31.288] - Finished 95 | [22:07:31.288] - Sha caled by dev: 825d198270c2cf509acda8f8e0830751c532da802060c324a4479e1fe599ae1f 96 | [22:07:31.288] - Verify success 97 | [22:07:31.289] - Program Finished 98 | [22:07:31.289] - All time cost(ms): 2220.2548828125 99 | [22:07:31.390] - [All Success] 100 | ~~~ 101 | 102 | Another GUI flash tool is BouffaloLabDevCube: 103 | - [Bouffalo Lab Dev Cube For Windows](https://dev.bouffalolab.com/media/upload/download/BouffaloLabDevCube-1.5.2-win32.zip) 104 | - [Bouffalo Lab Dev Cube For Ubuntu](https://dev.bouffalolab.com/media/upload/download/BouffaloLabDevCube-1.5.2-linux-x86.tar.gz) 105 | 106 | ## usb2uartjtag (default) 107 | 108 | Support JTAG+UART function 109 | 110 | UART support baudrate below 2Mbps, and 3Mbps, and some experimental baudrate (stability is not guaranteed): 111 | 112 | ~~~ 113 | 12M, 9.6M, 8M, 6.4M, 6M, 4.8M, 4M, 3.2M 114 | we remap baudrate in 10000~12000 to (baud-10000)*10000 115 | for example, 11200bps -> 12Mbps 116 | ~~~ 117 | 118 | LED0 for RX indication, LED1 for TX indication. 119 | 120 | JTAG function is verified for : 121 | 122 | - RV32 Xuantie E906/E907 123 | - RV64 Xuantie C906 124 | - Gowin FPGA GW1N-1, GW1NS-4C. (need enable GOWIN_INT_FLASH_QUIRK) 125 | 126 | ## usb2dualuart 127 | TODO. 128 | 129 | 130 | # Project Structure 131 | 132 | ``` 133 | RV-Debugger-BL702 134 | ├── firmware 135 | │   ├── app 136 | │   │   ├── usb2dualuart 137 | │   │   └── usb2uartjtag 138 | │   └── bl_mcu_sdk 139 | ├── hardware 140 | ├── README.md 141 | └── res 142 | ``` 143 | BL SDK usage tutorial refer to http://bouffalolab.gitee.io/bl_mcu_sdk/ 144 | 145 | ### Code Explanation 146 | ~~~ 147 | firmware/app/usb2uartjtag: 148 | ├── main.c 149 | ├── uart_interface.c 150 | ├── jtag_process.c 151 | └── io_cfg.h //main io cfg, another file is pinmux_config.h in bsp/board/bl702_debugger 152 | components/usb_stack/class/vendor: 153 | └── usbd_ftdi.c //all FTDI vendor request process, like baudrate set, dtr/rts set, Latency_Timer 154 | ~~~ 155 | 156 | -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(BSP_COMMON_DIR ${CMAKE_SOURCE_DIR}/bsp/bsp_common) 2 | set(TARGET_REQUIRED_LIBS usb_stack) 3 | set(TARGET_REQUIRED_PRIVATE_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ftdi) 4 | set(TARGET_REQUIRED_SRCS ${BSP_COMMON_DIR}/usb/usb_dc.c 5 | ${CMAKE_CURRENT_LIST_DIR}/ftdi/ftdi_eeprom.c 6 | ${CMAKE_CURRENT_LIST_DIR}/ftdi/usbd_ftdi.c 7 | ${CMAKE_CURRENT_LIST_DIR}/usb_descriptor.c 8 | ${CMAKE_CURRENT_LIST_DIR}/uart_interface.c) 9 | set(mains main.c) 10 | generate_bin() 11 | -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/dev_cfg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "hal_gpio.h" 4 | 5 | #define UART0_TXD_PIN GPIO_PIN_15 6 | #define UART0_RXD_PIN GPIO_PIN_0 7 | #define UART0_DTR_PIN GPIO_PIN_1 8 | #define UART0_RTS_PIN GPIO_PIN_2 9 | 10 | #define UART1_TXD_PIN GPIO_PIN_26 11 | #define UART1_RXD_PIN GPIO_PIN_27 12 | #define UART1_DTR_PIN GPIO_PIN_28 13 | #define UART1_RTS_PIN GPIO_PIN_24 14 | 15 | #define LED0_PIN GPIO_PIN_9 16 | #define LED1_PIN GPIO_PIN_17 17 | -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/ftdi/ftdi_eeprom.c: -------------------------------------------------------------------------------- 1 | #include 2 | uint16_t ftdi_eeprom_info[] = { 3 | 0x0808, 0x0403, 0x6010, 0x0500, 0x32A0, 0x0008, 0x0200, 0x0e96, 4 | 0x20a4, 0x0ec4, 0x0046, 0x030e, 'S', 'I', 'P', 'E', 5 | 'E', 'D', 0x0320, 'U', 'S', 'B', ' ', 'T', 6 | 'O', ' ', 'D', 'U', 'A', 'L', 'U', 'A', 7 | 'R', 'T', 0x030e, 'S', 'I', '8', '8', '4', 8 | '8', 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 9 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 10 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x827E, 11 | }; -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/ftdi/usbd_ftdi.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usbd_ftdi.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | #include "usbd_ftdi.h" 25 | 26 | #include "usbd_core.h" 27 | 28 | /* Requests */ 29 | #define SIO_RESET_REQUEST 0x00 /* Reset the port */ 30 | #define SIO_SET_MODEM_CTRL_REQUEST 0x01 /* Set the modem control register */ 31 | #define SIO_SET_FLOW_CTRL_REQUEST 0x02 /* Set flow control register */ 32 | #define SIO_SET_BAUDRATE_REQUEST 0x03 /* Set baud rate */ 33 | #define SIO_SET_DATA_REQUEST \ 34 | 0x04 /* Set the data characteristics of the port \ 35 | */ 36 | #define SIO_POLL_MODEM_STATUS_REQUEST 0x05 37 | #define SIO_SET_EVENT_CHAR_REQUEST 0x06 38 | #define SIO_SET_ERROR_CHAR_REQUEST 0x07 39 | #define SIO_SET_LATENCY_TIMER_REQUEST 0x09 40 | #define SIO_GET_LATENCY_TIMER_REQUEST 0x0A 41 | #define SIO_SET_BITMODE_REQUEST 0x0B 42 | #define SIO_READ_PINS_REQUEST 0x0C 43 | #define SIO_READ_EEPROM_REQUEST 0x90 44 | #define SIO_WRITE_EEPROM_REQUEST 0x91 45 | #define SIO_ERASE_EEPROM_REQUEST 0x92 46 | 47 | #define SIO_DISABLE_FLOW_CTRL 0x0 48 | #define SIO_RTS_CTS_HS (0x1 << 8) 49 | #define SIO_DTR_DSR_HS (0x2 << 8) 50 | #define SIO_XON_XOFF_HS (0x4 << 8) 51 | 52 | #define SIO_SET_DTR_MASK 0x1 53 | #define SIO_SET_DTR_HIGH (1 | (SIO_SET_DTR_MASK << 8)) 54 | #define SIO_SET_DTR_LOW (0 | (SIO_SET_DTR_MASK << 8)) 55 | #define SIO_SET_RTS_MASK 0x2 56 | #define SIO_SET_RTS_HIGH (2 | (SIO_SET_RTS_MASK << 8)) 57 | #define SIO_SET_RTS_LOW (0 | (SIO_SET_RTS_MASK << 8)) 58 | 59 | #define SIO_RTS_CTS_HS (0x1 << 8) 60 | 61 | static volatile uint32_t sof_tick = 0; 62 | static uint8_t Latency_Timer[2] = {0x0004, 0x0004}; 63 | static const char *stop_name[] = {"1", "1.5", "2"}; 64 | static const char *parity_name[] = {"N", "O", "E", "M", "S"}; 65 | 66 | static void ftdi_notify_handler(uint8_t event, void *arg); 67 | static int ftdi_vendor_request_handler(struct usb_setup_packet *pSetup, 68 | uint8_t **data, uint32_t *len); 69 | 70 | static void usbd_ftdi_reset(void); 71 | static void ftdi_set_baudrate(uint32_t itdf_divisor, uint32_t *actual_baudrate); 72 | 73 | uint32_t usbd_ftdi_get_sof_tick(void) { return sof_tick; } 74 | uint32_t usbd_ftdi_get_latency_timer(uint8_t index) { 75 | return Latency_Timer[index]; 76 | } 77 | 78 | void usbd_ftdi_add_interface(usbd_class_t *class, usbd_interface_t *intf) { 79 | static usbd_class_t *last_class = NULL; 80 | 81 | if (last_class != class) { 82 | last_class = class; 83 | usbd_class_register(class); 84 | } 85 | 86 | intf->class_handler = NULL; 87 | intf->custom_handler = NULL; 88 | intf->vendor_handler = ftdi_vendor_request_handler; 89 | intf->notify_handler = ftdi_notify_handler; 90 | usbd_class_add_interface(class, intf); 91 | } 92 | 93 | __weak void usbd_ftdi_set_line_coding(uint8_t index, uint32_t baudrate, 94 | uint8_t databits, uint8_t parity, 95 | uint8_t stopbits) {} 96 | __weak void usbd_ftdi_set_dtr(uint8_t index, bool dtr) {} 97 | __weak void usbd_ftdi_set_rts(uint8_t index, bool rts) {} 98 | 99 | static void ftdi_notify_handler(uint8_t event, void *arg) { 100 | switch (event) { 101 | case USB_EVENT_RESET: 102 | usbd_ftdi_reset(); 103 | break; 104 | case USB_EVENT_SOF: 105 | sof_tick++; 106 | USBD_LOG_DBG("tick: %d\r\n", sof_tick); 107 | break; 108 | default: 109 | USBD_LOG_DBG("event 0x%x\r\n", event); 110 | break; 111 | } 112 | } 113 | 114 | static int ftdi_vendor_request_handler(struct usb_setup_packet *pSetup, 115 | uint8_t **data, uint32_t *len) { 116 | static uint32_t actual_baudrate[2] = {1200, 1200}; 117 | uint8_t _epid = pSetup->wIndexL - 1; 118 | 119 | // LOG_D( 120 | // "[ftdi] request 0x%02x(type: 0x%02x), i: 0x%04x, v: 0x%04x, l: 121 | // 0x%04x\r", pSetup->bRequest, pSetup->bmRequestType, pSetup->wIndex, 122 | // pSetup->wValue, pSetup->wLength); 123 | 124 | switch (pSetup->bRequest) { 125 | case SIO_READ_EEPROM_REQUEST: 126 | *data = (uint8_t *)&ftdi_eeprom_info[pSetup->wIndexL]; 127 | *len = 2; 128 | break; 129 | case SIO_RESET_REQUEST: 130 | 131 | break; 132 | case SIO_SET_MODEM_CTRL_REQUEST: 133 | switch (pSetup->wValue) { 134 | case SIO_SET_DTR_HIGH: 135 | // LOG_D("DTR 1\r\n"); 136 | usbd_ftdi_set_dtr(_epid, true); 137 | break; 138 | case SIO_SET_DTR_LOW: 139 | // LOG_D("DTR 0\r\n"); 140 | usbd_ftdi_set_dtr(_epid, false); 141 | break; 142 | case SIO_SET_RTS_HIGH: 143 | // LOG_D("RTS 1\r\n"); 144 | usbd_ftdi_set_rts(_epid, true); 145 | break; 146 | case SIO_SET_RTS_LOW: 147 | // LOG_D("RTS 0\r\n"); 148 | usbd_ftdi_set_rts(_epid, false); 149 | break; 150 | default: 151 | break; 152 | } 153 | break; 154 | case SIO_SET_FLOW_CTRL_REQUEST: 155 | 156 | break; 157 | case SIO_SET_BAUDRATE_REQUEST: // wValue,2个字节波特率 158 | { 159 | ftdi_set_baudrate(pSetup->wValue | ((pSetup->wIndexH) << 16), 160 | &actual_baudrate[_epid]); 161 | if (actual_baudrate[_epid] != 1200) { 162 | // USBD_LOG("CDC_SET_LINE_CODING <%d %d %s 163 | // %s>\r\n",actual_baudrate,(uint8_t)pSetup->wValue,parity_name[(uint8_t)(pSetup->wValue>>8)],stop_name[(uint8_t)(pSetup->wValue>>11)]); 164 | usbd_ftdi_set_line_coding( 165 | _epid, actual_baudrate[_epid], 8, 166 | 0, 0); 167 | } 168 | break; 169 | } 170 | case SIO_SET_DATA_REQUEST: 171 | /** 172 | * D0-D7 databits BITS_7=7, BITS_8=8 173 | * D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4 174 | * D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2 175 | * D14 BREAK_OFF=0, BREAK_ON=1 176 | **/ 177 | if (actual_baudrate[_epid] != 1200) { 178 | // USBD_LOG("CDC_SET_LINE_CODING <%d %d %s 179 | // %s>\r\n",actual_baudrate,(uint8_t)pSetup->wValue,parity_name[(uint8_t)(pSetup->wValue>>8)],stop_name[(uint8_t)(pSetup->wValue>>11)]); 180 | usbd_ftdi_set_line_coding( 181 | _epid, actual_baudrate[_epid], (uint8_t)pSetup->wValue, 182 | (uint8_t)(pSetup->wValue >> 8), (uint8_t)(pSetup->wValue >> 11)); 183 | } 184 | break; 185 | 186 | case SIO_POLL_MODEM_STATUS_REQUEST: 187 | // Poll modem status information 188 | 189 | // This function allows the retrieve the two status bytes of the 190 | // device. The device sends these bytes also as a header for each read 191 | // access where they are discarded by ftdi_read_data(). The chip 192 | // generates the two stripped status bytes in the absence of data every 193 | // 40 ms. 194 | 195 | // Layout of the first byte: 196 | // - B0..B3 - must be 0 197 | // - B4 Clear to send (CTS) 198 | // 0 = inactive 199 | // 1 = active 200 | // - B5 Data set ready (DTS) 201 | // 0 = inactive 202 | // 1 = active 203 | // - B6 Ring indicator (RI) 204 | // 0 = inactive 205 | // 1 = active 206 | // - B7 Receive line signal detect (RLSD) 207 | // 0 = inactive 208 | // 1 = active 209 | 210 | // Layout of the second byte: 211 | // - B0 Data ready (DR) 212 | // - B1 Overrun error (OE) 213 | // - B2 Parity error (PE) 214 | // - B3 Framing error (FE) 215 | // - B4 Break interrupt (BI) 216 | // - B5 Transmitter holding register (THRE) 217 | // - B6 Transmitter empty (TEMT) 218 | // - B7 Error in RCVR FIFO 219 | *data = (uint8_t *)&ftdi_eeprom_info[2]; 220 | *len = 2; 221 | break; 222 | case SIO_SET_EVENT_CHAR_REQUEST: 223 | 224 | break; 225 | case SIO_SET_ERROR_CHAR_REQUEST: 226 | 227 | break; 228 | case SIO_SET_LATENCY_TIMER_REQUEST: 229 | // Latency_Timer[_epid] = pSetup->wValueL; 230 | Latency_Timer[_epid] = 0x10; 231 | break; 232 | case SIO_GET_LATENCY_TIMER_REQUEST: 233 | *data = &Latency_Timer[_epid]; 234 | *len = 1; 235 | USBD_LOG_DBG("get latency%d:%d,len:%d\r\n", _epid, **data, *len); 236 | break; 237 | case SIO_SET_BITMODE_REQUEST: 238 | 239 | break; 240 | default: 241 | return -1; 242 | } 243 | return 0; 244 | } 245 | 246 | static void usbd_ftdi_reset(void) { 247 | sof_tick = 0; 248 | for (size_t i = 0; i < 2; i++) { 249 | Latency_Timer[i] = 0x0010; 250 | } 251 | } 252 | 253 | static void ftdi_set_baudrate(uint32_t itdf_divisor, 254 | uint32_t *actual_baudrate) { 255 | #define FTDI_USB_CLK 48000000 256 | int baudrate; 257 | uint8_t frac[] = {0, 8, 4, 2, 6, 10, 12, 14}; 258 | int divisor = itdf_divisor & 0x3fff; 259 | divisor <<= 4; 260 | divisor |= frac[(itdf_divisor >> 14) & 0x07]; 261 | 262 | if (itdf_divisor == 0x01) { 263 | baudrate = 2000000; 264 | } else if (itdf_divisor == 0x00) { 265 | baudrate = 3000000; 266 | } else { 267 | baudrate = FTDI_USB_CLK / divisor; 268 | } 269 | 270 | if (baudrate > 10000 && baudrate < 12000) { 271 | *actual_baudrate = (baudrate - 10000) * 10000; 272 | } else { 273 | *actual_baudrate = baudrate; 274 | } 275 | } -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/ftdi/usbd_ftdi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usbd_ftdi.h 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | #ifndef _USBD_FTDI_H 24 | #define _USBD_FTDI_H 25 | 26 | #include "usbd_core.h" 27 | 28 | extern uint16_t ftdi_eeprom_info[]; 29 | 30 | void usbd_ftdi_add_interface(usbd_class_t *class, usbd_interface_t *intf); 31 | uint32_t usbd_ftdi_get_sof_tick(void); 32 | uint32_t usbd_ftdi_get_latency_timer(uint8_t index); 33 | 34 | /* to be impl */ 35 | void usbd_ftdi_set_line_coding(uint8_t index, uint32_t baudrate, 36 | uint8_t databits, uint8_t parity, 37 | uint8_t stopbits); 38 | void usbd_ftdi_set_dtr(uint8_t index, bool dtr); 39 | void usbd_ftdi_set_rts(uint8_t index, bool rts); 40 | #endif /* USB_FTDI_H_ */ 41 | -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Bouffalolab team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | #include "main.h" 25 | 26 | #include "bflb_platform.h" 27 | #include "hal_uart.h" 28 | #include "hal_usb.h" 29 | #include "usbd_core.h" 30 | 31 | /* ring buffer */ 32 | #define USB_OUT_RINGBUFFER_SIZE (8 * 1024) 33 | #define UART_RX_RINGBUFFER_SIZE (8 * 1024) 34 | static uint8_t usb_rx_mem[2][USB_OUT_RINGBUFFER_SIZE] 35 | __attribute__((section(".system_ram"))); 36 | static uint8_t uart_rx_mem[2][UART_RX_RINGBUFFER_SIZE] 37 | __attribute__((section(".system_ram"))); 38 | static Ring_Buffer_Type usb_rx_rb[2]; 39 | static Ring_Buffer_Type uart_rx_rb[2]; 40 | 41 | /* private function */ 42 | static void led_gpio_init(void); 43 | static void usb_ringbuffer_init(void); 44 | static void uart_ringbuffer_init(void); 45 | static void uart_irq_callback(struct device *dev, void *args, uint32_t size, 46 | uint32_t state); 47 | static int usb_dc_ftdi_send_from_ringbuffer(struct device *dev, 48 | Ring_Buffer_Type *rb, uint8_t ep); 49 | static int usb_dc_ftdi_receive_to_ringbuffer(struct device *dev, 50 | Ring_Buffer_Type *rb, uint8_t ep); 51 | static void usbd_cdc_acm_bulk_out(uint8_t ep); 52 | static void usbd_cdc_acm_bulk_in(uint8_t ep); 53 | 54 | static struct device *usb_fs; 55 | static usbd_class_t ftdi_class[2]; 56 | static usbd_interface_t ftdi_data_intf[2]; 57 | static usbd_endpoint_t ftdi_in_ep[2] = { 58 | {.ep_addr = FTDI_IN_0_EP, .ep_cb = usbd_cdc_acm_bulk_in}, 59 | {.ep_addr = FTDI_IN_1_EP, .ep_cb = usbd_cdc_acm_bulk_in}}; 60 | static usbd_endpoint_t ftdi_out_ep[2] = { 61 | {.ep_addr = FTDI_OUT_0_EP, .ep_cb = usbd_cdc_acm_bulk_out}, 62 | {.ep_addr = FTDI_OUT_1_EP, .ep_cb = usbd_cdc_acm_bulk_out}}; 63 | 64 | /* external funtion and data */ 65 | extern struct device *usb_dc_init(void); 66 | extern USB_DESC_SECTION uint8_t usb_descriptor[]; 67 | 68 | // enum uart_index_type board_get_debug_uart_index(void) { return 1; } 69 | 70 | int main(void) { 71 | /* disable debug for uart0 */ 72 | bflb_platform_print_set(1); 73 | led_gpio_init(); 74 | led_set(0, 1); /* led0 on */ 75 | led_set(1, 0); /* led1 off */ 76 | bflb_platform_init(0); 77 | usb_ringbuffer_init(); 78 | uart_ringbuffer_init(); 79 | uart_set_dtr_rts(0, UART0_DTR_PIN, UART0_RTS_PIN); 80 | uart_set_dtr_rts(1, UART1_DTR_PIN, UART1_RTS_PIN); 81 | uart_dtr_init(0); 82 | uart_dtr_init(1); 83 | uart_init(0, uart_irq_callback); 84 | uart_init(1, uart_irq_callback); 85 | 86 | /* update USB_VID,PID,BCD */ 87 | memcpy((void *)&usb_descriptor[8], (void *)&ftdi_eeprom_info[1], 88 | 3 * sizeof(uint16_t)); 89 | 90 | usbd_desc_register(usb_descriptor); 91 | for (size_t i = 0; i < 2; i++) { 92 | usbd_ftdi_add_interface(&ftdi_class[i], &ftdi_data_intf[i]); 93 | usbd_interface_add_endpoint(&ftdi_data_intf[i], &ftdi_in_ep[i]); 94 | usbd_interface_add_endpoint(&ftdi_data_intf[i], &ftdi_out_ep[i]); 95 | } 96 | 97 | usb_fs = usb_dc_init(); 98 | if (usb_fs) { 99 | device_control( 100 | usb_fs, DEVICE_CTRL_SET_INT, 101 | (void *)(USB_SOF_IT | USB_EP1_DATA_IN_IT | USB_EP2_DATA_OUT_IT | 102 | USB_EP3_DATA_IN_IT | USB_EP4_DATA_OUT_IT)); 103 | } 104 | while (!usb_device_is_configured()) { 105 | } 106 | 107 | led_set(1, 1); /* led1 on */ 108 | 109 | while (1) { 110 | uart_send_from_ringbuffer(0, &usb_rx_rb[0]); 111 | uart_send_from_ringbuffer(1, &usb_rx_rb[1]); 112 | } 113 | 114 | return 0; 115 | } 116 | 117 | /************************ led ctrl functions ************************/ 118 | static uint32_t led_pins[2] = {LED0_PIN, LED1_PIN}; 119 | static volatile uint8_t led_stat[2] = {0, 0}; 120 | static void led_gpio_init(void) { 121 | gpio_set_mode(led_pins[0], GPIO_OUTPUT_MODE); 122 | gpio_set_mode(led_pins[1], GPIO_OUTPUT_MODE); 123 | led_set(0, led_stat[0]); 124 | led_set(1, led_stat[1]); 125 | return; 126 | } 127 | 128 | void led_set(uint8_t idx, uint8_t status) { 129 | gpio_write(led_pins[idx], !status); 130 | led_stat[idx] = status; 131 | return; 132 | } 133 | 134 | void led_toggle(uint8_t idx) { 135 | led_stat[idx] = !led_stat[idx]; 136 | gpio_write(led_pins[idx], !led_stat[idx]); 137 | return; 138 | } 139 | 140 | /************************ API for usbd_ftdi ************************/ 141 | void usbd_ftdi_set_line_coding(uint8_t index, uint32_t baudrate, 142 | uint8_t databits, uint8_t parity, 143 | uint8_t stopbits) { 144 | uart_config(index, baudrate, databits, parity, stopbits); 145 | Ring_Buffer_Reset(&uart_rx_rb[index]); 146 | Ring_Buffer_Reset(&usb_rx_rb[index]); 147 | } 148 | void usbd_ftdi_set_dtr(uint8_t index, bool dtr) { dtr_pin_set(index, !dtr); } 149 | void usbd_ftdi_set_rts(uint8_t index, bool rts) { rts_pin_set(index, !rts); } 150 | 151 | /* init ring_buffer for usb */ 152 | static void usb_ringbuffer_init(void) { 153 | for (size_t i = 0; i < 2; i++) { 154 | /* init mem for ring_buffer */ 155 | memset(usb_rx_mem[i], 0, USB_OUT_RINGBUFFER_SIZE); 156 | 157 | /* init ring_buffer */ 158 | Ring_Buffer_Init(&usb_rx_rb[i], usb_rx_mem[i], USB_OUT_RINGBUFFER_SIZE, 159 | cpu_global_irq_disable, cpu_global_irq_enable); 160 | } 161 | } 162 | 163 | static void uart_ringbuffer_init(void) { 164 | for (size_t i = 0; i < 2; i++) { 165 | /* init mem for ring_buffer */ 166 | memset(uart_rx_mem[i], 0, UART_RX_RINGBUFFER_SIZE); 167 | 168 | /* init ring_buffer */ 169 | Ring_Buffer_Init(&uart_rx_rb[i], uart_rx_mem[i], UART_RX_RINGBUFFER_SIZE, 170 | cpu_global_irq_disable, cpu_global_irq_enable); 171 | } 172 | } 173 | 174 | /* USB out -> UART tx */ 175 | static void usbd_cdc_acm_bulk_out(uint8_t ep) { 176 | size_t _epid = (USB_EP_GET_IDX(ep) - 1) / 2; 177 | usb_dc_ftdi_receive_to_ringbuffer(usb_fs, &usb_rx_rb[_epid], ep); 178 | } 179 | /* UART rx -> USB in */ 180 | static void usbd_cdc_acm_bulk_in(uint8_t ep) { 181 | size_t _epid = (USB_EP_GET_IDX(ep) - 1) / 2; 182 | usb_dc_ftdi_send_from_ringbuffer(usb_fs, &uart_rx_rb[_epid], ep); 183 | // usb_dc_ftdi_send_from_ringbuffer(usb_fs, &usb_rx_rb[_epid], ep); 184 | } 185 | 186 | #include "bl702_usb.h" 187 | static int usb_dc_ftdi_receive_to_ringbuffer(struct device *dev, 188 | Ring_Buffer_Type *rb, uint8_t ep) { 189 | size_t _epid; 190 | uint8_t ep_idx; 191 | uint8_t recv_len; 192 | uint32_t timeout = 0x0000FFFF; 193 | static bool overflow_flag[2] = {false, false}; 194 | 195 | /* Check if OUT ep */ 196 | if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) { 197 | return -USB_DC_EP_DIR_ERR; 198 | } 199 | 200 | ep_idx = USB_EP_GET_IDX(ep); 201 | _epid = (ep_idx - 1) / 2; 202 | 203 | while (!USB_Is_EPx_RDY_Free(ep_idx)) { 204 | timeout--; 205 | if (!timeout) { 206 | LOG_E("ep%d wait free timeout\r\n", ep); 207 | return -USB_DC_EP_TIMEOUT_ERR; 208 | } 209 | } 210 | 211 | recv_len = USB_Get_EPx_RX_FIFO_CNT(ep_idx); 212 | 213 | /*if rx fifo count equal 0,it means last is send nack and ringbuffer is 214 | * smaller than 64, so,if ringbuffer is larger than 64,set ack to recv next 215 | * data. 216 | */ 217 | if (overflow_flag[_epid] && (Ring_Buffer_Get_Empty_Length(rb) > 64) && 218 | (!recv_len)) { 219 | overflow_flag[_epid] = false; 220 | USB_Set_EPx_Rdy(ep_idx); 221 | return 0; 222 | } else { 223 | uint32_t addr = USB_BASE + 0x11C + (ep_idx - 1) * 0x10; 224 | Ring_Buffer_Write_Callback(rb, recv_len, fifocopy_to_mem, (void *)addr); 225 | 226 | if (Ring_Buffer_Get_Empty_Length(rb) < 64) { 227 | overflow_flag[_epid] = true; 228 | return -USB_DC_RB_SIZE_SMALL_ERR; 229 | } 230 | 231 | USB_Set_EPx_Rdy(ep_idx); 232 | return 0; 233 | } 234 | } 235 | 236 | static int usb_dc_ftdi_send_from_ringbuffer(struct device *dev, 237 | Ring_Buffer_Type *rb, uint8_t ep) { 238 | size_t _epid; 239 | uint8_t ep_idx; 240 | uint32_t timeout = 0x0000FFFF; 241 | static uint8_t ftdi_header[2] = {0x01, 0x60}; 242 | static uint64_t last_send[2] = {0, 0}; 243 | 244 | ep_idx = USB_EP_GET_IDX(ep); 245 | _epid = (ep_idx - 1) / 2; 246 | 247 | /* Check if IN ep */ 248 | if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) { 249 | return -USB_DC_EP_DIR_ERR; 250 | } 251 | 252 | while (!USB_Is_EPx_RDY_Free(ep_idx)) { 253 | timeout--; 254 | if (!timeout) { 255 | LOG_E("ep%d wait free timeout\r\n", ep); 256 | return -USB_DC_EP_TIMEOUT_ERR; 257 | } 258 | } 259 | 260 | uint32_t addr = USB_BASE + 0x118 + (ep_idx - 1) * 0x10; 261 | 262 | if ((USB_Get_EPx_TX_FIFO_CNT(ep_idx) == USB_FS_MAX_PACKET_SIZE) && 263 | Ring_Buffer_Get_Length(rb) >= USB_FS_MAX_PACKET_SIZE - 2) { 264 | memcopy_to_fifo((void *)addr, (uint8_t *)ftdi_header, 2); 265 | Ring_Buffer_Read_Callback(rb, USB_FS_MAX_PACKET_SIZE - 2, memcopy_to_fifo, 266 | (void *)addr); 267 | 268 | USB_Set_EPx_Rdy(ep_idx); 269 | last_send[_epid] = bflb_platform_get_time_us(); 270 | return 0; 271 | } else { 272 | uint64_t Latency_Timer = usbd_ftdi_get_latency_timer(_epid); 273 | if (bflb_platform_get_time_us() - last_send[_epid] >= 274 | Latency_Timer * 1000) { 275 | memcopy_to_fifo((void *)addr, (uint8_t *)ftdi_header, 2); 276 | Ring_Buffer_Read_Callback(rb, Ring_Buffer_Get_Length(rb), memcopy_to_fifo, 277 | (void *)addr); 278 | 279 | USB_Set_EPx_Rdy(ep_idx); 280 | last_send[_epid] = bflb_platform_get_time_us(); 281 | } 282 | return -USB_DC_RB_SIZE_SMALL_ERR; 283 | } 284 | } 285 | 286 | static void uart_irq_callback(struct device *dev, void *args, uint32_t size, 287 | uint32_t state) { 288 | uint8_t _idx = UART_DEV(dev)->id; 289 | switch (state) { 290 | case UART_EVENT_RX_FIFO: 291 | case UART_EVENT_RTO: 292 | if (size && size < Ring_Buffer_Get_Empty_Length(&uart_rx_rb[_idx])) { 293 | Ring_Buffer_Write(&uart_rx_rb[_idx], (uint8_t *)args, size); 294 | led_toggle(_idx); 295 | } else { 296 | LOG_E(state == UART_EVENT_RX_FIFO ? "RF\r\n" : "RTO\r\n"); 297 | } 298 | break; 299 | case UART_RX_FER_IT: 300 | LOG_E("OV\r\n"); 301 | break; 302 | 303 | default: 304 | break; 305 | } 306 | } -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dev_cfg.h" 4 | #include "ftdi/usbd_ftdi.h" 5 | #include "hal_usb.h" 6 | #include "uart_interface.h" 7 | 8 | #define FTDI_IN_0_EP USB_SET_EP_IN(1) 9 | #define FTDI_OUT_0_EP USB_SET_EP_OUT(2) 10 | #define FTDI_IN_1_EP USB_SET_EP_IN(3) 11 | #define FTDI_OUT_1_EP USB_SET_EP_OUT(4) 12 | 13 | #define USBD_VID (0x0403) 14 | #define USBD_PID (0x6010) 15 | #define USBD_BCD (0x0500) 16 | #define USBD_MAX_POWER (90) /* 90/2 = 45 */ 17 | #define USBD_LANGID_STRING (0x0409) 18 | 19 | void led_set(uint8_t idx, uint8_t status); 20 | void led_toggle(uint8_t idx); -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/uart_interface.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file uart_interface.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | #include "uart_interface.h" 25 | 26 | #include "bflb_platform.h" 27 | #include "hal_dma.h" 28 | #include "hal_gpio.h" 29 | #include "hal_usb.h" 30 | 31 | #define UART_TX_DMA_SIZE (4095) 32 | static uint8_t src_buffer[2][UART_TX_DMA_SIZE] 33 | __attribute__((section(".system_ram"))); 34 | 35 | static struct device *uart[2] = {NULL, NULL}; 36 | static struct device *dma_ch[2] = {NULL, NULL}; 37 | 38 | void uart_init(uint8_t index, void (*callback)(struct device *dev, void *args, 39 | uint32_t size, uint32_t event)) { 40 | if (index == 0) { 41 | uart_register(UART0_INDEX, "uart0"); 42 | dma_register(DMA0_CH1_INDEX, "ch1"); 43 | uart[0] = device_find("uart0"); 44 | dma_ch[0] = device_find("ch1"); 45 | 46 | } else if (index == 1) { 47 | uart_register(UART1_INDEX, "uart1"); 48 | dma_register(DMA0_CH2_INDEX, "ch2"); 49 | uart[1] = device_find("uart1"); 50 | dma_ch[1] = device_find("ch2"); 51 | } 52 | 53 | if (uart[index] && dma_ch[index]) { 54 | device_open(uart[index], 55 | DEVICE_OFLAG_DMA_TX | DEVICE_OFLAG_INT_RX); // uart tx dma mode 56 | // device_control(uart[index], DEVICE_CTRL_SUSPEND, NULL); 57 | device_set_callback(uart[index], callback); 58 | device_control(uart[index], DEVICE_CTRL_SET_INT, 59 | (void *)(UART_RX_FIFO_IT | UART_RTO_IT)); 60 | 61 | device_open(dma_ch[index], 0); 62 | device_control(uart[index], DEVICE_CTRL_ATTACH_TX_DMA, dma_ch[index]); 63 | } 64 | } 65 | 66 | void uart_config(uint8_t index, uint32_t baudrate, uart_databits_t databits, 67 | uart_parity_t parity, uart_stopbits_t stopbits) { 68 | uart_param_cfg_t cfg; 69 | cfg.baudrate = baudrate; 70 | cfg.stopbits = stopbits; 71 | cfg.parity = parity; 72 | cfg.databits = (databits - 5); 73 | if (uart[index]) { 74 | device_control(uart[index], DEVICE_CTRL_CONFIG, &cfg); 75 | device_control(uart[index], DEVICE_CTRL_RESUME, NULL); 76 | } 77 | } 78 | 79 | static uint8_t uart_dtr[2]; 80 | static uint8_t uart_rts[2]; 81 | 82 | void uart_set_dtr_rts(uint8_t index, uint8_t dtr, uint8_t rts) { 83 | uart_dtr[index] = dtr; 84 | uart_rts[index] = rts; 85 | } 86 | void uart_dtr_init(uint8_t index) { 87 | gpio_set_mode(uart_dtr[index], GPIO_OUTPUT_MODE); 88 | } 89 | void uart_rts_init(uint8_t index) { 90 | gpio_set_mode(uart_rts[index], GPIO_OUTPUT_MODE); 91 | } 92 | void uart_dtr_deinit(uint8_t index) { 93 | gpio_set_mode(uart_dtr[index], GPIO_INPUT_MODE); 94 | } 95 | void uart_rts_deinit(uint8_t index) { 96 | gpio_set_mode(uart_rts[index], GPIO_INPUT_MODE); 97 | } 98 | void dtr_pin_set(uint8_t index, uint8_t status) { 99 | gpio_write(uart_dtr[index], status); 100 | } 101 | void rts_pin_set(uint8_t index, uint8_t status) { 102 | gpio_write(uart_rts[index], status); 103 | } 104 | 105 | static dma_control_data_t uart_dma_ctrl_cfg = { 106 | .bits.fix_cnt = 0, 107 | .bits.dst_min_mode = 0, 108 | .bits.dst_add_mode = 0, 109 | .bits.SI = 1, 110 | .bits.DI = 0, 111 | .bits.SWidth = DMA_TRANSFER_WIDTH_8BIT, 112 | .bits.DWidth = DMA_TRANSFER_WIDTH_8BIT, 113 | .bits.SBSize = 0, 114 | .bits.DBSize = 0, 115 | .bits.I = 0, 116 | .bits.TransferSize = UART_TX_DMA_SIZE}; 117 | static dma_lli_ctrl_t uart_lli_list[2] = {{.src_addr = (uint32_t)src_buffer[0], 118 | .dst_addr = DMA_ADDR_UART0_TDR, 119 | .nextlli = 0}, 120 | {.src_addr = (uint32_t)src_buffer[1], 121 | .dst_addr = DMA_ADDR_UART1_TDR, 122 | .nextlli = 0}}; 123 | 124 | void uart_send_from_ringbuffer(uint8_t index, Ring_Buffer_Type *rb) { 125 | if (Ring_Buffer_Get_Length(rb)) { 126 | if (!dma_channel_check_busy(dma_ch[index])) { 127 | uint32_t avalibleCnt = 128 | Ring_Buffer_Read(rb, src_buffer[index], UART_TX_DMA_SIZE); 129 | if (avalibleCnt) { 130 | uart_dma_ctrl_cfg.bits.TransferSize = avalibleCnt; 131 | memcpy(&uart_lli_list[index].cfg, &uart_dma_ctrl_cfg, 132 | sizeof(dma_control_data_t)); 133 | dma_channel_stop(dma_ch[index]); 134 | dma_channel_update(dma_ch[index], (void *)(&uart_lli_list[index])); 135 | dma_channel_start(dma_ch[index]); 136 | // TX indication 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/uart_interface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "hal_uart.h" 4 | #include "ring_buffer.h" 5 | 6 | 7 | void uart_init(uint8_t index, void (*callback)(struct device *dev, void *args, 8 | uint32_t size, uint32_t event)); 9 | void uart_config(uint8_t index, uint32_t baudrate, uart_databits_t databits, 10 | uart_parity_t parity, uart_stopbits_t stopbits); 11 | void uart_set_dtr_rts(uint8_t index, uint8_t dtr, uint8_t rts); 12 | void uart_dtr_init(uint8_t index); 13 | void uart_rts_init(uint8_t index); 14 | void uart_dtr_deinit(uint8_t index); 15 | void uart_rts_deinit(uint8_t index); 16 | void dtr_pin_set(uint8_t index, uint8_t status); 17 | void rts_pin_set(uint8_t index, uint8_t status); 18 | void uart_send_from_ringbuffer(uint8_t index, Ring_Buffer_Type *rb); -------------------------------------------------------------------------------- /firmware/app/usb2dualuart/usb_descriptor.c: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | #define FTDI_DESCRIPITOR_LEN (9 + 7 + 7 + 9 + 7 + 7) 4 | #define USB_CONFIG_SIZE (9 + FTDI_DESCRIPITOR_LEN) 5 | 6 | USB_DESC_SECTION uint8_t usb_descriptor[] = { 7 | /////////////////////////////////////// 8 | /// device descriptor 9 | /////////////////////////////////////// 10 | USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 11 | USBD_BCD, 0x01), 12 | 13 | /////////////////////////////////////// 14 | /// config descriptor 15 | /////////////////////////////////////// 16 | USB_CONFIG_DESCRIPTOR_INIT( 17 | USB_CONFIG_SIZE, 0x02, 0x01, 18 | (USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP), USBD_MAX_POWER), 19 | 20 | /////////////////////////////////////// 21 | /// interface0 descriptor 22 | /////////////////////////////////////// 23 | USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 24 | USB_DEVICE_CLASS_VEND_SPECIFIC, 0xff, 0xff, 25 | USB_STRING_LANGID_INDEX), 26 | USB_ENDPOINT_DESCRIPTOR_INIT(FTDI_IN_0_EP, USB_ENDPOINT_TYPE_BULK, 0x0040, 27 | 0x01), 28 | USB_ENDPOINT_DESCRIPTOR_INIT(FTDI_OUT_0_EP, USB_ENDPOINT_TYPE_BULK, 0x0040, 29 | 0x01), 30 | 31 | /////////////////////////////////////// 32 | /// interface1 descriptor 33 | /////////////////////////////////////// 34 | USB_INTERFACE_DESCRIPTOR_INIT(0x01, 0x00, 0x02, 35 | USB_DEVICE_CLASS_VEND_SPECIFIC, 0xff, 0xff, 36 | USB_STRING_LANGID_INDEX), 37 | USB_ENDPOINT_DESCRIPTOR_INIT(FTDI_IN_1_EP, USB_ENDPOINT_TYPE_BULK, 0x0040, 38 | 0x01), 39 | USB_ENDPOINT_DESCRIPTOR_INIT(FTDI_OUT_1_EP, USB_ENDPOINT_TYPE_BULK, 0x0040, 40 | 0x01), 41 | 42 | /////////////////////////////////////// 43 | /// string0 descriptor (LANGID) 44 | /////////////////////////////////////// 45 | USB_LANGID_INIT(USBD_LANGID_STRING), 46 | /////////////////////////////////////// 47 | /// string1 descriptor (MFC) 48 | /////////////////////////////////////// 49 | 0x0E, /* bLength */ 50 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 51 | 'S', 0x00, /* wcChar0 */ 52 | 'I', 0x00, /* wcChar1 */ 53 | 'P', 0x00, /* wcChar2 */ 54 | 'E', 0x00, /* wcChar3 */ 55 | 'E', 0x00, /* wcChar4 */ 56 | 'D', 0x00, /* wcChar5 */ 57 | /////////////////////////////////////// 58 | /// string2 descriptor (PRODUCT) 59 | /////////////////////////////////////// 60 | 0x20, /* bLength */ 61 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 62 | 'U', 0x00, /* wcChar0 */ 63 | 'S', 0x00, /* wcChar1 */ 64 | 'B', 0x00, /* wcChar2 */ 65 | ' ', 0x00, /* wcChar3 */ 66 | 'T', 0x00, /* wcChar4 */ 67 | 'O', 0x00, /* wcChar5 */ 68 | ' ', 0x00, /* wcChar6 */ 69 | 'D', 0x00, /* wcChar7 */ 70 | 'U', 0x00, /* wcChar8 */ 71 | 'A', 0x00, /* wcChar9 */ 72 | 'L', 0x00, /* wcChar10 */ 73 | 'U', 0x00, /* wcChar11 */ 74 | 'A', 0x00, /* wcChar12 */ 75 | 'R', 0x00, /* wcChar13 */ 76 | 'T', 0x00, /* wcChar14 */ 77 | /////////////////////////////////////// 78 | /// string3 descriptor (SERIAL) 79 | /////////////////////////////////////// 80 | 0x0E, /* bLength */ 81 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 82 | 'S', 0x00, /* wcChar0 */ 83 | 'I', 0x00, /* wcChar1 */ 84 | '8', 0x00, /* wcChar2 */ 85 | '8', 0x00, /* wcChar3 */ 86 | '4', 0x00, /* wcChar4 */ 87 | '8', 0x00, /* wcChar5 */ 88 | 89 | /////////////////////////////////////// 90 | /// device qualifier descriptor 91 | /////////////////////////////////////// 92 | 0x0a, USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, 0x00, 0x00, 0x00, 0x00, 0x00, 93 | 0x40, 0x01, 0x00, 94 | 95 | 0x00}; -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(BSP_COMMON_DIR ${CMAKE_SOURCE_DIR}/bsp/bsp_common) 2 | set(TARGET_REQUIRED_LIBS usb_stack) 3 | set(TARGET_REQUIRED_SRCS ${BSP_COMMON_DIR}/usb/usb_dc.c 4 | ${CMAKE_CURRENT_LIST_DIR}/usbd_ftdi.c 5 | ${CMAKE_CURRENT_LIST_DIR}/uart_interface.c 6 | ${CMAKE_CURRENT_LIST_DIR}/jtag_process.c 7 | ${CMAKE_CURRENT_LIST_DIR}/usb_descriptor.c) 8 | set(mains main.c) 9 | generate_bin() 10 | 11 | 12 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/io_cfg.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usbd_ftdi.h 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | #ifndef _IO_CFG_H 24 | #define _IO_CFG_H 25 | 26 | #define UART_TXD_PIN GPIO_PIN_26 27 | #define UART_RXD_PIN GPIO_PIN_27 28 | #define UART_DTR_PIN GPIO_PIN_28 29 | #define UART_RTS_PIN GPIO_PIN_24 30 | #define UART_CTS_PIN GPIO_PIN_25 31 | 32 | #define LED0_PIN GPIO_PIN_9 33 | #define LED1_PIN GPIO_PIN_17 34 | 35 | #define TMS_PIN GPIO_PIN_2 36 | #define TCK_PIN GPIO_PIN_15 37 | #define TDI_PIN GPIO_PIN_0 38 | #define TDO_PIN GPIO_PIN_1 39 | 40 | //UART0 for debug 41 | #define UART0_TXD_PIN GPIO_PIN_14 42 | #define UART0_RXD_PIN GPIO_PIN_23 43 | 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/jtag_process.c: -------------------------------------------------------------------------------- 1 | #include "hal_usb.h" 2 | #include "usbd_core.h" 3 | #include "usbd_ftdi.h" 4 | #include "ring_buffer.h" 5 | #include "hal_gpio.h" 6 | #include "hal_spi.h" 7 | #include "hal_pwm.h" 8 | #include "bl702_glb.h" 9 | #include "bl702_gpio.h" 10 | #include "bl702_pwm.h" 11 | #include "io_cfg.h" 12 | 13 | #define TMS_HIGH ((*(volatile uint32_t *)0x40000188) |= (1 << TMS_PIN)) 14 | #define TMS_LOW ((*(volatile uint32_t *)0x40000188) &= (~(1 << TMS_PIN))) 15 | #define TDI_HIGH ((*(volatile uint32_t *)0x40000188) |= (1 << TDI_PIN)) 16 | #define TDI_LOW ((*(volatile uint32_t *)0x40000188) &= (~(1 << TDI_PIN))) 17 | #define TCK_HIGH ((*(volatile uint32_t *)0x40000188) |= (1 << TCK_PIN)) 18 | #define TCK_LOW ((*(volatile uint32_t *)0x40000188) &= (~(1 << TCK_PIN))) 19 | #define TDO ((*(volatile uint32_t *)0x40000180) & (1 << TDO_PIN)) 20 | 21 | #define SCK_HIGH TCK_HIGH 22 | #define SCK_LOW TCK_LOW 23 | #define MOSI_HIGH TDI_HIGH 24 | #define MOSI_LOW TDI_LOW 25 | #define MISO TDO 26 | 27 | #define MPSSE_IDLE 0 28 | #define MPSSE_RCV_LENGTH_L 1 29 | #define MPSSE_RCV_LENGTH_H 2 30 | #define MPSSE_TRANSMIT_BYTE 3 31 | #define MPSSE_RCV_LENGTH 4 32 | #define MPSSE_TRANSMIT_BIT 5 33 | #define MPSSE_ERROR 6 34 | #define MPSSE_TRANSMIT_BIT_MSB 7 35 | #define MPSSE_TMS_OUT 8 36 | #define MPSSE_NO_OP_1 9 37 | #define MPSSE_NO_OP_2 10 38 | #define MPSSE_TRANSMIT_BYTE_MSB 11 39 | #define MPSSE_RUN_TEST 12 40 | 41 | #define JTAG_TX_BUFFER_SIZE (1 * 1024) 42 | #define JTAG_RX_BUFFER_SIZE (64) 43 | 44 | uint8_t jtag_tx_buffer[JTAG_TX_BUFFER_SIZE] __attribute__((section(".tcm_data"))); 45 | Ring_Buffer_Type jtag_tx_rb; 46 | 47 | uint8_t jtag_rx_buffer[JTAG_RX_BUFFER_SIZE] __attribute__((section(".tcm_data"))); 48 | static uint32_t jtag_rx_len = 0; 49 | static volatile uint32_t jtag_rx_pos __attribute__((section(".tcm_data"))); 50 | 51 | static uint32_t mpsse_longlen __attribute__((section(".tcm_data"))) = 0; 52 | static uint32_t mpsse_shortlen __attribute__((section(".tcm_data"))) = 0; 53 | static uint32_t mpsse_status __attribute__((section(".tcm_data"))) = MPSSE_IDLE; 54 | static uint32_t jtag_cmd __attribute__((section(".tcm_data"))) = 0; 55 | 56 | static volatile uint32_t jtag_received_flag __attribute__((section(".tcm_data"))) = false; 57 | 58 | extern struct device *usb_fs; 59 | 60 | static void rb_lock(void) 61 | { 62 | //disable_irq(); //no need disable irq as it is already disable in big loop 63 | } 64 | 65 | static void rb_unlock(void) 66 | { 67 | //enable_irq(); 68 | } 69 | 70 | static void jtag_write(uint8_t data) 71 | { 72 | Ring_Buffer_Write_Byte(&jtag_tx_rb, data); 73 | } 74 | 75 | void jtag_ringbuffer_init(void) 76 | { 77 | memset(jtag_tx_buffer, 0, JTAG_TX_BUFFER_SIZE); 78 | /* init ring_buffer */ 79 | Ring_Buffer_Init(&jtag_tx_rb, jtag_tx_buffer, JTAG_TX_BUFFER_SIZE, rb_lock, rb_unlock); 80 | } 81 | #if GOWIN_INT_FLASH_QUIRK 82 | static void pwm_start(void) 83 | { 84 | GLB_GPIO_Cfg_Type gpio_cfg; 85 | 86 | gpio_cfg.drive = 0; 87 | gpio_cfg.smtCtrl = 1; 88 | gpio_cfg.gpioMode = GPIO_MODE_AF; 89 | gpio_cfg.pullType = GPIO_PULL_DOWN; 90 | gpio_cfg.gpioFun = GPIO_FUN_PWM; 91 | gpio_cfg.gpioPin = GPIO_PIN_3; 92 | GLB_GPIO_Init(&gpio_cfg); 93 | PWM_Channel_Enable(3); 94 | } 95 | static void pwm_stop(void) 96 | { 97 | PWM_Channel_Disable(3); 98 | 99 | GLB_GPIO_Cfg_Type gpio_cfg; 100 | gpio_cfg.drive = 0; 101 | gpio_cfg.smtCtrl = 1; 102 | gpio_cfg.gpioMode = GPIO_MODE_OUTPUT; 103 | gpio_cfg.pullType = GPIO_PULL_NONE; 104 | gpio_cfg.gpioFun = GPIO_FUN_GPIO; 105 | gpio_cfg.gpioPin = GPIO_PIN_3; 106 | GLB_GPIO_Init(&gpio_cfg); 107 | } 108 | 109 | void pwm_init(void) 110 | { 111 | static PWM_CH_CFG_Type pwmCfg = { 112 | .ch = 3, 113 | .clk = PWM_CLK_BCLK, 114 | .stopMode = PWM_STOP_GRACEFUL, 115 | .pol = PWM_POL_NORMAL, 116 | .clkDiv = 1, 117 | .period = 28, 118 | .threshold1 = 0, 119 | .threshold2 = 14, 120 | .intPulseCnt = 0, 121 | }; 122 | PWM_Channel_Init(&pwmCfg); 123 | } 124 | #endif 125 | void jtag_gpio_init(void) 126 | { 127 | gpio_set_mode(TMS_PIN, GPIO_OUTPUT_MODE); 128 | gpio_set_mode(TDI_PIN, GPIO_OUTPUT_MODE); 129 | gpio_set_mode(TCK_PIN, GPIO_OUTPUT_MODE); 130 | gpio_set_mode(TDO_PIN, GPIO_INPUT_MODE); 131 | 132 | TMS_LOW; 133 | TDI_LOW; 134 | TCK_LOW; 135 | #if GOWIN_INT_FLASH_QUIRK 136 | pwm_init(); 137 | #endif 138 | } 139 | 140 | #if MPSSE_SPI_HW 141 | static struct device *jtag_spi; 142 | 143 | #define SPI_BASE_ADDR ((uint32_t)0x4000A200) 144 | #define SPI_MSB_FIRST() ((*(volatile uint32_t *)SPI_BASE_ADDR) &= (~(1 << 6))) 145 | #define SPI_LSB_FIRST() ((*(volatile uint32_t *)SPI_BASE_ADDR) |= (1 << 6)) 146 | 147 | static inline void spi_on(void) 148 | { 149 | /**gpio spi func*/ 150 | uint32_t temp_val = BL_RD_WORD(0x40000100); 151 | temp_val = (temp_val & (~(31 << 8))) | (4 << 8); 152 | BL_WR_WORD(0x40000100, temp_val); 153 | /**spi enable*/ 154 | (*(volatile uint32_t *)SPI_BASE_ADDR) |= (1 << 0); 155 | } 156 | static inline void spi_on(void) 157 | { 158 | /**gpio spi func*/ 159 | uint32_t temp_val = BL_RD_WORD(0x40000100 + TCK_PIN / 2 * 4); 160 | temp_val = (temp_val & (~(31 << 8))) | (4 << 8); 161 | BL_WR_WORD(0x40000100, temp_val); 162 | uint32_t temp_val = BL_RD_WORD(0x40000100 + TDO_PIN / 2 * 4); 163 | temp_val = (temp_val & (~(31 << 8))) | (4 << 8); 164 | BL_WR_WORD(0x40000100, temp_val); 165 | uint32_t temp_val = BL_RD_WORD(0x40000100 + TDI_PIN / 2 * 4); 166 | temp_val = (temp_val & (~(31 << 8))) | (4 << 8); 167 | BL_WR_WORD(0x40000100, temp_val); 168 | /**spi enable*/ 169 | (*(volatile uint32_t *)SPI_BASE_ADDR) |= (1 << 0); 170 | } 171 | static inline void spi_off(void) 172 | { 173 | /**spi disable*/ 174 | (*(volatile uint32_t *)SPI_BASE_ADDR) &= (~(1 << 0)); 175 | /**gpio func*/ 176 | uint32_t temp_val = BL_RD_WORD(0x40000100 + TCK_PIN / 2 * 4); 177 | temp_val = (temp_val & (~(31 << 8))) | (11 << 8); 178 | BL_WR_WORD(0x40000100, temp_val); 179 | uint32_t temp_val = BL_RD_WORD(0x40000100 + TDO_PIN / 2 * 4); 180 | temp_val = (temp_val & (~(31 << 8))) | (11 << 8); 181 | BL_WR_WORD(0x40000100, temp_val); 182 | uint32_t temp_val = BL_RD_WORD(0x40000100 + TDI_PIN / 2 * 4); 183 | temp_val = (temp_val & (~(31 << 8))) | (11 << 8); 184 | BL_WR_WORD(0x40000100, temp_val); 185 | } 186 | void jtag_spi_init(void) 187 | { 188 | spi_register(SPI0_INDEX, "jtag_spi", DEVICE_OFLAG_RDWR); 189 | jtag_spi = device_find("jtag_spi"); 190 | 191 | if (jtag_spi) { 192 | device_open(jtag_spi, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_STREAM_RX); 193 | } 194 | 195 | /*rx ignore disable*/ 196 | (*(volatile uint32_t *)0x4000A200) &= (~(1 << 8)); 197 | } 198 | 199 | #endif 200 | 201 | void usbd_cdc_jtag_out(uint8_t ep) 202 | { 203 | uint32_t chunk; 204 | 205 | if (!jtag_received_flag) { 206 | usbd_ep_read(ep, jtag_rx_buffer, 64, &chunk); 207 | 208 | if (chunk == 0) { 209 | //MSG("111\r\n"); 210 | return; 211 | } 212 | 213 | jtag_rx_len = chunk; 214 | // MSG("r:%d\r\n", jtag_rx_len); 215 | 216 | // bflb_platform_dump(jtag_rx_buffer, jtag_rx_len); 217 | jtag_rx_pos = 0; 218 | jtag_received_flag = true; 219 | } 220 | } 221 | 222 | extern uint16_t usb_dc_ftdi_send_from_ringbuffer(struct device *dev, Ring_Buffer_Type *rb, uint8_t ep); 223 | void usbd_cdc_jtag_in(uint8_t ep) 224 | { 225 | if (!jtag_received_flag) { 226 | usb_dc_ftdi_send_from_ringbuffer(usb_fs, &jtag_tx_rb, ep); 227 | } 228 | } 229 | 230 | ATTR_CLOCK_SECTION void jtag_process(void) 231 | { 232 | uint32_t usb_tx_data = 0; 233 | uint32_t data = 0; 234 | register volatile uint32_t *pio __asm("tp") = (volatile uint32_t *)0x40000180; 235 | 236 | if (!jtag_received_flag) { 237 | return; 238 | } 239 | 240 | cpu_global_irq_disable(); 241 | //if (jtag_received_flag) 242 | { 243 | switch (mpsse_status) { 244 | case MPSSE_IDLE: 245 | jtag_cmd = jtag_rx_buffer[jtag_rx_pos]; 246 | 247 | //MSG("cmd:0x%02x\r\n",jtag_cmd); 248 | 249 | switch (jtag_cmd) { 250 | case 0x80: 251 | case 0x82: /* 假Bit bang模式 */ 252 | mpsse_status = MPSSE_NO_OP_1; 253 | jtag_rx_pos++; 254 | break; 255 | 256 | case 0x81: 257 | case 0x83: /* 假状态 */ 258 | usb_tx_data = jtag_rx_buffer[jtag_rx_pos] - 0x80; 259 | jtag_write(usb_tx_data); 260 | jtag_rx_pos++; 261 | break; 262 | 263 | case 0x84: 264 | case 0x85: /* Loopback */ 265 | jtag_rx_pos++; 266 | break; 267 | 268 | case 0x86: /* 调速,暂时不支持 */ 269 | mpsse_status = MPSSE_NO_OP_1; 270 | jtag_rx_pos++; 271 | break; 272 | 273 | case 0x87: /* 立刻刷新缓冲 */ 274 | jtag_rx_pos++; 275 | break; 276 | 277 | case 0x19: 278 | case 0x1d: 279 | case 0x39: 280 | case 0x3d: 281 | case 0x11: 282 | case 0x15: 283 | case 0x31: 284 | case 0x35: 285 | #if MPSSE_SPI_HW 286 | spi_on(); 287 | #endif 288 | mpsse_status = MPSSE_RCV_LENGTH_L; 289 | jtag_rx_pos++; 290 | break; 291 | 292 | case 0x6b: 293 | case 0x6f: 294 | case 0x4b: 295 | case 0x4f: 296 | case 0x3b: 297 | case 0x3f: 298 | case 0x1b: 299 | case 0x1f: 300 | case 0x13: 301 | case 0x17: 302 | #if MPSSE_SPI_HW 303 | spi_off(); 304 | #endif 305 | mpsse_status = MPSSE_RCV_LENGTH; 306 | jtag_rx_pos++; 307 | break; 308 | 309 | default: 310 | usb_tx_data = 0xFA; 311 | jtag_write(usb_tx_data); 312 | mpsse_status = MPSSE_ERROR; 313 | break; 314 | } 315 | 316 | break; 317 | 318 | case MPSSE_RCV_LENGTH_L: /* 接收长度 */ 319 | mpsse_longlen = jtag_rx_buffer[jtag_rx_pos]; 320 | 321 | mpsse_status = MPSSE_RCV_LENGTH_H; 322 | jtag_rx_pos++; 323 | break; 324 | 325 | case MPSSE_RCV_LENGTH_H: 326 | mpsse_longlen |= (jtag_rx_buffer[jtag_rx_pos] << 8) & 0xff00; 327 | 328 | jtag_rx_pos++; 329 | #if GOWIN_INT_FLASH_QUIRK 330 | 331 | if ((mpsse_longlen >= 8000) && (jtag_cmd & (1 << 5)) == 0) { 332 | //SPI_OFF(); 333 | //Run_Test_Start(); 334 | pwm_start(); 335 | MSG("len:%d\r\n", mpsse_longlen); 336 | MSG("run test start\r\n"); 337 | mpsse_status = MPSSE_RUN_TEST; 338 | } else if (jtag_cmd == 0x11 || jtag_cmd == 0x31) 339 | #else 340 | if (jtag_cmd == 0x11 || jtag_cmd == 0x31 || jtag_cmd == 0x15 || jtag_cmd == 0x35) 341 | #endif 342 | { 343 | mpsse_status = MPSSE_TRANSMIT_BYTE_MSB; 344 | #if MPSSE_SPI_HW 345 | SPI_MSB_FIRST(); 346 | #endif 347 | } else { 348 | mpsse_status = MPSSE_TRANSMIT_BYTE; 349 | #if MPSSE_SPI_HW 350 | SPI_LSB_FIRST(); 351 | #endif 352 | } 353 | 354 | break; 355 | 356 | case MPSSE_TRANSMIT_BYTE: 357 | // __asm volatile("nop" ::: "memory"); 358 | data = jtag_rx_buffer[jtag_rx_pos]; 359 | #if MPSSE_SPI_HW 360 | usb_tx_data = spi_write_read(data); 361 | #else 362 | usb_tx_data = 0; 363 | 364 | for (uint32_t i = 8; i; i--) { 365 | //SCK_LOW; 366 | pio[2] &= ~(1 << TCK_PIN); 367 | 368 | if (data & 0x01) { 369 | //MOSI_HIGH; 370 | pio[2] |= (1 << TDI_PIN); 371 | } else { 372 | //MOSI_LOW; 373 | pio[2] &= ~(1 << TDI_PIN); 374 | } 375 | 376 | data >>= 1; 377 | usb_tx_data >>= 1; 378 | 379 | pio[2] |= (1 << TCK_PIN); 380 | //SCK_HIGH; 381 | //if (MISO) 382 | if (pio[0] & (1 << TDO_PIN)) { 383 | usb_tx_data |= 0x80; 384 | } 385 | } 386 | 387 | //SCK_LOW; 388 | pio[2] &= ~(1 << TCK_PIN); 389 | #endif 390 | 391 | if (jtag_cmd == 0x39 || jtag_cmd == 0x3d) { 392 | jtag_write(usb_tx_data); 393 | } 394 | 395 | if (mpsse_longlen == 0) { 396 | mpsse_status = MPSSE_IDLE; 397 | } 398 | 399 | mpsse_longlen--; 400 | jtag_rx_pos++; 401 | // __asm volatile("nop" ::: "memory"); 402 | break; 403 | 404 | case MPSSE_TRANSMIT_BYTE_MSB: 405 | data = jtag_rx_buffer[jtag_rx_pos]; 406 | 407 | #if MPSSE_SPI_HW 408 | usb_tx_data = spi_write_read(data); 409 | #else 410 | usb_tx_data = 0; 411 | 412 | for (uint32_t i = 8; i; i--) { 413 | //SCK_LOW; 414 | pio[2] &= ~(1 << TCK_PIN); 415 | 416 | if (data & 0x80) { 417 | //MOSI_HIGH; 418 | pio[2] |= (1 << TDI_PIN); 419 | } else { 420 | //MOSI_LOW; 421 | pio[2] &= ~(1 << TDI_PIN); 422 | } 423 | 424 | data <<= 1; 425 | usb_tx_data <<= 1; 426 | //SCK_HIGH; 427 | pio[2] |= (1 << TCK_PIN); 428 | //if (TDO) 429 | if (pio[0] & (1 << TDO_PIN)) { 430 | usb_tx_data |= 0x01; 431 | } 432 | } 433 | 434 | //SCK_LOW; 435 | pio[2] &= ~(1 << TCK_PIN); 436 | #endif 437 | 438 | if (jtag_cmd == 0x31 || jtag_cmd == 0x35) { 439 | jtag_write(usb_tx_data); 440 | } 441 | 442 | if (mpsse_longlen == 0) { 443 | mpsse_status = MPSSE_IDLE; 444 | } 445 | 446 | jtag_rx_pos++; 447 | mpsse_longlen--; 448 | break; 449 | 450 | case MPSSE_RCV_LENGTH: 451 | mpsse_shortlen = jtag_rx_buffer[jtag_rx_pos]; 452 | 453 | if (jtag_cmd == 0x6b || jtag_cmd == 0x4b || jtag_cmd == 0x6f || jtag_cmd == 0x4f) { 454 | mpsse_status = MPSSE_TMS_OUT; 455 | } else if (jtag_cmd == 0x13 || jtag_cmd == 0x17) { 456 | mpsse_status = MPSSE_TRANSMIT_BIT_MSB; 457 | } else { 458 | mpsse_status = MPSSE_TRANSMIT_BIT; 459 | } 460 | 461 | jtag_rx_pos++; 462 | break; 463 | 464 | case MPSSE_TRANSMIT_BIT: 465 | data = jtag_rx_buffer[jtag_rx_pos]; 466 | 467 | usb_tx_data = 0; 468 | 469 | do { 470 | //SCK_LOW; 471 | pio[2] &= ~(1 << TCK_PIN); 472 | 473 | if (data & 0x01) { 474 | //MOSI_HIGH; 475 | pio[2] |= (1 << TDI_PIN); 476 | } else { 477 | //MOSI_LOW; 478 | pio[2] &= ~(1 << TDI_PIN); 479 | } 480 | 481 | data >>= 1; 482 | usb_tx_data >>= 1; 483 | 484 | //SCK_HIGH; 485 | pio[2] |= (1 << TCK_PIN); 486 | 487 | // if (TDO) { 488 | if (pio[0] & (1 << TDO_PIN)) { 489 | usb_tx_data |= 0x80; 490 | } 491 | } while ((mpsse_shortlen--) > 0); 492 | 493 | //SCK_LOW; 494 | pio[2] &= ~(1 << TCK_PIN); 495 | 496 | if (jtag_cmd == 0x3b || jtag_cmd == 0x3f) { 497 | jtag_write(usb_tx_data); 498 | } 499 | 500 | mpsse_status = MPSSE_IDLE; 501 | jtag_rx_pos++; 502 | break; 503 | 504 | case MPSSE_TRANSMIT_BIT_MSB: 505 | data = jtag_rx_buffer[jtag_rx_pos]; 506 | 507 | do { 508 | //SCK_LOW; 509 | pio[2] &= ~(1 << TCK_PIN); 510 | 511 | if (data & 0x80) { 512 | //MOSI_HIGH; 513 | pio[2] |= (1 << TDI_PIN); 514 | } else { 515 | //MOSI_LOW; 516 | pio[2] &= ~(1 << TDI_PIN); 517 | } 518 | 519 | data <<= 1; 520 | //SCK_HIGH; 521 | pio[2] |= (1 << TCK_PIN); 522 | } while ((mpsse_shortlen--) > 0); 523 | 524 | //SCK_LOW; 525 | pio[2] &= ~(1 << TCK_PIN); 526 | 527 | mpsse_status = MPSSE_IDLE; 528 | jtag_rx_pos++; 529 | break; 530 | 531 | case MPSSE_ERROR: 532 | usb_tx_data = jtag_rx_buffer[jtag_rx_pos]; 533 | jtag_write(usb_tx_data); 534 | mpsse_status = MPSSE_IDLE; 535 | jtag_rx_pos++; 536 | 537 | break; 538 | 539 | case MPSSE_TMS_OUT: 540 | //__asm volatile ("nop":::"memory"); 541 | data = jtag_rx_buffer[jtag_rx_pos]; 542 | 543 | if (data & 0x80) { 544 | //TDI_HIGH; 545 | pio[2] |= 1 << TDI_PIN; 546 | } else { 547 | //TDI_LOW; 548 | pio[2] &= ~(1 << TDI_PIN); 549 | } 550 | 551 | usb_tx_data = 0; 552 | 553 | do { 554 | TCK_LOW; 555 | pio[2] &= ~(1 << TCK_PIN); 556 | 557 | if (data & 0x01) { 558 | //TMS_HIGH; 559 | pio[2] |= (1 << TMS_PIN); 560 | } else { 561 | //TMS_LOW; 562 | pio[2] &= ~(1 << TMS_PIN); 563 | } 564 | 565 | data >>= 1; 566 | usb_tx_data >>= 1; 567 | 568 | //TCK_HIGH; 569 | pio[2] |= (1 << TCK_PIN); 570 | 571 | // if (TDO) { 572 | if (pio[0] & (1 << TDO_PIN)) { 573 | usb_tx_data |= 0x80; 574 | } 575 | } while ((mpsse_shortlen--) > 0); 576 | 577 | //TCK_LOW; 578 | pio[2] &= ~(1 << TCK_PIN); 579 | 580 | if (jtag_cmd == 0x6b || jtag_cmd == 0x6f) { 581 | jtag_write(usb_tx_data); 582 | } 583 | 584 | mpsse_status = MPSSE_IDLE; 585 | jtag_rx_pos++; 586 | //__asm volatile ("nop":::"memory"); 587 | break; 588 | 589 | case MPSSE_NO_OP_1: 590 | jtag_rx_pos++; 591 | mpsse_status = MPSSE_NO_OP_2; 592 | break; 593 | 594 | case MPSSE_NO_OP_2: 595 | mpsse_status = MPSSE_IDLE; 596 | jtag_rx_pos++; 597 | break; 598 | #if GOWIN_INT_FLASH_QUIRK 599 | 600 | case MPSSE_RUN_TEST: 601 | if (mpsse_longlen == 0) { 602 | mpsse_status = MPSSE_IDLE; 603 | MSG("run test stop\r\n"); 604 | 605 | pwm_stop(); 606 | } 607 | 608 | for (uint32_t i = 0; i < 50; i++) { 609 | __asm volatile("nop"); 610 | } 611 | 612 | jtag_rx_pos++; 613 | mpsse_longlen--; 614 | break; 615 | #endif 616 | 617 | default: 618 | mpsse_status = MPSSE_IDLE; 619 | break; 620 | } 621 | 622 | if (jtag_rx_pos >= jtag_rx_len) { 623 | jtag_received_flag = false; 624 | usbd_ep_read(0x02, NULL, 0, NULL); 625 | } 626 | } 627 | cpu_global_irq_enable(); 628 | } 629 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/jtag_process.c.gowin: -------------------------------------------------------------------------------- 1 | /** 2 | * @file uart_interface.h 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | 25 | #include "hal_usb.h" 26 | #include "usbd_core.h" 27 | #include "usbd_ftdi.h" 28 | #include "ring_buffer.h" 29 | #include "hal_gpio.h" 30 | #include "hal_spi.h" 31 | #include "hal_pwm.h" 32 | #include "bl702_glb.h" 33 | #include "bl702_gpio.h" 34 | #include "bl702_pwm.h" 35 | #include "io_cfg.h" 36 | #define GOWIN_INT_FLASH_QUIRK 1 37 | #define GW_DBG 1 38 | #define MPSSE_SPI_HW 0 39 | 40 | #define PWM_CH 0 //TCK pin num %5 41 | 42 | #define TMS_HIGH ((*(volatile uint32_t *)0x40000188) |= (1<=21, idx=18: 1b 06 71 304 | void usbd_cdc_jtag_out(uint8_t ep) 305 | {// 306 | uint32_t chunk; 307 | //if (!jtag_received_flag) 308 | if(!doing_flag) 309 | { 310 | usbd_ep_read(ep, jtag_rx_buffer+jtag_rx_len, 64, &chunk); 311 | 312 | if (chunk == 0) 313 | { 314 | //MSG("111\r\n"); 315 | return; 316 | } 317 | //if(jtag_rx_len == 0) MSG("\r\n"); 318 | //查找ef program标志 1b 06 71 6b 00 01 319 | uint8_t* p0 = jtag_rx_buffer+jtag_rx_len; 320 | uint8_t* p = jtag_rx_buffer+jtag_rx_len+18; 321 | uint8_t* p1 = jtag_rx_buffer+jtag_rx_len+chunk-5; 322 | if(!ef_flag && chunk>=21 && p[0]==0x1b && p[1]==0x06 && p[2]==0x71){ 323 | ef_flag = 1; 324 | MSG("$"); 325 | } 326 | if(ef_flag == 1) { 327 | if( (p1[0]==0x19 && p1[1]==0x01)){ 328 | ef_flag = 0; //结尾是 19 01 00 00 00 (只适用于新工艺的1NZ和4K系列) 329 | }/* else if ((p0[4]==0x19 && p0[5]==0xee && p0[6]==0x02)){ 330 | //01 4b 03 01 19 ee 02 00 //1N FPGA 331 | ef_flag = 2; 332 | ef_cnt = 0x2ee - 6-1; 333 | } else if ((p0[26]==0x19 && p0[27]==0xee && p0[28]==0x02)) { 334 | //1N FPGA 335 | //06 00 4b 00 01 4b 03 01 4b 02 01 19 02 00 00 00 00 1b 06 00 4b 00 01 4b 03 01 19 ee 02 00 00 00 336 | ef_flag = 2; 337 | ef_cnt = 0x2ee - 28-1; 338 | }*/ 339 | } /*else if(ef_flag == 2) { 340 | ef_cnt -= chunk; 341 | if(ef_cnt<=0) { 342 | ef_flag = 0; 343 | } 344 | }*/ 345 | 346 | //MSG("@%d@",chunk); 347 | 348 | jtag_rx_len += chunk; 349 | 350 | // bflb_platform_dump(jtag_rx_buffer, jtag_rx_len); 351 | jtag_rx_pos = 0; 352 | jtag_received_flag = true; 353 | last_rcv = mtimer_get_time_us(); 354 | //MSG("%d", mtimer_get_time_us()%10000); //, 355 | usbd_ep_read(JTAG_OUT_EP, NULL, 0, NULL); //表示处理好一帧? 356 | } 357 | } 358 | 359 | #else 360 | void usbd_cdc_jtag_out(uint8_t ep) 361 | { 362 | uint32_t chunk; 363 | if (!jtag_received_flag) { //在处理完之前的包后才进行下一次接收 364 | usbd_ep_read(ep, jtag_rx_buffer, 64, &chunk); 365 | if (chunk == 0){ 366 | return; 367 | } 368 | jtag_rx_len = chunk; 369 | // bflb_platform_dump(jtag_rx_buffer, jtag_rx_len); 370 | jtag_rx_pos = 0; 371 | jtag_received_flag = true; 372 | } 373 | } 374 | #endif 375 | 376 | extern uint16_t usb_dc_ftdi_send_from_ringbuffer(struct device *dev, Ring_Buffer_Type *rb, uint8_t ep); 377 | static volatile uint32_t temp_tick1 = 0; 378 | void usbd_cdc_jtag_in(uint8_t ep) 379 | { //MSG("#%ld#", mtimer_get_time_us()%1000); 380 | if (jtag_rx_len==0) //(!jtag_received_flag)) //没有需要处理的接收内容时返回数据 381 | { 382 | //temp_tick1 = usbd_get_sof_tick(); 383 | usb_dc_ftdi_send_from_ringbuffer(usb_fs, &jtag_tx_rb, ep); 384 | } 385 | } 386 | 387 | 388 | ATTR_CLOCK_SECTION void jtag_process(void) 389 | { 390 | uint32_t usb_tx_data = 0; 391 | uint32_t data = 0; 392 | register uint32_t tmpt = mtimer_get_time_us(); 393 | register volatile uint32_t *pio __asm ("tp") = (volatile uint32_t *)0x40000180; 394 | register uint32_t bitbang = 0; 395 | 396 | if (!jtag_received_flag) 397 | return; 398 | 399 | #if GW_DBG 400 | if(ef_flag == 0) { 401 | if((tmpt-last_rcv<5) || (jtag_rx_len == 0)) //200us之后再统一处理, 加速整包的处理 // 402 | { 403 | return; 404 | } 405 | } else { 406 | //if((jtag_rx_len < 1750)) //200us之后再统一处理, 加速整包的处理 // 407 | //if((tmpt-last_rcv<500) || (jtag_rx_len == 0)) 408 | //{ //MSG("#%d#", jtag_rx_len); 409 | // return; 410 | //} 411 | //MSG("@%d,%d@", tmpt%10000, last_rcv%10000); 412 | return; //直接返回,等待接收完成 413 | } 414 | 415 | 416 | //MSG("#%d#", jtag_rx_len); 417 | //MSG("+%ldus, %d\r\n", mtimer_get_time_us(), jtag_rx_len); 418 | disable_irq(); 419 | doing_flag = 1; 420 | while(jtag_rx_pos < jtag_rx_len) 421 | #else 422 | disable_irq(); 423 | while(jtag_rx_pos < jtag_rx_len) 424 | #endif 425 | { 426 | switch (mpsse_status) 427 | { 428 | case MPSSE_IDLE: 429 | jtag_cmd = jtag_rx_buffer[jtag_rx_pos]; 430 | //MSG("cmd:0x%02x\r\n",jtag_cmd); 431 | switch (jtag_cmd) 432 | { /* Instructions*/ 433 | case 0x80: 434 | case 0x82:/* set data bit as output, we just nop it */ 435 | mpsse_status = MPSSE_NO_OP_1; //need read two byte next 436 | jtag_rx_pos++; 437 | break; 438 | case 0x81: 439 | case 0x83:/* dummy read back 8pins data, and send to usb */ 440 | usb_tx_data = jtag_rx_buffer[jtag_rx_pos] - 0x80; 441 | jtag_write(usb_tx_data); 442 | jtag_rx_pos++; 443 | break; 444 | case 0x84: 445 | case 0x85:/* Loopback, nothing to do*/ 446 | jtag_rx_pos++; 447 | break; 448 | case 0x86: /* Clock Divisor, 0xValueL, 0xValueH; CLK=30M/Val */ 449 | //not support, we fixed 2.5MHz, 400ns period, 200ns each 450 | mpsse_status = MPSSE_NO_OP_1; //need read two byte next 451 | jtag_rx_pos++; 452 | break; 453 | case 0x87: /* send immediate*/ 454 | //This will make the chip flush its buffer back to the PC. 455 | //no thing to do 456 | jtag_rx_pos++; 457 | break; 458 | case 0x8a: // //Disables the clk divide by 5 to allow for a 60MHz master clock 459 | case 0x8b: //Enables the clk divide by 5 to allow for backward compatibility with FT2232D 460 | case 0x8c: //Enables 3 phase data clocking. Used by I2C interfaces to allow data on both clock edges. 461 | case 0x8d: // //Disables 3 phase data clocking. 462 | case 0x8e: //Allows for a clock to be output without transferring data. Commonly used in the JTAG state machine. Clocks counted in terms of numbers of bit 463 | case 0x8f: //Allows for a clock to be output without transferring data. Commonly used in the JTAG state machine. Clocks countedin terms of numbers of bytes 464 | case 0x94: //Allows for a clock to be output without transferring data until a logic 1 input on GPIOL1 stops the clock 465 | case 0x95: //Allows for a clock to be output without transferring data until a logic 0 input on GPIOL1 stops the clock. 466 | case 0x96: //Allows for a clock to be output without transferring data until a logic 0 input on GPIOL1 stops the clock. 467 | case 0x97: // //Disable adaptive clocking 468 | case 0x9c: //Allows for a clock to be output without transferring data until a logic 1 input on GPIOL1 stops the clock or a set number of clock pulses are sent. Clocks counted in terms of numbers of bytes 469 | case 0x9d: //Allows for a clock to be output without transferring data until a logic 0 input on GPIOL1 stops the clock or a setnumber of clock pulses are sent. Clocks counted in terms of numbers of bytes 470 | jtag_rx_pos++; 471 | break; 472 | 473 | /* Data Shifting Command */ 474 | case 0x19: 475 | case 0x1d: 476 | case 0x39: 477 | case 0x3d: 478 | case 0x11: 479 | case 0x15: 480 | case 0x31: 481 | case 0x35: 482 | #if MPSSE_SPI_HW 483 | spi_on(); 484 | #endif 485 | mpsse_status = MPSSE_RCV_LENGTH_L; 486 | jtag_rx_pos++; 487 | break; 488 | case 0x6b: 489 | case 0x6f: 490 | case 0x4b: 491 | case 0x4f: 492 | case 0x3b: 493 | case 0x3f: 494 | case 0x1b: 495 | case 0x1f: 496 | case 0x13: 497 | case 0x17: 498 | #if MPSSE_SPI_HW 499 | spi_off(); 500 | #endif 501 | mpsse_status = MPSSE_RCV_LENGTH; 502 | jtag_rx_pos++; 503 | break; 504 | default: 505 | usb_tx_data = 0xFA; 506 | jtag_write(usb_tx_data); 507 | mpsse_status = MPSSE_ERROR; 508 | break; 509 | } 510 | break; 511 | case MPSSE_RCV_LENGTH_L:/* 接收长度 */ 512 | mpsse_longlen = jtag_rx_buffer[jtag_rx_pos]; 513 | 514 | mpsse_status = MPSSE_RCV_LENGTH_H; 515 | jtag_rx_pos++; 516 | break; 517 | case MPSSE_RCV_LENGTH_H: 518 | mpsse_longlen |= (jtag_rx_buffer[jtag_rx_pos] << 8) & 0xff00; 519 | 520 | jtag_rx_pos++; 521 | #if GOWIN_INT_FLASH_QUIRK 522 | if ((mpsse_longlen >=2000) && (jtag_cmd & (1 << 5)) == 0) //1N 型号:0xb98 523 | { 524 | //SPI_OFF(); 525 | //Run_Test_Start(); 526 | pwm_start(); 527 | //MSG("len:%d\r\n",mpsse_longlen); 528 | //MSG("run test start\r\n"); 529 | mpsse_status = MPSSE_RUN_TEST; 530 | } 531 | else if (jtag_cmd == 0x11 || jtag_cmd == 0x31) 532 | #else 533 | if (jtag_cmd == 0x11 || jtag_cmd == 0x31) 534 | #endif 535 | { 536 | mpsse_status = MPSSE_TRANSMIT_BYTE_MSB; 537 | #if MPSSE_SPI_HW 538 | SPI_MSB_FIRST(); 539 | #endif 540 | } 541 | else 542 | { 543 | mpsse_status = MPSSE_TRANSMIT_BYTE; 544 | #if MPSSE_SPI_HW 545 | SPI_LSB_FIRST(); 546 | #endif 547 | } 548 | break; 549 | case MPSSE_TRANSMIT_BYTE: 550 | //__asm volatile ("nop":::"memory"); 551 | data = jtag_rx_buffer[jtag_rx_pos]; 552 | #if MPSSE_SPI_HW 553 | usb_tx_data = spi_write_read(data); 554 | #else 555 | usb_tx_data = 0; 556 | 557 | bitbang = pio[2]; 558 | for (uint32_t i = 8; i ; i--) 559 | { 560 | //SCK_LOW; 561 | bitbang &= ~((1 << TCK_PIN) | (1 << TDI_PIN)); 562 | pio[2] = bitbang; 563 | DELAY_LOW(); 564 | if (data & 0x01) { 565 | //MOSI_HIGH; 566 | bitbang |= ((1 << TCK_PIN) | (1 << TDI_PIN)); 567 | } else { 568 | //MOSI_LOW; 569 | bitbang |= (1<>= 1; 574 | usb_tx_data >>= 1; 575 | //SCK_HIGH; 576 | //if (MISO) 577 | DELAY_HIGH(); 578 | if (pio[0] & (1 << TDO_PIN)) 579 | usb_tx_data |= 0x80; 580 | } 581 | //SCK_LOW; 582 | pio[2] &= ~(1<>= 1; 676 | usb_tx_data >>= 1; 677 | 678 | //SCK_HIGH; 679 | DELAY_HIGH(); 680 | if (MISO) 681 | usb_tx_data |= 0x80; 682 | } 683 | while ((mpsse_shortlen--) > 0); 684 | //SCK_LOW; 685 | pio[2] &= ~(1< 0); 717 | //SCK_LOW; 718 | pio[2] &= ~(1<>= 1; 762 | usb_tx_data >>= 1; 763 | 764 | //TCK_HIGH; 765 | //if (TDO) 766 | if (pio[0] & (1 << TDO_PIN)) 767 | usb_tx_data |= 0x80; 768 | } 769 | while ((mpsse_shortlen--) > 0); 770 | //TCK_LOW; 771 | pio[2] &= ~(1<= jtag_rx_len) 807 | { 808 | jtag_received_flag = false; 809 | #if !GW_DBG 810 | usbd_ep_read(JTAG_OUT_EP, NULL, 0, NULL); 811 | #endif 812 | jtag_rx_len = 0; 813 | 814 | } 815 | } 816 | //MSG("-%ldus\r\n", mtimer_get_time_us()); 817 | doing_flag = 0; 818 | ef_flag = 0; 819 | enable_irq(); 820 | 821 | return; 822 | } 823 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | #include "hal_usb.h" 24 | #include "usbd_core.h" 25 | #include "usbd_ftdi.h" 26 | #include "uart_interface.h" 27 | #include "bl702_ef_ctrl.h" 28 | #include "bl702_usb.h" 29 | #include "bl702_glb.h" 30 | #include "hal_gpio.h" 31 | #include "io_cfg.h" 32 | 33 | /* 34 | UART: 35 | RXD -> ringbuffer -> usbd_cdc_acm_bulk_in -> CDC_IN_EP 36 | UART <---------------------------------------------------> USB 37 | TXD <- ringbuffer <- usbd_cdc_acm_bulk_out<- CDC_OUT_EP 38 | 39 | JTAG: 40 | jtag_rx_buffer[jtag_rx_pos] -> jtag_cmd -> mpsse status machine 41 | MPSSE_TRANSMIT_BYTE/BIT MSB/LSB MPSSE_TMS_OUT 42 | bitbang simulate clk rate about 5MHz 43 | */ 44 | 45 | extern struct device* usb_dc_init(void); 46 | extern void jtag_process(void); 47 | extern void jtag_ringbuffer_init(void); 48 | extern void jtag_gpio_init(void); 49 | extern void usbd_cdc_jtag_out(uint8_t ep); 50 | extern void usbd_cdc_jtag_in(uint8_t ep); 51 | 52 | usbd_class_t cdc_class0; 53 | usbd_interface_t cdc_data_intf0; 54 | usbd_class_t cdc_class1; 55 | usbd_interface_t cdc_data_intf1; 56 | extern uint8_t cdc_descriptor[]; 57 | struct device *usb_fs; 58 | 59 | 60 | /************************ led ctrl functions ************************/ 61 | static uint32_t led_pins[2] = {LED0_PIN, LED1_PIN}; 62 | static volatile uint8_t led_stat[2] = {0, 0}; 63 | static void led_gpio_init(void) 64 | { 65 | gpio_set_mode(led_pins[0], GPIO_OUTPUT_MODE); 66 | gpio_set_mode(led_pins[1], GPIO_OUTPUT_MODE); 67 | return; 68 | } 69 | 70 | void led_set(uint8_t idx, uint8_t status) 71 | { 72 | gpio_write(led_pins[idx], !status); 73 | led_stat[idx] = status; 74 | return; 75 | } 76 | 77 | void led_toggle(uint8_t idx) 78 | { 79 | led_stat[idx] = !led_stat[idx]; 80 | gpio_write(led_pins[idx], !led_stat[idx]); 81 | return; 82 | } 83 | 84 | /************************ API for usbd_ftdi ************************/ 85 | void usbd_ftdi_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits) 86 | { 87 | uart1_config(baudrate, databits, parity, stopbits); 88 | } 89 | 90 | void usbd_ftdi_set_dtr(bool dtr) 91 | { 92 | dtr_pin_set(!dtr); 93 | } 94 | 95 | void usbd_ftdi_set_rts(bool rts) 96 | { 97 | rts_pin_set(!rts); 98 | } 99 | 100 | 101 | /************************ USB UART logic for latency timer ************************/ 102 | static volatile uint32_t temp_tick2 = 0; //tick for uart port 103 | static volatile uint32_t temp_tick1 = 0; //tick for uart port 104 | uint64_t last_send = 0; 105 | 106 | extern uint32_t mpsse_status; 107 | // UART RX -> USB IN 108 | uint16_t usb_dc_ftdi_send_from_ringbuffer(struct device *dev, Ring_Buffer_Type *rb, uint8_t ep) 109 | { 110 | uint8_t ep_idx; 111 | uint32_t timeout = 0x00FFFFFF; 112 | 113 | ep_idx = USB_EP_GET_IDX(ep); 114 | /* Check if IN ep */ 115 | if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) 116 | { 117 | return -USB_DC_EP_DIR_ERR; 118 | } 119 | 120 | while (!USB_Is_EPx_RDY_Free(ep_idx)) 121 | { 122 | timeout--; 123 | if (!timeout) 124 | { 125 | MSG("ep%d wait free timeout\r\n", ep); 126 | return -USB_DC_EP_TIMEOUT_ERR; 127 | } 128 | } 129 | 130 | uint32_t addr = USB_BASE + 0x118 + (ep_idx - 1) * 0x10; 131 | 132 | if ((USB_Get_EPx_TX_FIFO_CNT(ep_idx) == USB_FS_MAX_PACKET_SIZE) && Ring_Buffer_Get_Length(rb)) 133 | { 134 | uint8_t ftdi_header[2] = {0x01,0x60}; 135 | MSG("*"); 136 | memcopy_to_fifo((void *)addr,ftdi_header,2); 137 | Ring_Buffer_Read_Callback(rb, USB_FS_MAX_PACKET_SIZE-2, memcopy_to_fifo, (void *)addr); 138 | USB_Set_EPx_Rdy(ep_idx); 139 | led_toggle(0); //RX indication 140 | last_send = mtimer_get_time_us(); 141 | return 0; 142 | } 143 | else 144 | { 145 | /*uint64_t Latency_Timer = (ep_idx - 1)==0?usbd_ftdi_get_latency_timer1():usbd_ftdi_get_latency_timer2(); //超时才发 146 | if(mtimer_get_time_us()-last_send>Latency_Timer*1000) { 147 | uint8_t ftdi_header[2] = {0x01,0x60}; 148 | memcopy_to_fifo((void *)addr,ftdi_header,2); 149 | USB_Set_EPx_Rdy(ep_idx); 150 | last_send = mtimer_get_time_us(); 151 | //MSG("Port%d refresh\r\n", ep_idx); 152 | return -USB_DC_RB_SIZE_SMALL_ERR; 153 | }*/ 154 | 155 | if(ep_idx == CDC_IN_EP) //UART 156 | { 157 | if((uint32_t)(usbd_ftdi_get_sof_tick()-temp_tick2) >= usbd_ftdi_get_latency_timer2()) 158 | { 159 | uint8_t ftdi_header[2] = {0x01,0x60}; 160 | temp_tick2 = usbd_ftdi_get_sof_tick(); 161 | memcopy_to_fifo((void *)addr,ftdi_header,2); 162 | USB_Set_EPx_Rdy(ep_idx); 163 | } 164 | } 165 | else //0x81, JTAG 166 | { 167 | //if((uint32_t)(usbd_ftdi_get_sof_tick()-temp_tick1) >= usbd_ftdi_get_latency_timer1()) 168 | //if(mpsse_status != 12) 169 | //MSG("#"); 170 | if(mtimer_get_time_us()-last_send>1000) 171 | { 172 | uint8_t ftdi_header[2] = {0x01,0x60}; 173 | temp_tick1 = usbd_ftdi_get_sof_tick(); 174 | memcopy_to_fifo((void *)addr,ftdi_header,2); 175 | USB_Set_EPx_Rdy(ep_idx); 176 | } 177 | } 178 | return -USB_DC_RB_SIZE_SMALL_ERR; 179 | } 180 | 181 | } 182 | 183 | // USB OUT -> UART TX 184 | int usb_dc_ftdi_receive_to_ringbuffer(struct device *dev, Ring_Buffer_Type *rb, uint8_t ep) 185 | { 186 | uint8_t ep_idx; 187 | uint8_t recv_len; 188 | uint32_t timeout = 0x00FFFFFF; 189 | static bool overflow_flag = false; 190 | 191 | /* Check if OUT ep */ 192 | if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) 193 | { 194 | //USB_DC_LOG_ERR("Wrong endpoint direction\r\n"); 195 | return -USB_DC_EP_DIR_ERR; 196 | } 197 | 198 | ep_idx = USB_EP_GET_IDX(ep); 199 | 200 | while (!USB_Is_EPx_RDY_Free(ep_idx)) 201 | { 202 | timeout--; 203 | if (!timeout) 204 | { 205 | //USB_DC_LOG_ERR("ep%d wait free timeout\r\n", ep); 206 | return -USB_DC_EP_TIMEOUT_ERR; 207 | } 208 | } 209 | recv_len = USB_Get_EPx_RX_FIFO_CNT(ep_idx); 210 | 211 | /*if rx fifo count equal 0,it means last is send nack and ringbuffer is smaller than 64, 212 | * so,if ringbuffer is larger than 64,set ack to recv next data. 213 | */ 214 | if(overflow_flag && (Ring_Buffer_Get_Empty_Length(rb)>64) && (!recv_len)) 215 | { 216 | overflow_flag = false; 217 | USB_Set_EPx_Rdy(ep_idx); 218 | return 0; 219 | } 220 | else 221 | { 222 | uint32_t addr = USB_BASE + 0x11C + (ep_idx - 1) * 0x10; 223 | Ring_Buffer_Write_Callback(rb, recv_len, fifocopy_to_mem, (void *)addr); 224 | 225 | if(Ring_Buffer_Get_Empty_Length(rb) < 64) 226 | { 227 | overflow_flag = true; 228 | return -USB_DC_RB_SIZE_SMALL_ERR; 229 | } 230 | USB_Set_EPx_Rdy(ep_idx); 231 | return 0; 232 | } 233 | } 234 | 235 | 236 | // USB -> UART out 237 | void usbd_cdc_acm_bulk_out(uint8_t ep) 238 | { 239 | usb_dc_ftdi_receive_to_ringbuffer(usb_fs, &usb_rx_rb, ep); 240 | } 241 | //UART -> USB in 242 | void usbd_cdc_acm_bulk_in(uint8_t ep) 243 | { 244 | usb_dc_ftdi_send_from_ringbuffer(usb_fs, &uart1_rx_rb, ep); 245 | } 246 | 247 | 248 | /************************ endpoint definition ************************/ 249 | //For UART 250 | usbd_endpoint_t cdc_out_ep1 = 251 | { 252 | .ep_addr = CDC_OUT_EP, 253 | .ep_cb = usbd_cdc_acm_bulk_out 254 | }; 255 | 256 | usbd_endpoint_t cdc_in_ep1 = 257 | { 258 | .ep_addr = CDC_IN_EP, 259 | .ep_cb = usbd_cdc_acm_bulk_in 260 | }; 261 | 262 | //For JTAG 263 | usbd_endpoint_t cdc_out_ep0 = 264 | { 265 | .ep_addr = JTAG_OUT_EP, 266 | .ep_cb = usbd_cdc_jtag_out 267 | }; 268 | 269 | usbd_endpoint_t cdc_in_ep0 = 270 | { 271 | .ep_addr = JTAG_IN_EP, 272 | .ep_cb = usbd_cdc_jtag_in 273 | }; 274 | 275 | 276 | //for dbg chip id 277 | static void hexarr2string(uint8_t *hexarray,int length,uint8_t *string) 278 | { 279 | unsigned char num2string_table[] = "0123456789ABCDEF"; 280 | int i = 0; 281 | while(i < length) 282 | { 283 | *(string++) = num2string_table[((hexarray[i] >> 4) & 0x0f)]; 284 | *(string++) = num2string_table[(hexarray[i] & 0x0f)]; 285 | i++; 286 | } 287 | return; 288 | } 289 | 290 | int main(void) 291 | { 292 | uint8_t chipid[8]; 293 | uint8_t chipid2[6]; 294 | GLB_Select_Internal_Flash(); 295 | bflb_platform_init(0); 296 | uart_ringbuffer_init(); 297 | uart1_init(); 298 | uart1_set_dtr_rts(UART_DTR_PIN,UART_RTS_PIN); 299 | uart1_dtr_init(); 300 | uart1_rts_init(); 301 | led_gpio_init(); 302 | led_set(0, 1); //led0 for RX/TX indication 303 | led_set(1, 1); //led1 for Power indication 304 | jtag_ringbuffer_init(); 305 | jtag_gpio_init(); 306 | EF_Ctrl_Read_Chip_ID(chipid); 307 | // hexarr2string(&chipid[2],3,chipid2); 308 | // bflb_platform_dump(chipid,8); 309 | // bflb_platform_dump(chipid2,6); 310 | cdc_descriptor[0x12+0x37+0x04+0x0a+0x1c+0x24] = 0x00; //chipid2[0]; 311 | cdc_descriptor[0x12+0x37+0x04+0x0a+0x1c+0x24+2] = 0x11; //chipid2[1]; 312 | cdc_descriptor[0x12+0x37+0x04+0x0a+0x1c+0x24+4] = 0x22; //chipid2[2]; 313 | cdc_descriptor[0x12+0x37+0x04+0x0a+0x1c+0x24+6] = 0x33; //chipid2[3]; 314 | cdc_descriptor[0x12+0x37+0x04+0x0a+0x1c+0x24+8] = 0x44; //chipid2[4]; 315 | cdc_descriptor[0x12+0x37+0x04+0x0a+0x1c+0x24+10] = 0x55; //chipid2[5]; 316 | usbd_desc_register(cdc_descriptor); 317 | 318 | usbd_ftdi_add_interface(&cdc_class0,&cdc_data_intf0); 319 | usbd_interface_add_endpoint(&cdc_data_intf0,&cdc_out_ep0); 320 | usbd_interface_add_endpoint(&cdc_data_intf0,&cdc_in_ep0); 321 | 322 | usbd_ftdi_add_interface(&cdc_class1,&cdc_data_intf1); 323 | usbd_interface_add_endpoint(&cdc_data_intf1,&cdc_out_ep1); 324 | usbd_interface_add_endpoint(&cdc_data_intf1,&cdc_in_ep1); 325 | 326 | usb_fs = usb_dc_init(); 327 | if (usb_fs) 328 | { 329 | device_control(usb_fs, DEVICE_CTRL_SET_INT, (void *)(USB_SOF_IT|USB_EP2_DATA_OUT_IT | USB_EP1_DATA_IN_IT|USB_EP4_DATA_OUT_IT|USB_EP3_DATA_IN_IT)); 330 | } 331 | while(!usb_device_is_configured()){}; 332 | 333 | led_toggle(0); 334 | while (1) 335 | { 336 | uart_send_from_ringbuffer(); 337 | jtag_process(); 338 | } 339 | 340 | return 0; 341 | } 342 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/mpsse_cmd.md: -------------------------------------------------------------------------------- 1 | **Data Shifting Command** 2 | 3 | - Bit 0 : -ve CLK on write 4 | - Bit 1 : bit mode = 1 else byte mode 5 | - Bit 2 : -ve CLK on read 6 | - Bit 3 : LSB first = 1 else MSB first 7 | - Bit 4 : Do write TDI 8 | - Bit 5 : Do read TDO 9 | - Bit 6 : Do writeTMS 10 | - Bit 7 : 0 11 | 12 | **MSB** 13 | 14 | |OPCODE |Data IN |Data OUT |BIT/BYTE | IN EDGE |OUT EDGE | 15 | |-- |-- |-- |-- |-- |-- | 16 | |0x10 | - | YES | BYTES | - | +VE | 17 | |0x11 |- | YES | BYTES | - | -VE | 18 | |0x12 |- | YES | BITS | - | +VE | 19 | |0x13 |- | YES | BITS | - | -VE | 20 | |0x20 |YES | - | BYTES | +VE | - | 21 | |0x24 |YES | - | BYTES | -VE | - | 22 | |0x22 |YES | - | BITS | +VE | - | 23 | |0x26 |YES | - | BITS | -VE | - | 24 | |0x31 |YES | YES | BYTES | +VE | -VE | 25 | |0x34 |YES | YES | BYTES | -VE | +VE | 26 | |0x33 |YES | YES | BITS | +VE | -VE | 27 | |0x36 |YES | YES | BITS | -VE | +VE | 28 | 29 | **LSB** 30 | 31 | |OPCODE |Data IN |Data OUT |BIT/BYTE |IN EDGE |OUT EDGE | 32 | |-- |-- |-- |-- |-- |-- | 33 | |0x18 | - | YES | BYTES | - | +VE | 34 | |0x19 | - | YES | BYTES | - | -VE | 35 | |0x1A | - | YES | BITS | - | +VE | 36 | |0x1B | - | YES | BITS | - | -VE | 37 | |0x28 | YES | - | BYTES | +VE | - | 38 | |0x2C | YES | - | BYTES | -VE | - | 39 | |0x2A | YES | - | BITS | +VE | - | 40 | |0x2E | YES | - | BITS | -VE | - | 41 | |0x39 | YES | YES | BYTES | +VE | -VE | 42 | |0x3C | YES | YES | BYTES | -VE | +VE | 43 | |0x3B | YES | YES | BITS | +VE | -VE | 44 | |0x3E | YES | YES | BITS | -VE | +VE | 45 | 46 | **TMS COMMANDS** 47 | 48 | |OPCODE |Data IN |Data OUT |IN EDGE |OUT EDGE | 49 | |-- |-- |-- |-- |-- | 50 | |0x4A | - | YES | - | +VE | 51 | |0x4B | - | YES | - | -VE | 52 | |0x6A | YES | YES | +VE | +VE | 53 | |0x6B | YES | YES | -VE | +VE | 54 | |0x6E | YES | YES | +VE | -VE | 55 | |0x6F | YES | YES | -VE | -VE | 56 | 57 | **Set/Read Data Bits High/Low Bytes** 58 | 59 | |OPCODE |Set O/P |Read I/P |High Byte |Low Byte | 60 | |-- |-- |-- |-- |-- | 61 | |0x80 |YES | - | - | YES | 62 | |0x82 |YES | - | YES | - | 63 | |0x81 |- | YES | - | YES | 64 | |0x83 |- | YES | YES | - | 65 | 66 | **Loopback Commands** 67 | 68 | |OPCODE |Loopback Enabled | 69 | |-- |-- | 70 | |0x84 | YES | 71 | |0x85 | NO | 72 | 73 | 74 | **Clock Divisor** 75 | Set TCK/SK Divisor (FT2232D) 76 | 0x86, 77 | 0xValueL, 78 | 0xValueH 79 | 80 | Set clk divisor (FT232H/FT2232H/FT4232H) 81 | 0x86, 82 | 0xValueL, 83 | 0xValueH, 84 | 85 | **Instructions for CPU mode** 86 | 87 | |OPCODE |Write |Read |Short Address |Extended Address | 88 | |-- |-- |-- |-- |-- | 89 | |0x90 |- | YES | YES | - | 90 | |0x91 |- | YES | - | YES | 91 | |0x92 |YES | - | YES | - | 92 | |0x93 |YES | - | - | YES | 93 | 94 | 95 | **Instructions for use in both MPSSE and MCU Host Emulation Modes** 96 | 97 | |OPCODE |Function | 98 | |-- |-- | 99 | |0x87 | Send Immediate | 100 | |0x88 | Wait On I/O High| 101 | |0x89 | Wait On I/O Low | 102 | 103 | **FT232H, FT2232H & FT4232H ONLY** 104 | 105 | |OPCODE |Function | 106 | |-- |-- | 107 | |0x8A |Disables the clk divide by 5 to allow for a 60MHz master clock.| 108 | |0x8B |Enables the clk divide by 5 to allow for backward compatibility with FT2232D| 109 | |0x8C |Enables 3 phase data clocking. Used by I2C interfaces to allow data on both clock edges.| 110 | |0x8D |Disables 3 phase data clocking.| 111 | |0x8E |Allows for a clock to be output without transferring data. Commonly used in the JTAG state machine. Clocks counted in terms of numbers of bit.| 112 | |0x8F |Allows for a clock to be output without transferring data. Commonly used in the JTAG state machine. Clocks countedin terms of numbers of bytes| 113 | |0x94 |Allows for a clock to be output without transferring data until a logic 1 input on GPIOL1 stops the clock.| 114 | |0x95 |Allows for a clock to be output without transferring data until a logic 0 input on GPIOL1 stops the clock.| 115 | |0x96 |Enable adaptive clocking| 116 | |0x97 |Disable adaptive clocking| 117 | |0x9C |Allows for a clock to be output without transferring data until a logic 1 input on GPIOL1 stops the clock or a set number of clock pulses are sent. Clocks counted in terms of numbers of bytes| 118 | |0x9D |Allows for a clock to be output without transferring data until a logic 0 input on GPIOL1 stops the clock or a setnumber of clock pulses are sent. Clocks counted in terms of numbers of bytes| 119 | 120 | **FT232H ONLY** 121 | Set I/O to only drive on a ‘0’ and tristate on a ‘1’ 122 | 0x9E 123 | LowByteEnablesForOnlyDrive0 124 | HighByteEnablesForOnlyDrive0 125 | 126 | 127 | ## 调试笔记 128 | usb2.0 fs 64字节一包, 129 | 指令里可能有需要操作回复的,导致必须处理完才能收下一包 130 | 131 | 4b, TMS bit输出 132 | 1b, 输出bits 133 | 6b, TMS bit输入输出 134 | 19, 输出bytes数据 135 | 136 | 修改后两包间的时间间隔已经在15~40us, 但是还是烧录失败 137 | 138 | xpage时序详见UG290手册(FPGA产品编程配置手册) 139 | 表5-8写明了JTAG TCK要求,1~5MHz 140 | 141 | 142 | 4b 03 03 143 | 1b 06 15 144 | 6b 00 01 145 | 4b 01 01 146 | 4b 05 00 147 | 4b 03 03 148 | 1b 06 71 149 | 6b 00 01 150 | 4b 01 01 151 | 4b 05 00 152 | 19 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 153 | 4b 02 01 154 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/uart_interface.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file uart_interface.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | #include "uart_interface.h" 25 | 26 | #include "bflb_platform.h" 27 | #include "hal_dma.h" 28 | #include "hal_gpio.h" 29 | #include "hal_usb.h" 30 | #include "io_cfg.h" 31 | 32 | #define USB_OUT_RINGBUFFER_SIZE (8 * 1024) 33 | #define UART_RX_RINGBUFFER_SIZE (8 * 1024) 34 | #define UART_TX_DMA_SIZE (4095) 35 | 36 | uint8_t usb_rx_mem[USB_OUT_RINGBUFFER_SIZE] 37 | __attribute__((section(".system_ram"))); 38 | uint8_t uart_rx_mem[UART_RX_RINGBUFFER_SIZE] 39 | __attribute__((section(".system_ram"))); 40 | 41 | uint8_t src_buffer[UART_TX_DMA_SIZE] __attribute__((section(".tcm_code"))); 42 | 43 | struct device *uart1; 44 | struct device *dma_ch2; 45 | 46 | Ring_Buffer_Type usb_rx_rb; 47 | Ring_Buffer_Type uart1_rx_rb; 48 | 49 | void uart_irq_callback(struct device *dev, void *args, uint32_t size, 50 | uint32_t state) { 51 | switch (state) { 52 | case UART_EVENT_RX_FIFO: 53 | case UART_EVENT_RTO: 54 | if (size && size < Ring_Buffer_Get_Empty_Length(&uart1_rx_rb)) { 55 | Ring_Buffer_Write(&uart1_rx_rb, (uint8_t *)args, size); 56 | } else { 57 | MSG(state == UART_EVENT_RX_FIFO ? "RF\r\n" : "RTO\r\n"); 58 | } 59 | break; 60 | case UART_RX_FER_IT: 61 | MSG("OV\r\n"); 62 | break; 63 | default: 64 | break; 65 | } 66 | } 67 | 68 | void uart1_init(void) { 69 | uart_register(UART1_INDEX, "uart1"); 70 | dma_register(DMA0_CH2_INDEX, "ch2"); 71 | uart1 = device_find("uart1"); 72 | dma_ch2 = device_find("ch2"); 73 | 74 | if (uart1 && dma_ch2) { 75 | device_open( 76 | uart1, DEVICE_OFLAG_DMA_TX | DEVICE_OFLAG_INT_RX); // uart tx dma mode 77 | // device_control(uart1, DEVICE_CTRL_SUSPEND, NULL); 78 | device_set_callback(uart1, uart_irq_callback); 79 | device_control(uart1, DEVICE_CTRL_SET_INT, 80 | (void *)(UART_RX_FIFO_IT | UART_RTO_IT)); 81 | device_open(dma_ch2, 0); 82 | device_control(uart1, DEVICE_CTRL_ATTACH_TX_DMA, dma_ch2); 83 | } 84 | } 85 | 86 | void uart1_config(uint32_t baudrate, uart_databits_t databits, 87 | uart_parity_t parity, uart_stopbits_t stopbits) { 88 | uart_param_cfg_t cfg; 89 | cfg.baudrate = baudrate; 90 | cfg.stopbits = stopbits; 91 | cfg.parity = parity; 92 | 93 | if (databits == 5) { 94 | cfg.databits = UART_DATA_LEN_5; 95 | } else if (databits == 6) { 96 | cfg.databits = UART_DATA_LEN_6; 97 | } else if (databits == 7) { 98 | cfg.databits = UART_DATA_LEN_7; 99 | } else if (databits == 8) { 100 | cfg.databits = UART_DATA_LEN_8; 101 | } 102 | 103 | device_control(uart1, DEVICE_CTRL_CONFIG, &cfg); 104 | device_control(uart1, DEVICE_CTRL_RESUME, NULL); 105 | } 106 | 107 | static uint8_t uart1_dtr; 108 | static uint8_t uart1_rts; 109 | 110 | void uart1_set_dtr_rts(uint8_t dtr, uint8_t rts) { 111 | uart1_dtr = dtr; 112 | uart1_rts = rts; 113 | } 114 | 115 | void uart1_dtr_init(void) { gpio_set_mode(uart1_dtr, GPIO_OUTPUT_MODE); } 116 | void uart1_rts_init(void) { gpio_set_mode(uart1_rts, GPIO_OUTPUT_MODE); } 117 | void uart1_dtr_deinit(void) { gpio_set_mode(uart1_dtr, GPIO_INPUT_MODE); } 118 | void uart1_rts_deinit(void) { gpio_set_mode(uart1_rts, GPIO_INPUT_MODE); } 119 | void dtr_pin_set(uint8_t status) { gpio_write(uart1_dtr, status); } 120 | void rts_pin_set(uint8_t status) { gpio_write(uart1_rts, status); } 121 | void ringbuffer_lock() { cpu_global_irq_disable(); } 122 | void ringbuffer_unlock() { cpu_global_irq_enable(); } 123 | 124 | void uart_ringbuffer_init(void) { 125 | /* init mem for ring_buffer */ 126 | memset(usb_rx_mem, 0, USB_OUT_RINGBUFFER_SIZE); 127 | memset(uart_rx_mem, 0, UART_RX_RINGBUFFER_SIZE); 128 | 129 | /* init ring_buffer */ 130 | Ring_Buffer_Init(&usb_rx_rb, usb_rx_mem, USB_OUT_RINGBUFFER_SIZE, 131 | ringbuffer_lock, ringbuffer_unlock); 132 | Ring_Buffer_Init(&uart1_rx_rb, uart_rx_mem, UART_RX_RINGBUFFER_SIZE, 133 | ringbuffer_lock, ringbuffer_unlock); 134 | } 135 | 136 | static dma_control_data_t uart_dma_ctrl_cfg = { 137 | .bits.fix_cnt = 0, 138 | .bits.dst_min_mode = 0, 139 | .bits.dst_add_mode = 0, 140 | .bits.SI = 1, 141 | .bits.DI = 0, 142 | .bits.SWidth = DMA_TRANSFER_WIDTH_8BIT, 143 | .bits.DWidth = DMA_TRANSFER_WIDTH_8BIT, 144 | .bits.SBSize = 0, 145 | .bits.DBSize = 0, 146 | .bits.I = 0, 147 | .bits.TransferSize = 4095}; 148 | static dma_lli_ctrl_t uart_lli_list = {.src_addr = (uint32_t)src_buffer, 149 | .dst_addr = DMA_ADDR_UART1_TDR, 150 | .nextlli = 0}; 151 | 152 | extern void led_toggle(uint8_t idx); 153 | void uart_send_from_ringbuffer(void) { 154 | if (Ring_Buffer_Get_Length(&usb_rx_rb)) { 155 | if (!device_control(dma_ch2, DEVICE_CTRL_DMA_CHANNEL_GET_STATUS, NULL)) { 156 | uint32_t avalibleCnt = 157 | Ring_Buffer_Read(&usb_rx_rb, src_buffer, UART_TX_DMA_SIZE); 158 | 159 | if (avalibleCnt) { 160 | dma_channel_stop(dma_ch2); 161 | uart_dma_ctrl_cfg.bits.TransferSize = avalibleCnt; 162 | memcpy(&uart_lli_list.cfg, &uart_dma_ctrl_cfg, 163 | sizeof(dma_control_data_t)); 164 | device_control(dma_ch2, DEVICE_CTRL_DMA_CHANNEL_UPDATE, 165 | (void *)((uint32_t)&uart_lli_list)); 166 | dma_channel_start(dma_ch2); 167 | led_toggle(0); // TX indication 168 | } 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/uart_interface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file uart_interface.h 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | #ifndef __UART_IF_H__ 25 | #define __UART_IF_H__ 26 | 27 | #include "hal_uart.h" 28 | #include "ring_buffer.h" 29 | 30 | extern Ring_Buffer_Type usb_rx_rb; 31 | extern Ring_Buffer_Type uart1_rx_rb; 32 | 33 | void uart1_init(void); 34 | void uart1_config(uint32_t baudrate,uart_databits_t databits,uart_parity_t parity,uart_stopbits_t stopbits); 35 | void uart1_set_dtr_rts(uint8_t dtr, uint8_t rts); 36 | void uart1_dtr_init(void); 37 | void uart1_rts_init(void); 38 | void uart1_dtr_deinit(void); 39 | void uart1_rts_deinit(void); 40 | void dtr_pin_set(uint8_t status); 41 | void rts_pin_set(uint8_t status); 42 | void uart_ringbuffer_init(void); 43 | void uart_send_from_ringbuffer(void); 44 | #endif -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/usb_descriptor.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usbd_ftdi.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | 24 | #include "hal_usb.h" 25 | #include "usbd_core.h" 26 | #include "usbd_ftdi.h" 27 | #include "bl702_usb.h" 28 | 29 | const uint16_t ftdi_eeprom_info[] = 30 | { 31 | 0x0800, 0x0403, 0x6010, 0x0500, 0x3280, 0x0000, 0x0200, 0x1096, 32 | 0x1aa6, 0x0000, 0x0046, 0x0310, 0x004f, 0x0070, 0x0065, 0x006e, 33 | 0x002d, 0x0045, 0x0043, 0x031a, 0x0055, 0x0053, 0x0042, 0x0020, 34 | 0x0044, 0x0065, 0x0062, 0x0075, 0x0067, 0x0067, 0x0065, 0x0072, 35 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 36 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 37 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 38 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1027 39 | }; 40 | 41 | // const uint16_t ftdi_eeprom_info[] = 42 | // { 43 | // 0x0108, 0x0403, 0x6010, 0x0700, 0x3280, 0x0008, 0x0000, 0x0A9A, 44 | // 0x2CA4, 0x16D0, 0x0000, 0x0000, 0x0046, 0x030A, 0x0046, 0x0054 , 45 | // 0x0044, 0x0049, 0x032C, 0x0042, 0x006F, 0x0075, 0x0066, 0x0066 , 46 | // 0x0061, 0x006C, 0x006F, 0x0020, 0x004C, 0x0061, 0x0062, 0x0020 , 47 | // 0x0044, 0x0065, 0x0062, 0x0075, 0x0067, 0x0067, 0x0065, 0x0072, 48 | // 0x0316, 0x0042, 0x0046, 0x004C, 0x0042, 0x0031, 0x0032, 0x0033 , 49 | // 0x0034, 0x0035, 0x0036, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 , 50 | // 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x53FC , 51 | // }; 52 | uint8_t cdc_descriptor[] = 53 | { 54 | /////////////////////////////////////// 55 | /// device descriptor 56 | /////////////////////////////////////// 57 | 0x12, /* bLength */ 58 | USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */ 59 | 0x00, 0x02, /* bcdUSB */ 60 | 0x00, /* bDeviceClass */ 61 | 0x00, /* bDeviceSubClass */ 62 | 0x00, /* bDeviceProtocol */ 63 | 0x40, /* bMaxPacketSize */ 64 | 0x03, 0x04, /* idVendor */ 65 | 0x10, 0x60, /* idProduct */ 66 | 0x00, 0x05, /* bcdDevice */ 67 | 0x01, /* iManufacturer */ 68 | 0x02, /* iProduct */ 69 | 0x03, /* iSerial */ 70 | 0x01, /* bNumConfigurations */ 71 | 72 | /////////////////////////////////////// 73 | /// config descriptor 74 | /////////////////////////////////////// 75 | 0x09, /* bLength */ 76 | USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */ 77 | 0x37, 0x00, /* wTotalLength */ 78 | 0x02, /* bNumInterfaces */ 79 | 0x01, /* bConfigurationValue */ 80 | 0x00, /* iConfiguration */ 81 | 0xa0, /* bmAttributes */ 82 | 0x2d, /* bMaxPower */ 83 | 84 | /////////////////////////////////////// 85 | /// interface descriptor 86 | /////////////////////////////////////// 87 | 0x09, /* bLength */ 88 | USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ 89 | 0x00, /* bInterfaceNumber */ 90 | 0x00, /* bAlternateSetting */ 91 | 0x02, /* bNumEndpoints */ 92 | 0xff, /* bInterfaceClass */ 93 | 0xff, /* bInterfaceSubClass */ 94 | 0xff, /* bInterfaceProtocol */ 95 | 0x02, /* iInterface */ 96 | 97 | /////////////////////////////////////// 98 | /// endpoint descriptor 99 | /////////////////////////////////////// 100 | 0x07, /* bLength */ 101 | USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ 102 | 0x81, /* bEndpointAddress */ 103 | 0x02, /* bmAttributes */ 104 | 0x40, 0x00, /* wMaxPacketSize */ 105 | 0x01, /* bInterval */ 106 | 107 | /////////////////////////////////////// 108 | /// endpoint descriptor 109 | /////////////////////////////////////// 110 | 0x07, /* bLength */ 111 | USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ 112 | 0x02, /* bEndpointAddress */ 113 | 0x02, /* bmAttributes */ 114 | 0x40, 0x00, /* wMaxPacketSize */ 115 | 0x01, /* bInterval */ 116 | 117 | /////////////////////////////////////// 118 | /// interface descriptor 119 | /////////////////////////////////////// 120 | 0x09, /* bLength */ 121 | USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ 122 | 0x01, /* bInterfaceNumber */ 123 | 0x00, /* bAlternateSetting */ 124 | 0x02, /* bNumEndpoints */ 125 | 0xff, /* bInterfaceClass */ 126 | 0xff, /* bInterfaceSubClass */ 127 | 0xff, /* bInterfaceProtocol */ 128 | 0x00, /* iInterface */ 129 | 130 | /////////////////////////////////////// 131 | /// endpoint descriptor 132 | /////////////////////////////////////// 133 | 0x07, /* bLength */ 134 | USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ 135 | CDC_IN_EP, /* bEndpointAddress */ 136 | 0x02, /* bmAttributes */ 137 | 0x40, 0x00, /* wMaxPacketSize */ 138 | 0x01, /* bInterval */ 139 | 140 | /////////////////////////////////////// 141 | /// endpoint descriptor 142 | /////////////////////////////////////// 143 | 0x07, /* bLength */ 144 | USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ 145 | CDC_OUT_EP, /* bEndpointAddress */ 146 | 0x02, /* bmAttributes */ 147 | 0x40, 0x00, /* wMaxPacketSize */ 148 | 0x01, /* bInterval */ 149 | 150 | /////////////////////////////////////// 151 | /// string0 descriptor 152 | /////////////////////////////////////// 153 | 0x04, /* bLength */ 154 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 155 | 0x09, 0x04, /* wLangID0 */ 156 | /////////////////////////////////////// 157 | /// string1 descriptor 158 | /////////////////////////////////////// 159 | 0x0E, /* bLength */ 160 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 161 | 'S', 0x00, /* wcChar0 */ 162 | 'I', 0x00, /* wcChar1 */ 163 | 'P', 0x00, /* wcChar2 */ 164 | 'E', 0x00, /* wcChar3 */ 165 | 'E', 0x00, /* wcChar4 */ 166 | 'D', 0x00, /* wcChar5 */ 167 | /////////////////////////////////////// 168 | /// string2 descriptor 169 | /////////////////////////////////////// 170 | 0x1c, /* bLength */ 171 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 172 | 'J', 0x00, /* wcChar0 */ 173 | 'T', 0x00, /* wcChar1 */ 174 | 'A', 0x00, /* wcChar2 */ 175 | 'G', 0x00, /* wcChar3 */ 176 | ' ', 0x00, /* wcChar4 */ 177 | 'D', 0x00, /* wcChar5 */ 178 | 'e', 0x00, /* wcChar6 */ 179 | 'b', 0x00, /* wcChar7 */ 180 | 'u', 0x00, /* wcChar8 */ 181 | 'g', 0x00, /* wcChar9 */ 182 | 'g', 0x00, /* wcChar10 */ 183 | 'e', 0x00, /* wcChar11 */ 184 | 'r', 0x00, /* wcChar12 */ 185 | /////////////////////////////////////// 186 | /// string3 descriptor 187 | /////////////////////////////////////// 188 | 0x30, /* bLength */ 189 | USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ 190 | 'F', 0x00, /* wcChar0 */ 191 | 'a', 0x00, /* wcChar1 */ 192 | 'c', 0x00, /* wcChar2 */ 193 | 't', 0x00, /* wcChar3 */ 194 | 'o', 0x00, /* wcChar4 */ 195 | 'r', 0x00, /* wcChar5 */ 196 | 'y', 0x00, /* wcChar6 */ 197 | 'A', 0x00, /* wcChar7 */ 198 | 'I', 0x00, /* wcChar8 */ 199 | 'O', 0x00, /* wcChar9 */ 200 | 'T', 0x00, /* wcChar10 */ 201 | ' ', 0x00, /* wcChar11 */ 202 | 'P', 0x00, /* wcChar12 */ 203 | 'r', 0x00, /* wcChar13 */ 204 | 'o', 0x00, /* wcChar14 */ 205 | 'g', 0x00, /* wcChar15 */ 206 | ' ', 0x00, /* wcChar16 */ 207 | 'S', 0x00, /* wcChar17 */ 208 | 'e', 0x00, /* wcChar18 */ 209 | 'r', 0x00, /* wcChar19 */ 210 | 'i', 0x00, /* wcChar20 */ 211 | 'a', 0x00, /* wcChar21 */ 212 | 'l', 0x00, /* wcChar22 */ 213 | /////////////////////////////////////// 214 | /// device qualifier descriptor 215 | /////////////////////////////////////// 216 | 0x0a, 217 | USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, 218 | 0x00, 219 | 0x00, 220 | 0x00, 221 | 0x00, 222 | 0x00, 223 | 0x40, 224 | 0x01, 225 | 0x00, 226 | 227 | 0x00 228 | }; -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/usbd_ftdi.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usbd_ftdi.c 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | #include "usbd_core.h" 24 | #include "usbd_ftdi.h" 25 | 26 | extern const uint16_t ftdi_eeprom_info[]; 27 | static volatile uint32_t sof_tick = 0; 28 | static uint8_t Latency_Timer1 = 0x0004; 29 | static uint8_t Latency_Timer2 = 0x0004; 30 | const char *stop_name[] = {"1", "1.5", "2"}; 31 | const char *parity_name[] = {"N","O","E","M","S"}; 32 | 33 | static void usbd_ftdi_reset(void) 34 | { 35 | Latency_Timer1 = 0x0010; 36 | Latency_Timer2 = 0x0010; 37 | sof_tick = 0; 38 | } 39 | 40 | /* Requests */ 41 | #define SIO_RESET_REQUEST 0x00 /* Reset the port */ 42 | #define SIO_SET_MODEM_CTRL_REQUEST 0x01 /* Set the modem control register */ 43 | #define SIO_SET_FLOW_CTRL_REQUEST 0x02 /* Set flow control register */ 44 | #define SIO_SET_BAUDRATE_REQUEST 0x03 /* Set baud rate */ 45 | #define SIO_SET_DATA_REQUEST 0x04 /* Set the data characteristics of the port */ 46 | #define SIO_POLL_MODEM_STATUS_REQUEST 0x05 47 | #define SIO_SET_EVENT_CHAR_REQUEST 0x06 48 | #define SIO_SET_ERROR_CHAR_REQUEST 0x07 49 | #define SIO_SET_LATENCY_TIMER_REQUEST 0x09 50 | #define SIO_GET_LATENCY_TIMER_REQUEST 0x0A 51 | #define SIO_SET_BITMODE_REQUEST 0x0B 52 | #define SIO_READ_PINS_REQUEST 0x0C 53 | #define SIO_READ_EEPROM_REQUEST 0x90 54 | #define SIO_WRITE_EEPROM_REQUEST 0x91 55 | #define SIO_ERASE_EEPROM_REQUEST 0x92 56 | 57 | #define SIO_DISABLE_FLOW_CTRL 0x0 58 | #define SIO_RTS_CTS_HS (0x1 << 8) 59 | #define SIO_DTR_DSR_HS (0x2 << 8) 60 | #define SIO_XON_XOFF_HS (0x4 << 8) 61 | 62 | #define SIO_SET_DTR_MASK 0x1 63 | #define SIO_SET_DTR_HIGH ( 1 | ( SIO_SET_DTR_MASK << 8)) 64 | #define SIO_SET_DTR_LOW ( 0 | ( SIO_SET_DTR_MASK << 8)) 65 | #define SIO_SET_RTS_MASK 0x2 66 | #define SIO_SET_RTS_HIGH ( 2 | ( SIO_SET_RTS_MASK << 8 )) 67 | #define SIO_SET_RTS_LOW ( 0 | ( SIO_SET_RTS_MASK << 8 )) 68 | 69 | #define SIO_RTS_CTS_HS (0x1 << 8) 70 | 71 | static void ftdi_set_baudrate(uint32_t itdf_divisor, uint32_t *actual_baudrate) 72 | { 73 | #define FTDI_USB_CLK 48000000 74 | int baudrate; 75 | uint8_t frac[] = {0, 8, 4, 2, 6, 10, 12, 14}; 76 | int divisor = itdf_divisor & 0x3fff; 77 | divisor <<= 4; 78 | divisor |= frac[(itdf_divisor >> 14) & 0x07]; 79 | 80 | if(itdf_divisor == 0x01) 81 | { 82 | baudrate = 2000000; 83 | } 84 | else if(itdf_divisor == 0x00) 85 | { 86 | baudrate = 3000000; 87 | } 88 | else 89 | { 90 | baudrate = FTDI_USB_CLK / divisor; 91 | } 92 | if(baudrate>100000 && baudrate < 12000) 93 | { 94 | *actual_baudrate = (baudrate - 100000)*100000; 95 | } 96 | else 97 | *actual_baudrate = baudrate; 98 | 99 | } 100 | 101 | //static char datatmp[2]={0x32, 0x60}; 102 | static int ftdi_vendor_request_handler(struct usb_setup_packet *pSetup,uint8_t **data,uint32_t *len) 103 | { 104 | static uint32_t actual_baudrate = 1200; 105 | switch (pSetup->bRequest) 106 | { 107 | case SIO_READ_EEPROM_REQUEST: 108 | *data = (uint8_t*)&ftdi_eeprom_info[pSetup->wIndexL]; 109 | *len = 2; 110 | break; 111 | case SIO_RESET_REQUEST: 112 | 113 | break; 114 | 115 | case SIO_SET_MODEM_CTRL_REQUEST: 116 | if(pSetup->wValue == SIO_SET_DTR_HIGH) 117 | { 118 | //USBD_LOG("DTR 1\r\n"); 119 | usbd_ftdi_set_dtr(true); 120 | } 121 | else if(pSetup->wValue == SIO_SET_DTR_LOW) 122 | { 123 | //USBD_LOG("DTR 0\r\n"); 124 | usbd_ftdi_set_dtr(false); 125 | } 126 | else if(pSetup->wValue == SIO_SET_RTS_HIGH) 127 | { 128 | //USBD_LOG("RTS 1\r\n"); 129 | usbd_ftdi_set_rts(true); 130 | } 131 | else if(pSetup->wValue == SIO_SET_RTS_LOW) 132 | { 133 | //USBD_LOG("RTS 0\r\n"); 134 | usbd_ftdi_set_rts(false); 135 | } 136 | break; 137 | case SIO_SET_FLOW_CTRL_REQUEST: 138 | 139 | break; 140 | case SIO_SET_BAUDRATE_REQUEST://wValue,2个字节波特率 141 | { 142 | uint8_t baudrate_high = (pSetup->wIndex >> 8); 143 | ftdi_set_baudrate(pSetup->wValue|(baudrate_high<<16),&actual_baudrate); 144 | if(actual_baudrate != 1200) 145 | { 146 | usbd_ftdi_set_line_coding(actual_baudrate, 8, 0, 0); 147 | } 148 | break; 149 | } 150 | case SIO_SET_DATA_REQUEST: 151 | /** 152 | * D0-D7 databits BITS_7=7, BITS_8=8 153 | * D8-D10 parity NONE=0, ODD=1, EVEN=2, MARK=3, SPACE=4 154 | * D11-D12 STOP_BIT_1=0, STOP_BIT_15=1, STOP_BIT_2=2 155 | * D14 BREAK_OFF=0, BREAK_ON=1 156 | **/ 157 | if(actual_baudrate != 1200) 158 | { 159 | //USBD_LOG("CDC_SET_LINE_CODING <%d %d %s %s>\r\n",actual_baudrate,(uint8_t)pSetup->wValue,parity_name[(uint8_t)(pSetup->wValue>>8)],stop_name[(uint8_t)(pSetup->wValue>>11)]); 160 | usbd_ftdi_set_line_coding(actual_baudrate,(uint8_t)pSetup->wValue,(uint8_t)(pSetup->wValue>>8),(uint8_t)(pSetup->wValue>>11)); 161 | } 162 | break; 163 | 164 | case SIO_POLL_MODEM_STATUS_REQUEST: 165 | /* Poll modem status information 166 | 167 | This function allows the retrieve the two status bytes of the device. 168 | The device sends these bytes also as a header for each read access 169 | where they are discarded by ftdi_read_data(). The chip generates 170 | the two stripped status bytes in the absence of data every 40 ms. 171 | 172 | Layout of the first byte: 173 | - B0..B3 - must be 0 174 | - B4 Clear to send (CTS) 175 | 0 = inactive 176 | 1 = active 177 | - B5 Data set ready (DTS) 178 | 0 = inactive 179 | 1 = active 180 | - B6 Ring indicator (RI) 181 | 0 = inactive 182 | 1 = active 183 | - B7 Receive line signal detect (RLSD) 184 | 0 = inactive 185 | 1 = active 186 | 187 | Layout of the second byte: 188 | - B0 Data ready (DR) 189 | - B1 Overrun error (OE) 190 | - B2 Parity error (PE) 191 | - B3 Framing error (FE) 192 | - B4 Break interrupt (BI) 193 | - B5 Transmitter holding register (THRE) 194 | - B6 Transmitter empty (TEMT) 195 | - B7 Error in RCVR FIFO */ 196 | *data = (uint8_t*)&ftdi_eeprom_info[2]; 197 | *len = 2; 198 | break; 199 | case SIO_SET_EVENT_CHAR_REQUEST: 200 | 201 | break; 202 | case SIO_SET_ERROR_CHAR_REQUEST: 203 | 204 | break; 205 | case SIO_SET_LATENCY_TIMER_REQUEST: 206 | if(pSetup->wIndexL == 1) 207 | Latency_Timer1 = pSetup->wValueL; 208 | else 209 | Latency_Timer2 = pSetup->wValueL; 210 | break; 211 | case SIO_GET_LATENCY_TIMER_REQUEST: 212 | if(pSetup->wIndexL == 1) 213 | *data = &Latency_Timer1; 214 | else 215 | *data = &Latency_Timer2; 216 | *len = 1; 217 | //USBD_LOG("get latency:%d,len:%d\r\n",Latency_Timer1,*len); 218 | break; 219 | case SIO_SET_BITMODE_REQUEST: 220 | 221 | break; 222 | default: 223 | USBD_LOG_DBG("CDC ACM request 0x%x, value 0x%x\r\n", 224 | pSetup->bRequest, pSetup->wValue); 225 | return -1; 226 | } 227 | return 0; 228 | 229 | } 230 | static void ftdi_notify_handler(uint8_t event, void* arg) 231 | { 232 | switch (event) 233 | { 234 | case USB_EVENT_RESET: 235 | usbd_ftdi_reset(); 236 | break; 237 | case USB_EVENT_SOF: 238 | sof_tick++; 239 | USBD_LOG_DBG("tick: %d\r\n", sof_tick); 240 | break; 241 | default: 242 | break; 243 | } 244 | } 245 | 246 | __weak void usbd_ftdi_set_line_coding(uint32_t baudrate,uint8_t databits,uint8_t parity,uint8_t stopbits) 247 | { 248 | 249 | } 250 | __weak void usbd_ftdi_set_dtr(bool dtr) 251 | { 252 | 253 | } 254 | __weak void usbd_ftdi_set_rts(bool rts) 255 | { 256 | 257 | } 258 | uint32_t usbd_ftdi_get_sof_tick(void) 259 | { 260 | return sof_tick; 261 | } 262 | 263 | uint32_t usbd_ftdi_get_latency_timer1(void) 264 | { 265 | return Latency_Timer1; 266 | } 267 | 268 | uint32_t usbd_ftdi_get_latency_timer2(void) 269 | { 270 | return Latency_Timer2; 271 | } 272 | 273 | void usbd_ftdi_add_interface(usbd_class_t *class, usbd_interface_t *intf) 274 | { 275 | static usbd_class_t *last_class = NULL; 276 | 277 | if(last_class != class) 278 | { 279 | last_class = class; 280 | usbd_class_register(class); 281 | } 282 | 283 | intf->class_handler = NULL; 284 | intf->custom_handler = NULL; 285 | intf->vendor_handler = ftdi_vendor_request_handler; 286 | intf->notify_handler = ftdi_notify_handler; 287 | usbd_class_add_interface(class,intf); 288 | } 289 | -------------------------------------------------------------------------------- /firmware/app/usb2uartjtag/usbd_ftdi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file usbd_ftdi.h 3 | * @brief 4 | * 5 | * Copyright (c) 2021 Sipeed team 6 | * 7 | * Licensed to the Apache Software Foundation (ASF) under one or more 8 | * contributor license agreements. See the NOTICE file distributed with 9 | * this work for additional information regarding copyright ownership. The 10 | * ASF licenses this file to you under the Apache License, Version 2.0 (the 11 | * "License"); you may not use this file except in compliance with the 12 | * License. You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | * License for the specific language governing permissions and limitations 20 | * under the License. 21 | * 22 | */ 23 | #ifndef _USBD_FTDI_H 24 | #define _USBD_FTDI_H 25 | 26 | #define CDC_IN_EP 0x83 27 | #define CDC_OUT_EP 0x04 28 | 29 | #define JTAG_IN_EP 0x81 30 | #define JTAG_OUT_EP 0x02 31 | 32 | void usbd_ftdi_add_interface(usbd_class_t *class, usbd_interface_t *intf); 33 | 34 | void usbd_ftdi_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits); 35 | void usbd_ftdi_set_dtr(bool dtr); 36 | void usbd_ftdi_set_rts(bool rts); 37 | uint32_t usbd_ftdi_get_sof_tick(void); 38 | uint32_t usbd_ftdi_get_latency_timer1(void); 39 | uint32_t usbd_ftdi_get_latency_timer2(void); 40 | #endif /* USB_FTDI_H_ */ 41 | -------------------------------------------------------------------------------- /hardware/BL702_USB2JTAG_3610_asm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/RV-Debugger-BL702/7f17747f98c1441e19410d41c9be37e6d126131b/hardware/BL702_USB2JTAG_3610_asm.pdf -------------------------------------------------------------------------------- /hardware/BL702_USB2JTAG_3610_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/RV-Debugger-BL702/7f17747f98c1441e19410d41c9be37e6d126131b/hardware/BL702_USB2JTAG_3610_sch.pdf -------------------------------------------------------------------------------- /res/MPSSE.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/RV-Debugger-BL702/7f17747f98c1441e19410d41c9be37e6d126131b/res/MPSSE.pdf -------------------------------------------------------------------------------- /res/rv-debugger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/RV-Debugger-BL702/7f17747f98c1441e19410d41c9be37e6d126131b/res/rv-debugger.png --------------------------------------------------------------------------------