├── .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
--------------------------------------------------------------------------------