├── .cproject
├── .gitattributes
├── .gitignore
├── .project
├── LICENSE
├── README.md
├── USBCompositeDevice.uvopt
├── USBCompositeDevice.uvproj
├── bootloader.c
├── bootloader.h
├── ch554_conf.c
├── ch554_conf.h
├── ch554_platform.h
├── delay.c
├── delay.h
├── host
├── .gitignore
├── CH554_CDC_BusBridge.sln
├── CH554_CDC_BusBridge.vcxproj
├── CH554_CDC_BusBridge.vcxproj.filters
├── Makefile
├── flash25.c
├── flash25.h
├── main.c
├── rikka.png
├── rs232.c
├── rs232.h
├── spi.c
└── spi.h
├── i2c.c
├── i2c.h
├── include
├── ch554.h
├── ch554_datatypes.h
└── ch554_usb.h
├── keilc51
├── CH554.H
└── CH554.INC
├── main.c
├── spi.c
├── spi.h
├── usb_cdc.c
├── usb_cdc.h
├── usb_desc.c
├── usb_desc.h
├── usb_endp.c
├── usb_endp.h
├── usb_ep0.c
├── usb_it.c
└── usb_string_desc.c
/.cproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
54 | # Keil
55 | Listings/
56 | Objects/
57 | *.build_log.htm
58 | *.uvgui.*
59 |
60 | # Eclipse SDCC
61 | .settings/
62 | Release/
63 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | USB_CDC
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
16 | full,incremental,
17 |
18 |
19 |
20 |
21 |
22 | org.eclipse.cdt.core.cnature
23 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
24 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 rikka0w0
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CH554 USB CDC
2 |
3 | This demo emulates a USB CDC, which is equivalent to a UART port. (本演示程序模拟了一个USB CDC设备, 可以当作串口使用):
4 |
5 | Author(作者): Rikka0w0 (小六花)
6 | Original Author(原作者): rgwan (Zhiyuan Wan)
7 |
8 | * `keilc51\CH554.H`, `Delay.C` and `Delay.h` comes from official CH554 demo (WCH), the USB MSD implementation is inspired by the USB MSD demo for STM32 (ST).
9 | (`keilc51\CH554.H`, `Delay.C`和`Delay.h`是从WCH官方的示例代码里提取的,U盘部分程序参考了STM32的USB MSD示例)
10 | * All file in folder `includes` comes from Github repository [Blinkinlabs's ch554_sdcc](https://github.com/Blinkinlabs/ch554_sdcc).
11 | (`includes`文件夹中的文件是从[Blinkinlabs's ch554_sdcc](https://github.com/Blinkinlabs/ch554_sdcc)里复制的)
12 | * Compiler/IDE: Keil uVersion & SDCC. (编译器/开发环境:Keil 礦ision和SDCC)
13 | * A Wiki page describes how to setup SDCC on Windows and Linux. (Wiki中会介绍如何在Windows和Linux上搭建SDCC编译环境)
14 | * Feel free to use this demo as the template/start of a open-source or non-commercial project, modifying source code and republishing is allowed.
15 | (对于开源项目和非商业项目,可以是用本演示代码作为起点或者模板,作者允许修改并重新发布这份代码)
16 | * However you __MUST__ contact the author for permission prior to use this demo for commercial purposes.
17 | (__如果用于商业目的的话,必须提前得到作者的允许__)
18 |
19 | # Hardware Setup(硬件配置):
20 | * The hardware is based on the minimal circuit setup of CH554
21 | (硬件基于CH554的最小系统)
22 | * Chip is directly powered by Vbus, which is approximately 5V
23 | (芯片直接由Vbus驱动,大约是5V)
24 | * P1.5 = I2C SDA, P1.4 = I2C SCL, defined in `i2c.c`, each pin is pull-up by a 1k resistor to 5V.
25 | (I2C引脚定义在`i2c.c`里面,每个脚都要一个1k的上拉电阻,上拉到5V)
26 | * Pin 1 to pin 4 of 24LC512 are connected to ground, Pin 8 connect to 5V, Pin5 is I2C SDA and Pin6 is I2C SCL, Pin7 is floating.
27 | (24LC512 EEPROM的1到4脚都接地,8脚连接5V,5脚对应I2C SDA,6脚对应I2C SCL,七脚悬空)
28 |
29 |
30 | # Capabilities(能做到什么):
31 | ## USB Mass Storage Device (USB大容量储存设备)
32 | * Emulate a 512Kib I2C EEPROM 24LC512 as a 64KB USB Drive
33 | (用512Kib的I2C总线EEPROM 24LC512模拟了一个64KB的U盘)
34 | * Read, write, delete and format operations are fully supported.
35 | (完全支持各种读写删除还有格式化操作)
36 | * Support safe media ejection in Windows, Linux and Mac OS X
37 | (在Windows, Linux和Mac OS X上支持安全弹出介质)
38 | * Use USB Endpoint 3 IN and OUT, Interface 2, Bulk-only transfer
39 | (使用了端点3的IN和OUT,2号接口,BOT传输)
40 | ## USB Keyboard (USB键盘)
41 | * Simulate key press and release, and send them to the host.
42 | (可以模拟键盘按键操作并发往主机)
43 | * Use USB Endpoint 1 IN, Interface 1, Interrupt transfer
44 | (使用了端点2的IN,1号接口, 中断传输)
45 | ## USB Vendor-Define HID (厂商自定义的USB HID设备)
46 | * Exchange data (receive and send) with host, up to 64 bytes each time
47 | (可以和主机交换数据,每次最多64字节)
48 | * Use USB Endpoint 2 IN, Interface 0, Interrupt transfer
49 | (使用了端点2的IN, 0号接口,中断传输)
50 | ## UART (串口)
51 | * UART0, no function re-mapping (0号串口,没有io重映射)
52 | * Exchange data (receive and send) with host (可以和主机交换数据)
53 | * Support printf (支持printf)
54 | ## I2C
55 | * CH55x does not have built-in I2C peripheral (CH55x系列木有内置I2C通信外设)
56 | * Implement and emulate a I2C peripheral with GPIO (用GPIO来模拟I2C总线通信)
57 |
58 | # File Structure(文件结构):
59 | ## main.c
60 | * void main(void) {}
61 | * USB Device Interrupt Entry(USB设备中断函数入口)
62 | ## Delay.c Delay.h
63 | * Delay (延时函数)
64 | ## ch554_platform.h
65 | * Define uint8_t, uint32_t e.t.c (定义uint8_t, uint32_t等等标准类型)
66 | * Handle the difference between Keil C51 and SDCC
67 | (处理Keil C51和SDCC编译器之间的差异)
68 | * `U16B0` returns the lowest byte of a 16-bit integer, regardless of endian, similar defination for `U16B1`, `U32B0` e.t.c
69 | (`U16B0`会返回一个16位整数的低字节,与端无关,`U16B1`, `U32B0`等也是类似功能)
70 | * `U16_XBig` converts a big-endian 16-bit integer to fit the local endian, vise versa, similar defination for `U16_XLittle`, `U32_XBig` and `U32_XLittle`.
71 | (`U16_XBig`用于将一个大端储存的16位数转换成当前的端方式,也可以用于反向转换,`U16_XLittle`, `U32_XBig`和`U32_XLittle`的作用类似)
72 | * Instead of using `sbit led=P1^1`, use `SBIT(var, port, bin)` to declare a bit variable, for example, `SBIT(led, GPIO1, 1)`, this facilitates compilation under different compilers.
73 | (最好用`SBIT(var, port, bin)`来声明位变量,比如`SBIT(led, GPIO1, 1)`来代替`sbit led=P1^1`,这样有助于在不同编译器下编译程序)
74 | ## ch554_conf.c ch554_conf.h
75 | * Configure system clock (配置系统时钟)
76 | * Initialize USB Device (初始化USB设备)
77 | * Initialize UART0 (初始化串口0)
78 | * Set system clock frequency and UART0 baud rate in ch554_conf.h
79 | (在ch554_conf.h里设置系统时钟频率和UART0的波特率)
80 | ## i2c.c i2c.h
81 | * Emulate a I2C bus host with GPIO (用GPIO来模拟一个I2C总线主机)
82 | * `I2C_DELAY(void)` controls the I2C clock frequency
83 | * `I2C_WriteByte()` sends the data byte in `I2C_Buf` to I2C bus and return the ACK status in bit 0 of `I2C_Buf` then release the I2C bus,
84 | 0 means ACK and 1 means NACK.
85 | (`I2C_WriteByte()`会把`I2C_Buf`里的一个字节发送到I2C总线上并在`I2C_Buf`的最低位返回ACK的状态然后释放I2C总线,0为ACK,1为NACK)
86 | * `I2C_ReadByte(void)` reads a byte from I2C bus and store it in `I2C_Buf`.
87 | (`I2C_ReadByte(void)`从I2C总线上读一个字节然后放在`I2C_Buf`里面)
88 | ## usb_it.c
89 | * USB interrupt service routine (USB中断处理函数)
90 | * Handle USB bus reset/suspend/wakeup (处理USB总线重置/挂起/唤醒)
91 | * Dispatch incoming requests to EndPoint service functions (把主机发来的请求分发给端点的处理函数)
92 | ## usb_endp.h
93 | * Declear EndPoint buffers (声明端点的缓存)
94 | * Toggle certain EndPoint service function (开启或者关闭相关的端点处理函数)
95 | ## usb_endp.c
96 | * Define EndPoint buffers (定义端点的缓存以及大小)
97 | * `USB_EP_HALT_SET(ep)` and `USB_EP_HALT_CLEAR(ep)` stall or restore an EndPoint as the host requests
98 | (`USB_EP_HALT_SET(ep)`和`USB_EP_HALT_CLEAR(ep)`根据主机请求挂起stall或者恢复端点)
99 | * Optionally, add your EndPoint service functions here (如果愿意可以把USB的端点处理函数放在这里)
100 | ## usb_ep0.c
101 | * Contain service routine for EndPoint 0 SETUP/IN/OUT
102 | (包含端点0的SETUP/IN/OUT事务的处理函数)
103 | * Handle requests sent by host during enumeration phase
104 | (在枚举的时候负责回应主机的请求)
105 | ## usb_desc.h
106 | * Define the total length of Config Descriptor, including Interface Descriptor e.t.c (定义配置描述符的总大小,包含接口描述符等)
107 | * Define the total number of String Descriptor (定义字符描述符的数量)
108 | * Define length of HID Report Descriptors (定义各种HID报告描述符的大小)
109 | ## usb_desc.c
110 | * Define Device Descriptor (定义设备描述符)
111 | * Define Configuration Descriptor and Interface Descriptor (定义配置和接口描述符)
112 | ## usb_string_desc.c
113 | * Define custom String Descriptors (定义自定义的字符描述符)
114 | * String Descriptor 0 is reserved for language configuration (0号字符描述符是为语言标识保留的)
115 |
116 | # Notes:
117 | * The only difference between CH554 and CH552 is that, CH552 only supports USB device mode while CH554 can also be programmed as a Host.
118 | So this demo may work on CH552 as well. (CH552只能作为USB的设备,而CH554还可以作为USB主机,这是两种芯片唯一的区别。因此本Demo可能也能在CH552上正常工作)
119 | * 8051 systems including CH554 is big-endian while x86 and ARM processors are little-endian.
120 | (8051系统包括CH554是大端存储的,即数据的高位放在低内存地址中,而x86和ARM处理器都是小端存储的)
121 | * USB packets are little-endian, keep this in mind!
122 | (USB包都是小端的,特别需要注意!)
123 | * SDCC requires that all interrupt service functions must be written inside the same .c file containing `void main(void)`,
124 | otherwise SDCC can not find them. According to official SDCC documentation, it's not a bug but a feature. Keil C51 doesn't have this limitaion.
125 | (SDCC要求中断处理函数必须和main函数放在一个.c文件中,否则SDCC没办法找到这些函数。根据SDCC官方文档,这是一个特性不算Bug,Keil C51编译器没有这种限制)
--------------------------------------------------------------------------------
/USBCompositeDevice.uvopt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.0
5 |
6 | ### uVision Project, (C) Keil Software
7 |
8 |
9 | *.c
10 | *.s*; *.src; *.a*
11 | *.obj
12 | *.lib
13 | *.txt; *.h; *.inc
14 | *.plm
15 | *.cpp
16 | 0
17 |
18 |
19 |
20 | 0
21 | 0
22 |
23 |
24 |
25 | Target 1
26 | 0x0
27 | MCS-51
28 |
29 | 24000000
30 |
31 | 1
32 | 1
33 | 1
34 | 0
35 | 0
36 |
37 |
38 | 0
39 | 65535
40 | 0
41 | 0
42 | 0
43 |
44 |
45 | 120
46 | 65
47 | 8
48 | .\Listings\
49 |
50 |
51 | 1
52 | 1
53 | 1
54 | 0
55 | 1
56 | 1
57 | 0
58 | 1
59 | 0
60 | 0
61 | 0
62 | 0
63 |
64 |
65 | 1
66 | 1
67 | 1
68 | 1
69 | 1
70 | 1
71 | 1
72 | 0
73 | 0
74 |
75 |
76 | 1
77 | 0
78 | 1
79 |
80 | 255
81 |
82 |
83 | 0
84 | Data Sheet
85 | DATASHTS\SST\SST89C5X.PDF
86 |
87 |
88 |
89 | 1
90 | 0
91 | 1
92 | 1
93 | 1
94 | 1
95 | 1
96 | 1
97 | 1
98 | 1
99 | 0
100 | 1
101 | 1
102 | 1
103 | 0
104 | 1
105 | 1
106 | 1
107 | 1
108 | 0
109 | 0
110 | -1
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | 0
126 | DLGDP51
127 | (98=-1,-1,-1,-1,0)(82=-1,-1,-1,-1,0)(83=-1,-1,-1,-1,0)(84=-1,-1,-1,-1,0)(85=-1,-1,-1,-1,0)(3003=-1,-1,-1,-1,0)(91=-1,-1,-1,-1,0)(92=-1,-1,-1,-1,0)(93=-1,-1,-1,-1,0)
128 |
129 |
130 |
131 |
132 | 0
133 |
134 |
135 | 0
136 | 1
137 | 1
138 | 0
139 | 0
140 | 0
141 | 0
142 | 1
143 | 0
144 | 0
145 | 0
146 | 0
147 | 0
148 | 0
149 | 0
150 | 0
151 | 0
152 | 0
153 | 0
154 | 0
155 | 0
156 | 0
157 | 0
158 | 0
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | Source Group 1
167 | 1
168 | 0
169 | 0
170 | 0
171 |
172 | 1
173 | 1
174 | 1
175 | 0
176 | 0
177 | 0
178 | 0
179 | .\usb_ep0.c
180 | usb_ep0.c
181 | 0
182 | 0
183 |
184 |
185 | 1
186 | 2
187 | 1
188 | 0
189 | 0
190 | 0
191 | 0
192 | .\usb_desc.c
193 | usb_desc.c
194 | 0
195 | 0
196 |
197 |
198 | 1
199 | 3
200 | 1
201 | 0
202 | 0
203 | 0
204 | 0
205 | .\usb_it.c
206 | usb_it.c
207 | 0
208 | 0
209 |
210 |
211 | 1
212 | 4
213 | 1
214 | 0
215 | 0
216 | 0
217 | 0
218 | .\usb_endp.c
219 | usb_endp.c
220 | 0
221 | 0
222 |
223 |
224 | 1
225 | 5
226 | 1
227 | 0
228 | 0
229 | 0
230 | 0
231 | .\usb_string_desc.c
232 | usb_string_desc.c
233 | 0
234 | 0
235 |
236 |
237 | 1
238 | 6
239 | 1
240 | 0
241 | 0
242 | 0
243 | 0
244 | .\i2c.c
245 | i2c.c
246 | 0
247 | 0
248 |
249 |
250 | 1
251 | 7
252 | 1
253 | 0
254 | 0
255 | 0
256 | 0
257 | .\ch554_conf.c
258 | ch554_conf.c
259 | 0
260 | 0
261 |
262 |
263 | 1
264 | 8
265 | 1
266 | 0
267 | 0
268 | 0
269 | 0
270 | .\main.c
271 | main.c
272 | 0
273 | 0
274 |
275 |
276 | 1
277 | 9
278 | 1
279 | 0
280 | 0
281 | 0
282 | 0
283 | .\bootloader.c
284 | bootloader.c
285 | 0
286 | 0
287 |
288 |
289 | 1
290 | 10
291 | 1
292 | 0
293 | 0
294 | 0
295 | 0
296 | .\delay.c
297 | delay.c
298 | 0
299 | 0
300 |
301 |
302 | 1
303 | 11
304 | 1
305 | 0
306 | 0
307 | 0
308 | 0
309 | .\usb_cdc.c
310 | usb_cdc.c
311 | 0
312 | 0
313 |
314 |
315 | 1
316 | 12
317 | 1
318 | 0
319 | 0
320 | 0
321 | 0
322 | .\spi.c
323 | spi.c
324 | 0
325 | 0
326 |
327 |
328 |
329 |
330 |
--------------------------------------------------------------------------------
/USBCompositeDevice.uvproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.1
5 |
6 | ### uVision Project, (C) Keil Software
7 |
8 |
9 |
10 | Target 1
11 | 0x0
12 | MCS-51
13 |
14 |
15 | SST89C54
16 | SST
17 | IRAM(0-0xFF) IROM(0-0x3FFF) CLOCK(33000000)
18 |
19 | "LIB\STARTUP.A51" ("Standard 8051 Startup Code")
20 |
21 | 2932
22 | REG52.H
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 0
34 | 0
35 |
36 |
37 |
38 |
39 |
40 |
41 | 0
42 | 0
43 | 0
44 | 0
45 | 1
46 |
47 | .\Objects\
48 | USBCompositeDevice
49 | 1
50 | 0
51 | 1
52 | 1
53 | 1
54 | .\Listings\
55 | 0
56 | 0
57 | 0
58 |
59 | 0
60 | 0
61 |
62 |
63 | 0
64 | 0
65 | 0
66 | 0
67 |
68 |
69 | 0
70 | 0
71 |
72 |
73 | 0
74 | 0
75 | 0
76 | 0
77 |
78 |
79 | 0
80 | 0
81 |
82 |
83 | 0
84 | 0
85 |
86 | 0
87 |
88 |
89 |
90 | 0
91 | 0
92 | 0
93 | 0
94 | 0
95 | 1
96 | 0
97 | 0
98 | 0
99 | 0
100 | 3
101 |
102 |
103 | 1
104 | 65535
105 |
106 |
107 | S8051.DLL
108 |
109 | DP51.DLL
110 | -pSST5X
111 | S8051.DLL
112 |
113 | TP51.DLL
114 | -pSST5X
115 |
116 |
117 |
118 | 0
119 | 0
120 | 0
121 | 0
122 | 16
123 |
124 |
125 | 1
126 | 1
127 | 1
128 | 1
129 | 1
130 | 1
131 | 1
132 | 1
133 | 0
134 | 1
135 |
136 |
137 | 0
138 | 1
139 | 0
140 | 1
141 | 1
142 | 1
143 | 0
144 | 1
145 | 1
146 | 1
147 |
148 | 0
149 | -1
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | 1
169 | 0
170 | 0
171 | 0
172 | 0
173 | -1
174 |
175 | 0
176 |
177 | "" ()
178 |
179 |
180 |
181 |
182 | 0
183 |
184 |
185 |
186 | 0
187 | 0
188 | 2
189 | 0
190 | 0
191 | 0
192 | 0
193 | 0
194 | 0
195 | 1
196 | 0
197 | 1
198 | 0
199 | 0
200 | 0
201 | 0
202 | 0
203 | 0
204 | 0
205 | 0
206 | 0
207 | 0
208 | 0
209 | 0
210 | 0
211 | 0
212 | 0
213 | 0
214 | 0
215 | 0
216 | 0
217 | 0
218 | 0
219 | 0
220 | 0
221 | 0
222 | 0
223 | 0
224 | 0
225 | 0
226 | 0
227 |
228 |
229 | 0
230 | 0x0
231 | 0xffff
232 |
233 |
234 | 0
235 | 0x0
236 | 0x0
237 |
238 |
239 | 0
240 | 0x0
241 | 0x0
242 |
243 |
244 | 0
245 | 0x0
246 | 0x0
247 |
248 |
249 | 0
250 | 0x0
251 | 0x0
252 |
253 |
254 | 0
255 | 0x0
256 | 0x0
257 |
258 |
259 | 0
260 | 0x0
261 | 0x0
262 |
263 |
264 | 0
265 | 0x0
266 | 0x0
267 |
268 |
269 | 1
270 | 0x0
271 | 0x4000
272 |
273 |
274 | 0
275 | 0x0
276 | 0x100
277 |
278 |
279 | 0
280 | 0x0
281 | 0x0
282 |
283 |
284 | 0
285 | 0x0
286 | 0x0
287 |
288 |
289 | 0
290 | 0x0
291 | 0x0
292 |
293 |
294 |
295 |
296 | 0
297 | 0
298 | 1
299 | 0
300 | 1
301 | 3
302 | 8
303 | 2
304 | 1
305 | 1
306 | 0
307 | 0
308 |
309 |
310 | CLOCK_FREQ_24
311 |
312 |
313 |
314 |
315 |
316 | 0
317 | 1
318 | 0
319 | 0
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | 0
329 | 0
330 | 1
331 | 0
332 | 2
333 | 1
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 | Source Group 1
363 |
364 |
365 | usb_ep0.c
366 | 1
367 | .\usb_ep0.c
368 |
369 |
370 | usb_desc.c
371 | 1
372 | .\usb_desc.c
373 |
374 |
375 | usb_it.c
376 | 1
377 | .\usb_it.c
378 |
379 |
380 | usb_endp.c
381 | 1
382 | .\usb_endp.c
383 |
384 |
385 | usb_string_desc.c
386 | 1
387 | .\usb_string_desc.c
388 |
389 |
390 | i2c.c
391 | 1
392 | .\i2c.c
393 |
394 |
395 | ch554_conf.c
396 | 1
397 | .\ch554_conf.c
398 |
399 |
400 | main.c
401 | 1
402 | .\main.c
403 |
404 |
405 | bootloader.c
406 | 1
407 | .\bootloader.c
408 |
409 |
410 | 2
411 | 0
412 | 0
413 | 0
414 | 0
415 | 2
416 | 2
417 | 1
418 | 1
419 | 2
420 | 11
421 |
422 |
423 | 1
424 | 65535
425 |
426 |
427 |
428 | 2
429 | 2
430 | 2
431 | 2
432 | 2
433 | 8
434 | 10
435 | 3
436 | 2
437 | 2
438 | 2
439 | 0
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 | delay.c
452 | 1
453 | .\delay.c
454 |
455 |
456 | usb_cdc.c
457 | 1
458 | .\usb_cdc.c
459 |
460 |
461 | spi.c
462 | 1
463 | .\spi.c
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
--------------------------------------------------------------------------------
/bootloader.c:
--------------------------------------------------------------------------------
1 | #include "bootloader.h"
2 | #include "delay.h"
3 | #include "ch554_platform.h"
4 |
5 | void JumpToBootloader(void) {
6 | USB_INT_EN = 0;
7 | USB_CTRL = 0x06;
8 |
9 | mDelaymS(100);
10 |
11 | EA = 0;/* Disable all interrupts */
12 |
13 | #ifdef __SDCC
14 | __asm
15 | LJMP BOOT_ADDR /* Jump to bootloader */
16 | __endasm;
17 | #endif
18 |
19 | #ifdef __C51__
20 | #pragma asm
21 | LJMP BOOT_ADDR /* Jump to bootloader */
22 | #pragma endasm
23 | #endif
24 |
25 | while(1);
26 | }
27 |
--------------------------------------------------------------------------------
/bootloader.h:
--------------------------------------------------------------------------------
1 | #ifndef __BOOTLOADER_H
2 | #define __BOOTLOADER_H
3 |
4 | #define BOOT_ADDR 0x3800
5 |
6 | void JumpToBootloader(void);
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/ch554_conf.c:
--------------------------------------------------------------------------------
1 | #include "Delay.H"
2 | #include "ch554_platform.h"
3 |
4 | #include "usb_desc.h"
5 | #include "usb_endp.h"
6 | #include "i2c.h"
7 | #include "spi.h"
8 |
9 |
10 | void ConfigSysClock() {
11 | //SAFE_MOD = 0x55;
12 | //SAFE_MOD = 0xAA;
13 | //CLOCK_CFG |= bOSC_EN_XT; // Enable External Crystal
14 | //CLOCK_CFG &= ~bOSC_EN_INT; // Disable External Crystal
15 |
16 | // Enters `safe mode` for next 13 to 23 CPU clock cycles
17 | SAFE_MOD = 0x55;
18 | SAFE_MOD = 0xAA;
19 |
20 | #if defined CLOCK_FREQ_32
21 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz
22 | #elif defined CLOCK_FREQ_24
23 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz
24 | #elif defined CLOCK_FREQ_16
25 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz
26 | #elif defined CLOCK_FREQ_12
27 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz
28 | #elif defined CLOCK_FREQ_6
29 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz
30 | #elif defined CLOCK_FREQ_3
31 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz
32 | #elif defined CLOCK_FREQ_P750
33 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz
34 | #elif defined CLOCK_FREQ_P1875
35 | CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5KHz
36 | #else
37 | #error "Clock frequency is not configured!"
38 | #endif
39 |
40 | SAFE_MOD = 0x00;
41 | }
42 |
43 | void USBDevice_Init() {
44 | IE_USB = 0; // Disable USB interrupt (for setup)
45 | USB_CTRL = 0x00; // Device mode, Full speed(12Mbps), Disable pull up(Invisible to host), Reset stuff
46 | //UDEV_CTRL = bUD_PD_DIS; //Disable DP/DN pull down resistor
47 |
48 | //Configure Endpoint 0
49 | UEP0_DMA_L = (uint8_t) Ep0Buffer; // Address of Endpoint 0 buffer
50 | // bUEP4_RX_EN and bUEP4_TX_EN controls both Endpoint 0 and 4, refer to table 16.3.2
51 | UEP4_1_MOD &= ~(bUEP4_RX_EN | bUEP4_TX_EN); // EP0 64-byte buffer
52 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; // SETUP/OUT -> ACK, IN -> NAK
53 |
54 | //Configure Endpoint 1
55 | UEP1_DMA_L = (uint8_t) Ep1Buffer; // Address of Endpoint 1 buffer
56 | //UEP4_1_MOD = UEP4_1_MOD & ~bUEP1_BUF_MOD | bUEP1_TX_EN;
57 | UEP4_1_MOD &=~bUEP1_BUF_MOD; //See table 16.3.3
58 | UEP4_1_MOD |= bUEP1_TX_EN; // EP1 Tx only, 64 bytes of buffer
59 | // Enable DATA0/DATA1 toggling, Reply NAK for IN transactions
60 | UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK;
61 |
62 | //Configure Endpoint 2
63 | UEP2_DMA_L = (uint8_t) Ep2Buffer; // Address of Endpoint 2 buffer
64 | //UEP2_3_MOD = UEP2_3_MOD & ~bUEP2_BUF_MOD | bUEP2_TX_EN;
65 | UEP2_3_MOD &=~bUEP2_BUF_MOD; // Disable Endpoint2 buffer mode
66 | UEP2_3_MOD |= bUEP2_TX_EN; // Enable Endpoint2 Tx
67 | UEP2_3_MOD |= bUEP2_RX_EN; // Enable Endpoint2 Rx
68 | // Enable DATA0/DATA1 toggling, Reply NAK for IN transactions, ACK for OUT transactions
69 | UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
70 |
71 | // Setup interrupts
72 | USB_INT_FG = 0xFF; // Clear interrupt flags
73 | // Generate a interrupt when USB bus suspend | transfer complete | bus reset
74 | USB_INT_EN = bUIE_SUSPEND | bUIE_TRANSFER | bUIE_BUS_RST;
75 | IE_USB = 1; //Enable USB interrupt
76 |
77 |
78 | // Get ready for enumeration
79 | USB_DEV_AD = 0x00; //Set USB address to 0, get ready for enumeration
80 | // Connect pull up resistor | While handling interrup, reply NAK t if flag is set | Enable DMA
81 | USB_CTRL = bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN;
82 | UDEV_CTRL |= bUD_PORT_EN; // Enable USB Port
83 |
84 | // Reset all tx length to 0
85 | UEP1_T_LEN = 0;
86 | UEP2_T_LEN = 0;
87 | }
88 |
89 | void UART0_Init(void) {
90 | uint32_t x;
91 | uint8_t x2;
92 |
93 | SM0 = 0;
94 | SM1 = 1;
95 | SM2 = 0; // UART0 Mode 0
96 |
97 | // Use Timer1 as the baud rate generator
98 | RCLK = 0;
99 | TCLK = 0;
100 | PCON |= SMOD;
101 | x = 10 * FREQ_SYS / UART0_BUAD / 16;
102 | x2 = x % 10;
103 | x /= 10;
104 | if ( x2 >= 5 ) x ++; // Round
105 |
106 | TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; // Timer1: 8-bit auto reload
107 | T2MOD = T2MOD | bTMR_CLK | bT1_CLK; // Select input clock for Timer1
108 | TH1 = 0-x;
109 | TR1 = 1; // Start Timer1
110 | TI = 1;
111 | REN = 1; // Enable UART1
112 | }
113 |
114 | void CH554_Init(void) {
115 | ConfigSysClock();
116 | mDelaymS(5); // Wait until the internal crystal becomes stable
117 |
118 | //UART0_Init();
119 | I2C_Init();
120 | SPI_SetMasterMode3();
121 | SPI_SetMasterIOFloat();
122 | SPI_SetClockDivider(4);
123 |
124 | USBDevice_Init();
125 |
126 | EA = 1;
127 | }
128 |
129 | //void putchar(char c) {
130 | // while (!TI) /* assumes UART is initialized */
131 | // ;
132 | // TI = 0;
133 | // SBUF = c;
134 | //}
135 | //
136 | //char getchar() {
137 | // while(!RI); /* assumes UART is initialized */
138 | // RI = 0;
139 | // return SBUF;
140 | //}
141 |
142 | //void putchar(char data);
143 | //char getchar();
144 |
--------------------------------------------------------------------------------
/ch554_conf.h:
--------------------------------------------------------------------------------
1 | #ifndef __CH554_CONF_H__
2 | #define __CH554_CONF_H__
3 |
4 | #define UART0_BUAD 57600
5 |
6 | //#define CLOCK_FREQ_32
7 | //#define CLOCK_FREQ_24
8 | //#define CLOCK_FREQ_16
9 | //#define CLOCK_FREQ_12
10 | //#define CLOCK_FREQ_6
11 | //#define CLOCK_FREQ_3
12 | //#define CLOCK_FREQ_P750
13 | //#define CLOCK_FREQ_P1875
14 |
15 | #ifdef CLOCK_FREQ_32
16 | #define FREQ_SYS 32000000
17 | #endif
18 | #ifdef CLOCK_FREQ_24
19 | #define FREQ_SYS 24000000
20 | #endif
21 | #ifdef CLOCK_FREQ_16
22 | #define FREQ_SYS 16000000
23 | #endif
24 | #ifdef CLOCK_FREQ_12
25 | #define FREQ_SYS 12000000
26 | #endif
27 | #ifdef CLOCK_FREQ_6
28 | #define FREQ_SYS 6000000
29 | #endif
30 | #ifdef CLOCK_FREQ_3
31 | #define FREQ_SYS 3000000
32 | #endif
33 | #ifdef CLOCK_FREQ_P750
34 | #define FREQ_SYS 750000
35 | #endif
36 | #ifdef CLOCK_FREQ_P1875
37 | #define FREQ_SYS 187500
38 | #endif
39 |
40 |
41 | void CH554_Init(void);
42 |
43 | // Interrupt Handlers
44 | void USBInterrupt(void);
45 |
46 | #endif
47 |
--------------------------------------------------------------------------------
/ch554_platform.h:
--------------------------------------------------------------------------------
1 | #ifndef __PLATFORM
2 | #define __PLATFORM
3 |
4 | #if defined (SDCC) || defined (__SDCC)
5 | #ifndef __SDCC
6 | #define __SDCC
7 | #endif
8 |
9 | // Use GCC defined standard types
10 | #include
11 | // SDCC is little-endian
12 | #define __LITTLE_ENDIAN
13 |
14 | // Define Keil C51 specified derivatives
15 | #define xdata __xdata
16 | #define idata __idata
17 | #define code __code
18 | #define interrupt __interrupt
19 |
20 | #define xdatabuf(addr, name, sz) __xdata __at(addr) uint8_t name[sz]
21 | #define extern_xdatabuf(addr, name) extern __xdata __at(addr) uint8_t name[]
22 | #elif defined (__C51__) || defined (__CX51__)
23 | #ifndef __C51__
24 | #define __C51__
25 | #endif
26 |
27 | // Define standard types
28 | #ifndef bool
29 | typedef bit bool;
30 | #endif
31 |
32 | #ifndef uint8_t
33 | typedef unsigned char uint8_t;
34 | #endif
35 |
36 | #ifndef int8_t
37 | typedef signed char int8_t;
38 | #endif
39 |
40 | #ifndef uint16_t
41 | typedef unsigned short uint16_t;
42 | #endif
43 |
44 | #ifndef int16_t
45 | typedef signed short int16_t;
46 | #endif
47 |
48 | #ifndef uint32_t
49 | typedef unsigned long uint32_t;
50 | #endif
51 |
52 | #ifndef int32_t
53 | typedef signed long int32_t;
54 | #endif
55 |
56 | // Keil C51 is big-endian
57 | #define __BIG_ENDIAN
58 |
59 | // SDCC style SBIT
60 | #define SBIT(var, port, pin) sbit var = port^pin
61 |
62 | #define xdatabuf(addr, name, sz) xdata uint8_t name[sz] _at_ addr
63 | #define extern_xdatabuf(addr, name) extern xdata uint8_t name[]
64 | #else
65 | #error "Unsupported compiler!"
66 | #endif
67 |
68 | #if defined __BIG_ENDIAN
69 | // uint16_t
70 | #define U16B0(u) (((uint8_t*)&u)[1])
71 | #define U16B1(u) (((uint8_t*)&u)[0])
72 | // uint32_t
73 | #define U32B0(u) (((uint8_t*)&u)[3])
74 | #define U32B1(u) (((uint8_t*)&u)[2])
75 | #define U32B2(u) (((uint8_t*)&u)[1])
76 | #define U32B3(u) (((uint8_t*)&u)[0])
77 |
78 | #define U16_XBig(dstAddr, srcAddr) { \
79 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \
80 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \
81 | }
82 |
83 | #define U16_XLittle(dstAddr, srcAddr) { \
84 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[1]; \
85 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[0]; \
86 | }
87 |
88 | #define U32_XBig(dstAddr, srcAddr) { \
89 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \
90 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \
91 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[2]; \
92 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[3]; \
93 | }
94 |
95 | #define U32_XLittle(dstAddr, srcAddr) { \
96 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[3]; \
97 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[2]; \
98 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[1]; \
99 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[0]; \
100 | }
101 | #elif defined __LITTLE_ENDIAN
102 | // uint16_t
103 | #define U16B0(u) (((uint8_t*)&u)[0])
104 | #define U16B1(u) (((uint8_t*)&u)[1])
105 | // uint32_t
106 | #define U32B0(u) (((uint8_t*)&u)[0])
107 | #define U32B1(u) (((uint8_t*)&u)[1])
108 | #define U32B2(u) (((uint8_t*)&u)[2])
109 | #define U32B3(u) (((uint8_t*)&u)[3])
110 |
111 | #define U16_XBig(dstAddr, srcAddr) { \
112 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[1]; \
113 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[0]; \
114 | }
115 |
116 | #define U16_XLittle(dstAddr, srcAddr) { \
117 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \
118 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \
119 | }
120 |
121 | #define U32_XBig(dstAddr, srcAddr) { \
122 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[3]; \
123 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[2]; \
124 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[1]; \
125 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[0]; \
126 | }
127 |
128 | #define U32_XLittle(dstAddr, srcAddr) { \
129 | ((uint8_t*)dstAddr)[0] = ((uint8_t*)srcAddr)[0]; \
130 | ((uint8_t*)dstAddr)[1] = ((uint8_t*)srcAddr)[1]; \
131 | ((uint8_t*)dstAddr)[2] = ((uint8_t*)srcAddr)[2]; \
132 | ((uint8_t*)dstAddr)[3] = ((uint8_t*)srcAddr)[3]; \
133 | }
134 | #else
135 | #error "Little-Endian or Big-Endian?"
136 | #endif
137 |
138 |
139 | #endif // __PLATFORM
140 |
141 |
142 |
143 | #define GPIO1 0x90
144 | #define GPIO2 0xA0
145 | #define GPIO3 0xB0
146 |
147 |
148 |
149 | #include "ch554_conf.H"
150 |
151 | #ifdef __SDCC
152 | #include "include\ch554.h"
153 | #include "include\ch554_usb.h"
154 | #endif
155 |
156 | #ifdef __C51__
157 | #include "keilc51\ch554.h"
158 | #endif
159 |
--------------------------------------------------------------------------------
/delay.c:
--------------------------------------------------------------------------------
1 | #include "Delay.H"
2 | #include "ch554_platform.h"
3 |
4 | void mDelayuS(uint16_t n ) {
5 | #ifdef CLOCK_CFG
6 | #if CLOCK_CFG <= 6000000
7 | n >>= 2;
8 | #endif
9 | #if CLOCK_CFG <= 3000000
10 | n >>= 2;
11 | #endif
12 | #if CLOCK_CFG <= 750000
13 | n >>= 4;
14 | #endif
15 | #endif
16 | while ( n ) {
17 | ++ SAFE_MOD;
18 | #ifdef CLOCK_CFG
19 | #if CLOCK_CFG >= 14000000
20 | ++ SAFE_MOD;
21 | #endif
22 | #if CLOCK_CFG >= 16000000
23 | ++ SAFE_MOD;
24 | #endif
25 | #if CLOCK_CFG >= 18000000
26 | ++ SAFE_MOD;
27 | #endif
28 | #if CLOCK_CFG >= 20000000
29 | ++ SAFE_MOD;
30 | #endif
31 | #if CLOCK_CFG >= 22000000
32 | ++ SAFE_MOD;
33 | #endif
34 | #if CLOCK_CFG >= 24000000
35 | ++ SAFE_MOD;
36 | #endif
37 | #if CLOCK_CFG >= 26000000
38 | ++ SAFE_MOD;
39 | #endif
40 | #if CLOCK_CFG >= 28000000
41 | ++ SAFE_MOD;
42 | #endif
43 | #if CLOCK_CFG >= 30000000
44 | ++ SAFE_MOD;
45 | #endif
46 | #if CLOCK_CFG >= 32000000
47 | ++ SAFE_MOD;
48 | #endif
49 | #endif
50 | -- n;
51 | }
52 | }
53 |
54 | void mDelaymS(uint16_t n ) {
55 | while ( n ) {
56 | #ifdef DELAY_MS_HW
57 | while ( ( TKEY_CTRL & bTKC_IF ) == 0 );
58 | while ( TKEY_CTRL & bTKC_IF );
59 | #else
60 | mDelayuS(1000);
61 | #endif
62 | -- n;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/delay.h:
--------------------------------------------------------------------------------
1 | #ifndef __DELAY_H__
2 | #define __DELAY_H__
3 |
4 | #include "ch554_platform.h"
5 |
6 | void mDelayuS(uint16_t n );
7 | void mDelaymS(uint16_t n );
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/host/.gitignore:
--------------------------------------------------------------------------------
1 | #Visual Studio files
2 | *.[Oo]bj
3 | *.user
4 | *.aps
5 | *.pch
6 | *.vspscc
7 | *.vssscc
8 | *_i.c
9 | *_p.c
10 | *.ncb
11 | *.suo
12 | *.tlb
13 | *.tlh
14 | *.bak
15 | *.[Cc]ache
16 | *.ilk
17 | *.log
18 | *.sbr
19 | *.sdf
20 | *.opensdf
21 | *.unsuccessfulbuild
22 | ipch/
23 | obj/
24 | [Ll]ib
25 | [Bb]in
26 | [Dd]ebug*/
27 | [Rr]elease*/
28 | Ankh.NoLoad
29 | *.VC.db
30 |
31 | #GCC files
32 | *.o
33 | *.d
34 | *.res
35 | *.dll
36 | *.a
37 |
38 | #Visual Studio Code files
39 | .vscode/
--------------------------------------------------------------------------------
/host/CH554_CDC_BusBridge.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26430.6
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CH554_CDC_BusBridge", "CH554_CDC_BusBridge.vcxproj", "{600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x64.ActiveCfg = Debug|x64
17 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x64.Build.0 = Debug|x64
18 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x86.ActiveCfg = Debug|Win32
19 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Debug|x86.Build.0 = Debug|Win32
20 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x64.ActiveCfg = Release|x64
21 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x64.Build.0 = Release|x64
22 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x86.ActiveCfg = Release|Win32
23 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/host/CH554_CDC_BusBridge.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 15.0
23 | {600C7BD9-6E76-4D4A-AD7D-2CD9C0F2DF0D}
24 | Win32Proj
25 | CH554_CDC_BusBridge
26 | 7.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v141_xp
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v141_xp
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v141_xp
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v141_xp
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 | $(SolutionDir)$(Platform)\$(Configuration)\
76 | $(Platform)\$(Configuration)\
77 |
78 |
79 | true
80 |
81 |
82 | false
83 | $(SolutionDir)$(Platform)\$(Configuration)\
84 | $(Platform)\$(Configuration)\
85 |
86 |
87 | false
88 |
89 |
90 |
91 |
92 |
93 | Level3
94 | Disabled
95 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
96 |
97 |
98 | Console
99 |
100 |
101 |
102 |
103 |
104 |
105 | Level3
106 | Disabled
107 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
108 |
109 |
110 | Console
111 |
112 |
113 |
114 |
115 | Level3
116 |
117 |
118 | MaxSpeed
119 | true
120 | true
121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
122 |
123 |
124 | Console
125 | true
126 | true
127 |
128 |
129 |
130 |
131 | Level3
132 |
133 |
134 | MaxSpeed
135 | true
136 | true
137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
138 |
139 |
140 | Console
141 | true
142 | true
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
--------------------------------------------------------------------------------
/host/CH554_CDC_BusBridge.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 | Source Files
29 |
30 |
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 |
--------------------------------------------------------------------------------
/host/Makefile:
--------------------------------------------------------------------------------
1 | test: main.o spi.o rs232.o flash25.o
2 | cc -o main main.o rs232.o spi.o flash25.o
3 |
4 | main.o: main.c
5 | cc $(CFLAGS) -c main.c -o main.o
6 | flash25.o: flash25.c flash25.h
7 | cc $(CFLAGS) -c flash25.c -o flash25.o
8 | spi.o: spi.c spi.h
9 | cc $(CFLAGS) -c spi.c -o spi.o
10 | rs232.o: rs232.c rs232.h
11 | cc $(CFLAGS) -c rs232.c -o rs232.o
12 |
13 | clean:
14 | rm *.o main
15 |
--------------------------------------------------------------------------------
/host/flash25.c:
--------------------------------------------------------------------------------
1 | #include "flash25.h"
2 | #include "spi.h"
3 | #include "rs232.h"
4 |
5 | #include
6 |
7 | uint32_t SPI_Flash25_ReadID(HCOM hCom) {
8 | uint8_t cmd = FLASH25_CMD_RDID;
9 | uint8_t id[3] = { 0 };
10 | SPI_Write(hCom, &cmd, 1, SPI_NO_STOP);
11 | SPI_Read(hCom, &id, 3, SPI_STOP_AFTER);
12 |
13 | return (id[2] << 16) | (id[1] << 8) | id[0];
14 | }
15 |
16 | void SPI_Flash25_WriteEnable(HCOM hCom) {
17 | unsigned char cmd = FLASH25_CMD_WREN;
18 | SPI_Write(hCom, &cmd, 1, SPI_STOP_AFTER);
19 | }
20 |
21 | void SPI_Flash25_WaitForWriteEnd(HCOM hCom) {
22 | uint8_t temp = FLASH25_CMD_RDSR;
23 | SPI_Write(hCom, &temp, 1, SPI_NO_STOP);
24 |
25 | /* Loop as long as the memory is busy with a write cycle */
26 | do {
27 | /* Send a dummy byte to generate the clock needed by the FLASH
28 | and put the value of the status register in FLASH_Status variable */
29 | SPI_Read(hCom, &temp, 1, SPI_NO_STOP);
30 |
31 | } while (temp & FLASH25_FLAG_WIP);
32 |
33 | // Set CS to high
34 | SPI_CS(hCom, 1);
35 | }
36 |
37 | static void SPI_Flash25_PageWrite(HCOM hCom, uint8_t* buf, uint32_t addr, uint32_t count) {
38 | /* Enable the write access to the FLASH */
39 | SPI_Flash25_WriteEnable(hCom);
40 |
41 | unsigned char header[4] = { 0 };
42 | header[0] = FLASH25_CMD_WRITE;
43 | header[1] = (addr & 0xFF0000) >> 16;
44 | header[2] = (addr & 0xFF00) >> 8;
45 | header[3] = addr & 0xFF;
46 |
47 | SPI_Write(hCom, header, 4, SPI_NO_STOP);
48 | SPI_Write(hCom, buf, count, SPI_STOP_AFTER);
49 |
50 | /* Wait the end of Flash writing */
51 | SPI_Flash25_WaitForWriteEnd(hCom);
52 | }
53 |
54 | void SPI_Flash25_BufferWrite(HCOM hCom, uint8_t* buf, uint32_t addr, uint32_t page_size, uint32_t count) {
55 | uint32_t page_count = 0, byte_remaining = 0, offset = 0, byte_to_boundary = 0;
56 |
57 | offset = addr % page_size;
58 | byte_to_boundary = page_size - offset;
59 | page_count = count / page_size;
60 | byte_remaining = count % page_size;
61 |
62 | if (offset == 0) { /* addr is page_size aligned */
63 | if (page_count == 0) { /* byte_to_boundary < page_size */
64 | SPI_Flash25_PageWrite(hCom, buf, addr, count);
65 | } else { /* byte_to_boundary > page_size */
66 | while (page_count--) {
67 | SPI_Flash25_PageWrite(hCom, buf, addr, page_size);
68 | addr += page_size;
69 | buf += page_size;
70 | }
71 |
72 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_remaining);
73 | }
74 | } else { /* addr is not page_size aligned */
75 | if (page_count == 0) { /* byte_to_boundary < page_size */
76 | if (byte_remaining > byte_to_boundary) { /* (byte_to_boundary + addr) > page_size */
77 | byte_remaining -= byte_to_boundary;
78 |
79 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_to_boundary);
80 | addr += byte_to_boundary;
81 | buf += byte_to_boundary;
82 |
83 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_remaining);
84 | } else {
85 | SPI_Flash25_PageWrite(hCom, buf, addr, count);
86 | }
87 | } else { /* more than 1 page */
88 | count -= byte_to_boundary;
89 | page_count = count / page_size;
90 | byte_remaining = count % page_size;
91 |
92 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_to_boundary);
93 | addr += byte_to_boundary;
94 | buf += byte_to_boundary;
95 |
96 | while (page_count--) {
97 | SPI_Flash25_PageWrite(hCom, buf, addr, page_size);
98 | addr += page_size;
99 | buf += page_size;
100 | }
101 |
102 | if (byte_remaining != 0) {
103 | SPI_Flash25_PageWrite(hCom, buf, addr, byte_remaining);
104 | }
105 | }
106 | }
107 | }
108 |
109 | void SPI_Flash25_BufferRead(HCOM hCom, uint8_t* pBuffer, uint32_t ReadAddr, uint32_t NumByteToRead) {
110 | uint8_t header[4];
111 | header[0] = FLASH25_CMD_READ;
112 | header[1] = (ReadAddr & 0xFF0000) >> 16;
113 | header[2] = (ReadAddr & 0xFF00) >> 8;
114 | header[3] = ReadAddr & 0xFF;
115 |
116 | SPI_Write(hCom, header, 4, SPI_NO_STOP);
117 | SPI_Read(hCom, pBuffer, NumByteToRead, SPI_STOP_AFTER);
118 | }
119 |
120 | void SPI_Flash25_SectorErase(HCOM hCom, uint32_t SectorAddr) {
121 | /* Send write enable instruction */
122 | SPI_Flash25_WriteEnable(hCom);
123 |
124 | uint8_t header[4];
125 | header[0] = FLASH25_CMD_SE;
126 | header[1] = (SectorAddr & 0xFF0000) >> 16;
127 | header[2] = (SectorAddr & 0xFF00) >> 8;
128 | header[3] = SectorAddr & 0xFF;
129 |
130 | SPI_Write(hCom, header, 4, SPI_STOP_AFTER);
131 |
132 | /* Wait the end of Flash writing */
133 | SPI_Flash25_WaitForWriteEnd(hCom);
134 | }
135 |
136 | void SPI_Flash25_BulkErase(HCOM hCom) {
137 | /* Send write enable instruction */
138 | SPI_Flash25_WriteEnable(hCom);
139 |
140 | unsigned char cmd = FLASH25_CMD_BE;
141 | SPI_Write(hCom, &cmd, 1, SPI_STOP_AFTER);
142 |
143 | /* Wait the end of Flash writing */
144 | SPI_Flash25_WaitForWriteEnd(hCom);
145 | }
--------------------------------------------------------------------------------
/host/flash25.h:
--------------------------------------------------------------------------------
1 | #ifndef __FLASH25_H
2 | #define __FLASH25_H
3 |
4 | #include "rs232.h"
5 | #include
6 |
7 | #define FLASH25_CMD_WRITE 0x02 /* Write to Memory instruction */
8 | #define FLASH25_CMD_WRSR 0x01 /* Write Status Register instruction */
9 | #define FLASH25_CMD_WREN 0x06 /* Write enable instruction */
10 |
11 | #define FLASH25_CMD_READ 0x03 /* Read from Memory instruction */
12 | #define FLASH25_CMD_RDSR 0x05 /* Read Status Register instruction */
13 | #define FLASH25_CMD_RDID 0x9F /* Read identification */
14 | #define FLASH25_CMD_SE 0xD8 /* Sector Erase instruction */
15 | #define FLASH25_CMD_BE 0xC7 /* Bulk Erase instruction */
16 |
17 | #define FLASH25_FLAG_WIP 0x01 /* Write In Progress (WIP) flag */
18 |
19 | uint32_t SPI_Flash25_ReadID(HCOM hCom);
20 | void SPI_Flash25_WriteEnable(HCOM hCom);
21 | void SPI_Flash25_WaitForWriteEnd(HCOM hCom);
22 | void SPI_Flash25_BufferWrite(HCOM hCom, uint8_t* pBuffer, uint32_t WriteAddr, uint32_t page_size, uint32_t NumByteToWrite);
23 | void SPI_Flash25_BufferRead(HCOM hCom, uint8_t* pBuffer, uint32_t ReadAddr, uint32_t NumByteToRead);
24 | void SPI_Flash25_SectorErase(HCOM hCom, uint32_t SectorAddr);
25 | void SPI_Flash25_BulkErase(HCOM hCom);
26 |
27 | #endif // !__FLASH25_H
28 |
--------------------------------------------------------------------------------
/host/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "rs232.h"
4 | #include "spi.h"
5 | #include "flash25.h"
6 |
7 | int main(int argc, const char** argv) {
8 | #ifndef _WIN32
9 | printf("WARNING: Linux users should disable modemmanager to make this program work properly!\n E.g. sudo apt-get purge modemmanager\n");
10 | #endif
11 |
12 | if (argc < 2) {
13 | printf("RS232 port is not specified, on Linux, normally it should be /dev/ttyACM0, on Windows it should be something like COM8. \n");
14 | return EXIT_FAILURE;
15 | }
16 |
17 | const char* portName = argv[1];
18 | HCOM hCom = RS232_Open(portName);
19 | //Set the buffer size
20 | if (RS232_IS_INVALID(hCom)) {
21 | printf("Unable to open port %s \n", portName);
22 | return EXIT_FAILURE;
23 | }
24 | RS232_Config(hCom, 115200, RS232_CONFIG_DEFAULT);
25 |
26 | // Pull up CS to terminate any pending SPI operation
27 | SPI_CS(hCom, 1);
28 | printf("Chip ID = %x\n", SPI_Flash25_ReadID(hCom));
29 | unsigned char* src = (unsigned char*)malloc(0x200000);
30 | FILE *file = fopen("rikka.png", "rb");
31 | fseek(file, 0L, SEEK_END);
32 | long src_len = ftell(file);
33 | rewind(file);
34 | fread(src, src_len, 1, file);
35 | fclose(file);
36 |
37 | printf("File size = %ld\n", src_len);
38 | SPI_Flash25_BulkErase(hCom);
39 | printf("Chip Erased\n");
40 | SPI_Flash25_BufferWrite(hCom, src, 0, 256, src_len);
41 | printf("Writing done!\n");
42 |
43 | unsigned char* dst = (unsigned char*)malloc(0x200000);
44 | SPI_Flash25_BufferRead(hCom, dst, 0, src_len);
45 | printf("Reading done!\n");
46 |
47 | for (int i = 0; i < src_len; i++) {
48 | if (src[i] != dst[i]) {
49 | printf("diff %d\n", i);
50 | }
51 | }
52 |
53 | RS232_Close(hCom);
54 |
55 | system("pause");
56 | return 0;
57 | }
--------------------------------------------------------------------------------
/host/rikka.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/host/rikka.png
--------------------------------------------------------------------------------
/host/rs232.c:
--------------------------------------------------------------------------------
1 | #include "rs232.h"
2 |
3 | ssize_t RS232_ReadLine(HCOM hCom, char *buffer, size_t count) {
4 | size_t received = 0;
5 | ssize_t n = 0;
6 | char sbuf;
7 |
8 | do {
9 | n = RS232_Read(hCom, &sbuf, 1);
10 |
11 | if (n == -1)
12 | return -1;
13 |
14 | buffer[received] = sbuf;
15 | received += n;
16 | } while (sbuf != '\n' && (received + 2) < count);
17 |
18 | if (buffer[received - 2] == '\r')
19 | received--;
20 | buffer[received] = '\0';
21 | return received;
22 | }
23 |
24 | #ifdef _WIN32
25 | HCOM RS232_Open(const unsigned char* name) {
26 | HCOM hCom = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
27 |
28 | return hCom;
29 | }
30 |
31 | void RS232_Config(HCOM hCom, speed_t baud, unsigned char config) {
32 | DCB dcb = { 0 };
33 | GetCommState(hCom, &dcb);
34 |
35 | dcb.BaudRate = baud;
36 |
37 | switch (config & RS232_CONFIG_CS_MASK) {
38 | case RS232_CONFIG_CS5:
39 | dcb.ByteSize = 5;
40 | break;
41 | case RS232_CONFIG_CS6:
42 | dcb.ByteSize = 6;
43 | break;
44 | case RS232_CONFIG_CS7:
45 | dcb.ByteSize = 7;
46 | break;
47 | case RS232_CONFIG_CS8:
48 | default:
49 | dcb.ByteSize = 8;
50 | break;
51 | }
52 |
53 | switch (config & RS232_CONFIG_PARITY_MASK) {
54 | case RS232_CONFIG_PARITY_EVEN:
55 | dcb.ByteSize = EVENPARITY;
56 | break;
57 | case RS232_CONFIG_PARITY_ODD:
58 | dcb.Parity = ODDPARITY;
59 | break;
60 | case RS232_CONFIG_PARITY_NO:
61 | default:
62 | dcb.Parity = NOPARITY;
63 | break;
64 | }
65 |
66 | dcb.StopBits = (config & RS232_CONFIG_STOPBIT_2) ? TWOSTOPBITS : ONESTOPBIT;
67 | dcb.fOutxCtsFlow = 0;
68 | dcb.fOutxDsrFlow = 0;
69 | dcb.fDsrSensitivity = 0;
70 | dcb.fDtrControl = DTR_CONTROL_DISABLE;
71 | dcb.fRtsControl = RTS_CONTROL_DISABLE;
72 |
73 | SetCommState(hCom, &dcb);
74 | }
75 |
76 | ssize_t RS232_Write(HCOM hCom, const void* buf, size_t count) {
77 | DWORD written = 0;
78 | if (WriteFile(hCom, buf, count, &written, NULL) == FALSE) {
79 | return -1; // Error
80 | } else {
81 | return written;
82 | }
83 | }
84 |
85 | ssize_t RS232_Read(HCOM hCom, void *buf, size_t count) {
86 | DWORD read = 0;
87 | if (ReadFile(hCom, buf, count, &read, NULL) == FALSE) {
88 | return -1; // Error
89 | } else {
90 | return read;
91 | }
92 | }
93 |
94 | void RS232_RTS_Set(HCOM hCom) {
95 | EscapeCommFunction(hCom, SETRTS);
96 | }
97 |
98 | void RS232_RTS_Clr(HCOM hCom) {
99 | EscapeCommFunction(hCom, CLRRTS);
100 | }
101 |
102 | void RS232_DTR_Set(HCOM hCom) {
103 | EscapeCommFunction(hCom, SETDTR);
104 | }
105 |
106 | void RS232_DTR_Clr(HCOM hCom) {
107 | EscapeCommFunction(hCom, CLRDTR);
108 | }
109 |
110 | void RS232_Close(HCOM hCom) {
111 | CloseHandle(hCom);
112 | }
113 |
114 | int RS232_CTS(HCOM hCom) {
115 | DWORD flags;
116 | GetCommModemStatus(hCom, &flags);
117 | return (flags & MS_CTS_ON) ? 1 : 0;
118 | }
119 |
120 | int RS232_DSR(HCOM hCom) {
121 | DWORD flags;
122 | GetCommModemStatus(hCom, &flags);
123 | return (flags & MS_DSR_ON) ? 1 : 0;
124 | }
125 | #else
126 | HCOM RS232_Open(const unsigned char* name) {
127 | return open(name, O_RDWR | O_NOCTTY);
128 | }
129 |
130 | void RS232_Config(HCOM fd, speed_t baud, unsigned char config) {
131 | struct termios options;
132 | int baudr;
133 | tcgetattr(fd, &options);
134 |
135 | switch (baud) {
136 | case 50:
137 | baudr = B50;
138 | break;
139 | case 75:
140 | baudr = B75;
141 | break;
142 | case 110:
143 | baudr = B110;
144 | break;
145 | case 134:
146 | baudr = B134;
147 | break;
148 | case 150:
149 | baudr = B150;
150 | break;
151 | case 200:
152 | baudr = B200;
153 | break;
154 | case 300:
155 | baudr = B300;
156 | break;
157 | case 600:
158 | baudr = B600;
159 | break;
160 | case 1200:
161 | baudr = B1200;
162 | break;
163 | case 1800:
164 | baudr = B1800;
165 | break;
166 | case 2400:
167 | baudr = B2400;
168 | break;
169 | case 4800:
170 | baudr = B4800;
171 | break;
172 | case 9600:
173 | baudr = B9600;
174 | break;
175 | case 19200:
176 | baudr = B19200;
177 | break;
178 | case 38400:
179 | baudr = B38400;
180 | break;
181 | case 57600:
182 | baudr = B57600;
183 | break;
184 | case 115200:
185 | baudr = B115200;
186 | break;
187 | case 230400:
188 | baudr = B230400;
189 | break;
190 | case 460800:
191 | baudr = B460800;
192 | break;
193 | case 500000:
194 | baudr = B500000;
195 | break;
196 | case 576000:
197 | baudr = B576000;
198 | break;
199 | case 921600:
200 | baudr = B921600;
201 | break;
202 | case 1000000:
203 | baudr = B1000000;
204 | break;
205 | case 1152000:
206 | baudr = B1152000;
207 | break;
208 | case 1500000:
209 | baudr = B1500000;
210 | break;
211 | case 2000000:
212 | baudr = B2000000;
213 | break;
214 | case 2500000:
215 | baudr = B2500000;
216 | break;
217 | case 3000000:
218 | baudr = B3000000;
219 | break;
220 | case 3500000:
221 | baudr = B3500000;
222 | break;
223 | case 4000000:
224 | baudr = B4000000;
225 | break;
226 | default:
227 | baudr = B1152000;
228 | break;
229 | }
230 | cfsetispeed(&options, baudr);
231 | cfsetospeed(&options, baudr);
232 |
233 | options.c_cflag &= ~CSIZE;
234 | switch (config & RS232_CONFIG_CS_MASK) {
235 | case RS232_CONFIG_CS5:
236 | options.c_cflag |= CS5;
237 | break;
238 | case RS232_CONFIG_CS6:
239 | options.c_cflag |= CS6;
240 | break;
241 | case RS232_CONFIG_CS7:
242 | options.c_cflag |= CS7;
243 | break;
244 | case RS232_CONFIG_CS8:
245 | default:
246 | options.c_cflag |= CS8;
247 | break;
248 | }
249 |
250 | switch (config & RS232_CONFIG_PARITY_MASK) {
251 | case RS232_CONFIG_PARITY_EVEN:
252 | options.c_cflag |= PARENB;
253 | options.c_cflag &= ~PARODD;
254 | break;
255 | case RS232_CONFIG_PARITY_ODD:
256 | options.c_cflag |= PARENB;
257 | options.c_cflag |= PARODD;
258 | break;
259 | case RS232_CONFIG_PARITY_NO:
260 | default:
261 | options.c_cflag &= ~PARENB;
262 | break;
263 | }
264 |
265 | if (config & RS232_CONFIG_STOPBIT_2) {
266 | options.c_cflag |= CSTOPB;
267 | } else {
268 | options.c_cflag &= ~CSTOPB;
269 | }
270 |
271 | options.c_cflag &= ~CRTSCTS;
272 | options.c_cflag |= CREAD | CLOCAL;
273 |
274 | // Put the serial port in raw mode, similar to cfmakeraw
275 | options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
276 | options.c_oflag &= ~OPOST;
277 | options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
278 | tcsetattr(fd, TCSANOW, &options);
279 | }
280 |
281 | ssize_t RS232_Write(HCOM fd, const void* buf, size_t count) {
282 | return write(fd, buf, count);
283 | }
284 |
285 | ssize_t RS232_Read(HCOM fd, void *buf, size_t count) {
286 | return read(fd, buf, count);
287 | }
288 |
289 | void RS232_RTS_Set(HCOM fd) {
290 | int RTS_flag = TIOCM_RTS;
291 | ioctl(fd, TIOCMBIS, &RTS_flag);
292 | }
293 |
294 | void RS232_RTS_Clr(HCOM fd) {
295 | int RTS_flag = TIOCM_RTS;
296 | ioctl(fd, TIOCMBIC, &RTS_flag);
297 | }
298 |
299 | void RS232_DTR_Set(HCOM fd) {
300 | int DTR_flag = TIOCM_DTR;
301 | ioctl(fd, TIOCMBIS, &DTR_flag);
302 | }
303 |
304 | void RS232_DTR_Clr(HCOM fd) {
305 | int DTR_flag = TIOCM_DTR;
306 | ioctl(fd, TIOCMBIC, &DTR_flag);
307 | }
308 |
309 | int RS232_CTS(HCOM fd) {
310 | int flags;
311 | ioctl(fd, TIOCMGET, &flags);
312 | return (flags & TIOCM_CTS) ? 1 : 0;
313 | }
314 |
315 | int RS232_DSR(HCOM fd) {
316 | int flags;
317 | ioctl(fd, TIOCMGET, &flags);
318 | return (flags & TIOCM_DSR) ? 1 : 0;
319 | }
320 |
321 | void RS232_Close(HCOM hCom) {
322 | close(hCom);
323 | }
324 | #endif
325 |
326 |
327 |
--------------------------------------------------------------------------------
/host/rs232.h:
--------------------------------------------------------------------------------
1 | #ifndef __RS232_H
2 | #define __RS232_H
3 |
4 | #define RS232_CONFIG_STOPBIT_2 0x40
5 | #define RS232_CONFIG_STOPBIT_1 0x00
6 |
7 | #define RS232_CONFIG_PARITY_MASK 0x30
8 | #define RS232_CONFIG_PARITY_EVEN 0x20
9 | #define RS232_CONFIG_PARITY_ODD 0x10
10 | #define RS232_CONFIG_PARITY_NO 0x00
11 |
12 | #define RS232_CONFIG_CS_MASK 0x0F
13 | #define RS232_CONFIG_CS8 8
14 | #define RS232_CONFIG_CS7 7
15 | #define RS232_CONFIG_CS6 6
16 | #define RS232_CONFIG_CS5 5
17 |
18 | #define RS232_CONFIG_DEFAULT (RS232_CONFIG_CS8 | RS232_CONFIG_PARITY_NO | RS232_CONFIG_STOPBIT_1)
19 |
20 | #ifdef _WIN32
21 | #include
22 | typedef SSIZE_T ssize_t;
23 | typedef unsigned int speed_t;
24 | typedef void* HCOM;
25 | #define RS232_IS_INVALID(hCom) (hCom == INVALID_HANDLE_VALUE)
26 | #else
27 | #include /* File Control Definitions */
28 | #include /* POSIX Terminal Control Definitions */
29 | #include /* UNIX Standard Definitions */
30 | #include /* ERROR Number Definitions */
31 | #include /* ioctl() */
32 |
33 | typedef int HCOM;
34 | #define RS232_IS_INVALID(hCom) (hCom == -1)
35 | #endif
36 |
37 | // Valid bauds: 110, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400
38 | // 57600, 115200, 128000, 256000, 500000, 1000000
39 |
40 | HCOM RS232_Open(const unsigned char* name);
41 | void RS232_Config(HCOM hCom, speed_t baud, unsigned char config);
42 | ssize_t RS232_Write(HCOM hCom, const void* buf, size_t count);
43 | ssize_t RS232_Read(HCOM hCom, void *buf, size_t count);
44 | ssize_t RS232_ReadLine(HCOM hCom, char *buffer, size_t count);
45 | void RS232_RTS_Set(HCOM hCom);
46 | void RS232_RTS_Clr(HCOM hCom);
47 | void RS232_DTR_Set(HCOM hCom);
48 | void RS232_DTR_Clr(HCOM hCom);
49 | int RS232_CTS(HCOM hCom);
50 | int RS232_DSR(HCOM hCom);
51 | void RS232_Close(HCOM hCom);
52 |
53 | #endif // !__RS232_H
54 |
--------------------------------------------------------------------------------
/host/spi.c:
--------------------------------------------------------------------------------
1 | #include "spi.h"
2 | #include "rs232.h"
3 |
4 | #include
5 |
6 | #define SPI_SEGMENT_MAXLEN 32
7 | #define SPI_REPLY_MAXLEN 32
8 |
9 | int SPI_Write(HCOM hCom, const void* buf, size_t count, char flag) {
10 | char rx_buf[SPI_REPLY_MAXLEN];
11 | const char* tx_buf = (char*)buf;
12 | unsigned char header[2];
13 | header[0] = 'S';
14 | header[1] = SPI_SEGMENT_MAXLEN | SPI_NO_STOP;
15 |
16 | while (count > SPI_SEGMENT_MAXLEN) {
17 | if (RS232_Write(hCom, header, 2) == -1)
18 | goto err;
19 |
20 | if (RS232_Write(hCom, tx_buf, SPI_SEGMENT_MAXLEN) == -1)
21 | goto err;
22 |
23 | if (RS232_ReadLine(hCom, rx_buf, SPI_REPLY_MAXLEN) == -1)
24 | goto err;
25 |
26 | if (!strcmp(rx_buf, "OK"))
27 | goto err;
28 |
29 | tx_buf += SPI_SEGMENT_MAXLEN;
30 | count -= SPI_SEGMENT_MAXLEN;
31 | }
32 |
33 | if (count > 0) {
34 | if (flag & SPI_NO_STOP) {
35 | header[1] = count | SPI_NO_STOP;
36 | } else {
37 | header[1] = count;
38 | }
39 |
40 | if (RS232_Write(hCom, header, 2) == -1)
41 | goto err;
42 |
43 | if (RS232_Write(hCom, tx_buf, count) == -1)
44 | goto err;
45 |
46 | if (RS232_ReadLine(hCom, rx_buf, SPI_REPLY_MAXLEN) == -1)
47 | goto err;
48 |
49 | if (!strcmp(rx_buf, "OK"))
50 | goto err;
51 | }
52 |
53 | return 0;
54 | err:
55 | return -1;
56 | }
57 |
58 | int SPI_Read(HCOM hCom, void* buf, size_t count, char flag) {
59 | char* rx_buf = (char*)buf;
60 | unsigned char header[2];
61 | size_t read;
62 | header[0] = 'G';
63 | header[1] = SPI_SEGMENT_MAXLEN | SPI_NO_STOP;
64 |
65 | while (count > SPI_SEGMENT_MAXLEN) {
66 | if (RS232_Write(hCom, header, 2) == -1)
67 | goto err;
68 |
69 | read = 0;
70 | do {
71 | size_t rs232_read_ret = RS232_Read(hCom, rx_buf, SPI_SEGMENT_MAXLEN - read);
72 | if (rs232_read_ret == -1)
73 | goto err;
74 | read += rs232_read_ret;
75 | rx_buf += rs232_read_ret;
76 | } while (read < SPI_SEGMENT_MAXLEN);
77 |
78 | count -= SPI_SEGMENT_MAXLEN;
79 | }
80 |
81 | if (count > 0) {
82 | if (flag & SPI_NO_STOP) {
83 | header[1] = count | SPI_NO_STOP;
84 | } else {
85 | header[1] = count;
86 | }
87 |
88 | if (RS232_Write(hCom, header, 2) == -1)
89 | goto err;
90 |
91 | read = 0;
92 | do {
93 | size_t rs232_read_ret = RS232_Read(hCom, rx_buf, count);
94 | if (rs232_read_ret == -1)
95 | goto err;
96 | read += rs232_read_ret;
97 | rx_buf += rs232_read_ret;
98 | } while (read < count);
99 |
100 | return 0;
101 | }
102 |
103 | return 0;
104 | err:
105 | return -1;
106 | }
107 |
108 | int SPI_CS(HCOM hCom, unsigned char val) {
109 | unsigned char header[2];
110 | if (val) {
111 | header[0] = 'G';
112 | header[1] = 0;
113 | } else {
114 | header[0] = 'S';
115 | header[1] = 0;
116 | }
117 |
118 | return (RS232_Write(hCom, header, 2) == -1) ? -1 : 0;
119 | }
120 |
--------------------------------------------------------------------------------
/host/spi.h:
--------------------------------------------------------------------------------
1 | #ifndef __SPI_H
2 | #define __SPI_H
3 |
4 | #include "rs232.h"
5 |
6 | // SPI_Write and SPI_Read flags
7 | #define SPI_NO_STOP 0x80 /* After this transmission, CS remains low */
8 | #define SPI_STOP_AFTER 0x00 /* After this transmission, CS will be set to high */
9 |
10 | /* Write bytes from to SPI device */
11 | int SPI_Write(HCOM hCom, const void* buf, size_t count, char flag);
12 | /* Read bytes from SPI device to */
13 | int SPI_Read(HCOM hCom, void* buf, size_t count, char flag);
14 | /* Set the level of CS, normally you don't need this! */
15 | int SPI_CS(HCOM hCom, unsigned char val);
16 |
17 | #endif // !__SPI_H
18 |
--------------------------------------------------------------------------------
/i2c.c:
--------------------------------------------------------------------------------
1 | #include "i2c.h"
2 | #include "ch554_platform.h"
3 |
4 | xdata uint8_t I2C_Buf;
5 |
6 | SBIT(sda_pin, 0x90, 7);
7 | SBIT(scl_pin, 0x90, 6);
8 | //sbit sda_pin = P1^5;
9 | //sbit scl_pin = P1^4;
10 |
11 | #define I2C_SDA() (sda_pin==1)
12 | #define I2C_SDA_H() {sda_pin = 1;}
13 | #define I2C_SDA_L() {sda_pin = 0;}
14 | #define I2C_SCL_H() {scl_pin = 1;}
15 | #define I2C_SCL_L() {scl_pin = 0;}
16 |
17 | void I2C_DELAY(void) {
18 | uint8_t i;
19 | for (i=0; i<7; i++); // Frequency control
20 | }
21 |
22 | void I2C_Init(void) {
23 | I2C_SDA_H();
24 | I2C_DELAY();
25 | I2C_SCL_H();
26 | I2C_DELAY();
27 | }
28 |
29 | // Generate a I2C start sequence
30 | void I2C_Send_Start(void) {
31 | // I2C_SCL = H, I2C_SDA = H
32 | I2C_SDA_H();
33 | I2C_DELAY();
34 | I2C_SCL_H();
35 | I2C_DELAY();
36 | I2C_SDA_L();
37 | I2C_DELAY();
38 | I2C_SCL_L();
39 | I2C_DELAY();
40 | // I2C_SCL = L, I2C_SDA = L
41 | }
42 |
43 | // Write a byte (stored in I2C_Buf) to I2C bus and return the ACK status in I2C_Buf
44 | // xxxx xxx(ACK bit)
45 | // ACK bit = 0 -> ACK received
46 | // ACK bit = 1 -> NACK received
47 | void I2C_WriteByte(void) {
48 | // I2C_SCL = L
49 | if (I2C_Buf & 0x80) {I2C_SDA_H();} else {I2C_SDA_L();}
50 | I2C_DELAY();
51 | I2C_SCL_H();
52 | I2C_DELAY();
53 | I2C_SCL_L();
54 | I2C_DELAY();
55 |
56 | if (I2C_Buf & 0x40) {I2C_SDA_H();} else {I2C_SDA_L();}
57 | I2C_DELAY();
58 | I2C_SCL_H();
59 | I2C_DELAY();
60 | I2C_SCL_L();
61 | I2C_DELAY();
62 |
63 | if (I2C_Buf & 0x20) {I2C_SDA_H();} else {I2C_SDA_L();}
64 | I2C_DELAY();
65 | I2C_SCL_H();
66 | I2C_DELAY();
67 | I2C_SCL_L();
68 | I2C_DELAY();
69 |
70 | if (I2C_Buf & 0x10) {I2C_SDA_H();} else {I2C_SDA_L();}
71 | I2C_DELAY();
72 | I2C_SCL_H();
73 | I2C_DELAY();
74 | I2C_SCL_L();
75 | I2C_DELAY();
76 |
77 | if (I2C_Buf & 0x08) {I2C_SDA_H();} else {I2C_SDA_L();}
78 | I2C_DELAY();
79 | I2C_SCL_H();
80 | I2C_DELAY();
81 | I2C_SCL_L();
82 | I2C_DELAY();
83 |
84 | if (I2C_Buf & 0x04) {I2C_SDA_H();} else {I2C_SDA_L();}
85 | I2C_DELAY();
86 | I2C_SCL_H();
87 | I2C_DELAY();
88 | I2C_SCL_L();
89 | I2C_DELAY();
90 |
91 | if (I2C_Buf & 0x02) {I2C_SDA_H();} else {I2C_SDA_L();}
92 | I2C_DELAY();
93 | I2C_SCL_H();
94 | I2C_DELAY();
95 | I2C_SCL_L();
96 | I2C_DELAY();
97 |
98 | if (I2C_Buf & 0x01) {I2C_SDA_H();} else {I2C_SDA_L();}
99 | I2C_DELAY();
100 | I2C_SCL_H();
101 | I2C_DELAY();
102 | I2C_SCL_L();
103 | I2C_DELAY();
104 |
105 | I2C_SDA_H();
106 | I2C_DELAY();
107 |
108 | // Check ACK bit
109 | // I2C_SCL = L
110 | I2C_SCL_H();
111 | I2C_DELAY();
112 |
113 | I2C_Buf = 0;
114 | if (I2C_SDA())
115 | I2C_Buf = 1;
116 |
117 | I2C_SCL_L();
118 | I2C_DELAY();
119 | }
120 |
121 | // Read a byte from I2C bus and store the result into I2C_Buf
122 | void I2C_ReadByte(void) {
123 | I2C_Buf = 0;
124 |
125 | // I2C_SCL = L
126 | I2C_SDA_H(); //Master release the bus
127 | I2C_DELAY();
128 |
129 | I2C_SCL_H();
130 | I2C_DELAY();
131 | if (I2C_SDA())
132 | I2C_Buf |= 0x80;
133 | I2C_SCL_L();
134 | I2C_DELAY();
135 |
136 |
137 | I2C_SCL_H();
138 | I2C_DELAY();
139 | if (I2C_SDA())
140 | I2C_Buf |= 0x40;
141 | I2C_SCL_L();
142 | I2C_DELAY();
143 |
144 | I2C_SCL_H();
145 | I2C_DELAY();
146 | if (I2C_SDA())
147 | I2C_Buf |= 0x20;
148 | I2C_SCL_L();
149 | I2C_DELAY();
150 |
151 | I2C_SCL_H();
152 | I2C_DELAY();
153 | if (I2C_SDA())
154 | I2C_Buf |= 0x10;
155 | I2C_SCL_L();
156 | I2C_DELAY();
157 |
158 | I2C_SCL_H();
159 | I2C_DELAY();
160 | if (I2C_SDA())
161 | I2C_Buf |= 0x08;
162 | I2C_SCL_L();
163 | I2C_DELAY();
164 |
165 | I2C_SCL_H();
166 | I2C_DELAY();
167 | if (I2C_SDA())
168 | I2C_Buf |= 0x04;
169 | I2C_SCL_L();
170 | I2C_DELAY();
171 |
172 | I2C_SCL_H();
173 | I2C_DELAY();
174 | if (I2C_SDA())
175 | I2C_Buf |= 0x02;
176 | I2C_SCL_L();
177 | I2C_DELAY();
178 |
179 | I2C_SCL_H();
180 | I2C_DELAY();
181 | if (I2C_SDA())
182 | I2C_Buf |= 0x01;
183 | I2C_SCL_L();
184 | I2C_DELAY();
185 | }
186 |
187 | // Send a ACK to I2C bus
188 | void I2C_Send_ACK(void) {
189 | // I2C_SCL = L
190 | I2C_SDA_L();
191 | I2C_DELAY();
192 | I2C_SCL_H();
193 | I2C_DELAY();
194 | I2C_SCL_L();
195 | I2C_DELAY();
196 | }
197 |
198 | // Send a NACK to I2C bus
199 | void I2C_Send_NACK(void) {
200 | // I2C_SCL = L
201 | I2C_SDA_H();
202 | I2C_DELAY();
203 | I2C_SCL_H();
204 | I2C_DELAY();
205 | I2C_SCL_L();
206 | I2C_DELAY();
207 | }
208 |
209 | // Generate a I2C stop condition, release the bus
210 | void I2C_Send_Stop(void) {
211 | // I2C_SCL = L, I2C_SDA = H
212 | I2C_SDA_L();
213 | I2C_DELAY();
214 | I2C_SCL_H();
215 | I2C_DELAY();
216 | I2C_SDA_H(); //Master release the bus
217 | I2C_DELAY();
218 | }
219 |
--------------------------------------------------------------------------------
/i2c.h:
--------------------------------------------------------------------------------
1 | #ifndef __I2C_H
2 | #define __I2C_H
3 |
4 | #include "ch554_platform.h"
5 |
6 | extern xdata uint8_t I2C_Buf;
7 |
8 | void I2C_Init(void);
9 |
10 | // Generate a I2C start sequence
11 | void I2C_Send_Start(void);
12 | // Write a byte (stored in I2C_Buf) to I2C bus and return the ACK status in I2C_Buf
13 | // xxxx xxx(ACK bit)
14 | // ACK bit = 0 -> ACK received
15 | // ACK bit = 1 -> NACK received
16 | void I2C_WriteByte();
17 |
18 | // Read a byte from I2C bus and store the result into I2C_Buf
19 | void I2C_ReadByte(void);
20 | // Send a ACK to I2C bus
21 | void I2C_Send_ACK(void);
22 | // Send a NACK to I2C bus
23 | void I2C_Send_NACK(void);
24 |
25 | // Generate a I2C stop condition, release the bus
26 | void I2C_Send_Stop(void);
27 |
28 | #endif
--------------------------------------------------------------------------------
/include/ch554.h:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------------------------
2 | CH554.H
3 | Header file for CH554 microcontrollers.
4 | ****************************************
5 | ** Copyright (C) W.ch 1999-2014 **
6 | ** Web: http://wch.cn **
7 | ****************************************
8 | --------------------------------------------------------------------------*/
9 |
10 | #ifndef __CH554_H__
11 | #define __CH554_H__
12 |
13 | #include
14 |
15 | /*----- SFR --------------------------------------------------------------*/
16 | /* sbit are bit addressable, others are byte addressable */
17 |
18 | /* System Registers */
19 | SFR(PSW, 0xD0); // program status word
20 | SBIT(CY, 0xD0, 7); // carry flag
21 | SBIT(AC, 0xD0, 6); // auxiliary carry flag
22 | SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0
23 | SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit
24 | SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit
25 | #define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection
26 | // RS1 & RS0: register R0-R7 bank selection
27 | // 00 - bank 0, R0-R7 @ address 0x00-0x07
28 | // 01 - bank 1, R0-R7 @ address 0x08-0x0F
29 | // 10 - bank 2, R0-R7 @ address 0x10-0x17
30 | // 11 - bank 3, R0-R7 @ address 0x18-0x1F
31 | SBIT(OV, 0xD0, 2); // overflow flag
32 | SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1
33 | SBIT(P, 0xD0, 0); // ReadOnly: parity flag
34 | SFR(ACC, 0xE0); // accumulator
35 | SFR(B, 0xF0); // general purpose register B
36 | SFR(SP, 0x81); // stack pointer
37 | //sfr16 DPTR = 0x82; // DPTR pointer, little-endian
38 | SFR(DPL, 0x82); // data pointer low
39 | SFR(DPH, 0x83); // data pointer high
40 | SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode
41 | //sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID
42 | #define CHIP_ID SAFE_MOD
43 | SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode
44 | #define bBOOT_LOAD 0x20 // ReadOnly: boot loader status for discriminating BootLoader or Application: set 1 by power on reset, clear 0 by software reset
45 | #define bSW_RESET 0x10 // software reset bit, auto clear by hardware
46 | #define bCODE_WE 0x08 // enable flash-ROM (include code & Data-Flash) being program or erasing: 0=writing protect, 1=enable program and erase
47 | #define bDATA_WE 0x04 // enable Data-Flash (flash-ROM data area) being program or erasing: 0=writing protect, 1=enable program and erase
48 | #define bLDO3V3_OFF 0x02 // disable 5V->3.3V LDO: 0=enable LDO for USB and internal oscillator under 5V power, 1=disable LDO, V33 pin input external 3.3V power
49 | #define bWDOG_EN 0x01 // enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow
50 |
51 | /* Clock and Sleep and Power Registers */
52 | SFR(PCON, 0x87); // power control and reset flag
53 | #define SMOD 0x80 // baud rate selection for UART0 mode 1/2/3: 0=slow(Fsys/128 @mode2, TF1/32 @mode1/3, no effect for TF2),
54 | // 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2)
55 | #define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit
56 | #define bRST_FLAG0 0x10 // ReadOnly: recent reset flag low bit
57 | #define MASK_RST_FLAG 0x30 // ReadOnly: bit mask of recent reset flag
58 | #define RST_FLAG_SW 0x00
59 | #define RST_FLAG_POR 0x10
60 | #define RST_FLAG_WDOG 0x20
61 | #define RST_FLAG_PIN 0x30
62 | // bPC_RST_FLAG1 & bPC_RST_FLAG0: recent reset flag
63 | // 00 - software reset, by bSW_RESET=1 @(bBOOT_LOAD=0 or bWDOG_EN=1)
64 | // 01 - power on reset
65 | // 10 - watch-dog timer overflow reset
66 | // 11 - external input manual reset by RST pin
67 | #define GF1 0x08 // general purpose flag bit 1
68 | #define GF0 0x04 // general purpose flag bit 0
69 | #define PD 0x02 // power-down enable bit, auto clear by wake-up hardware
70 | SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode
71 | #define bOSC_EN_INT 0x80 // internal oscillator enable and original clock selection: 1=enable & select internal clock, 0=disable & select external clock
72 | #define bOSC_EN_XT 0x40 // external oscillator enable, need quartz crystal or ceramic resonator between XI and XO pins
73 | #define bWDOG_IF_TO 0x20 // ReadOnly: watch-dog timer overflow interrupt flag, cleared by reload watch-dog count or auto cleared when MCU enter interrupt routine
74 | #define bROM_CLK_FAST 0x10 // flash-ROM clock frequency selection: 0=normal(for Fosc>=16MHz), 1=fast(for Fosc<16MHz)
75 | #define bRST 0x08 // ReadOnly: pin RST input
76 | #define bT2EX_ 0x08 // alternate pin for T2EX
77 | #define bCAP2_ 0x08 // alternate pin for CAP2
78 | #define MASK_SYS_CK_SEL 0x07 // bit mask of system clock Fsys selection
79 | /*
80 | Fxt = 24MHz(8MHz~25MHz for non-USB application), from external oscillator @XI&XO
81 | Fosc = bOSC_EN_INT ? 24MHz : Fxt
82 | Fpll = Fosc * 4 => 96MHz (32MHz~100MHz for non-USB application)
83 | Fusb4x = Fpll / 2 => 48MHz (Fixed)
84 | MASK_SYS_CK_SEL[2] [1] [0]
85 | Fsys = Fpll/3 = 32MHz: 1 1 1
86 | Fsys = Fpll/4 = 24MHz: 1 1 0
87 | Fsys = Fpll/6 = 16MHz: 1 0 1
88 | Fsys = Fpll/8 = 12MHz: 1 0 0
89 | Fsys = Fpll/16 = 6MHz: 0 1 1
90 | Fsys = Fpll/32 = 3MHz: 0 1 0
91 | Fsys = Fpll/128 = 750KHz: 0 0 1
92 | Fsys = Fpll/512 =187.5KHz: 0 0 0
93 | */
94 | SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode
95 | #define bWAK_BY_USB 0x80 // enable wake-up by USB event
96 | #define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level
97 | #define bWAK_P1_5_LO 0x20 // enable wake-up by pin P1.5 low level
98 | #define bWAK_P1_4_LO 0x10 // enable wake-up by pin P1.4 low level
99 | #define bWAK_P1_3_LO 0x08 // enable wake-up by pin P1.3 low level
100 | #define bWAK_RST_HI 0x04 // enable wake-up by pin RST high level
101 | #define bWAK_P3_2E_3L 0x02 // enable wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level
102 | #define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level
103 | SFR(RESET_KEEP, 0xFE); // value keeper during reset
104 | SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536
105 |
106 | /* Interrupt Registers */
107 | SFR(IE, 0xA8); // interrupt enable
108 | SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0
109 | SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable
110 | SBIT(ET2, 0xA8, 5); // enable timer2 interrupt
111 | SBIT(ES, 0xA8, 4); // enable UART0 interrupt
112 | SBIT(ET1, 0xA8, 3); // enable timer1 interrupt
113 | SBIT(EX1, 0xA8, 2); // enable external interrupt INT1
114 | SBIT(ET0, 0xA8, 1); // enable timer0 interrupt
115 | SBIT(EX0, 0xA8, 0); // enable external interrupt INT0
116 | SFR(IP, 0xB8); // interrupt priority and current priority
117 | SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag
118 | SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag
119 | // PH_FLAG & PL_FLAG: current interrupt priority
120 | // 00 - no interrupt now
121 | // 01 - low level priority interrupt action now
122 | // 10 - high level priority interrupt action now
123 | // 11 - unknown error
124 | SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level
125 | SBIT(PS, 0xB8, 4); // UART0 interrupt priority level
126 | SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level
127 | SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level
128 | SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level
129 | SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level
130 | SFR(IE_EX, 0xE8); // extend interrupt enable
131 | SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt
132 | SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt
133 | SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt
134 | SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt
135 | SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt
136 | SBIT(IE_USB, 0xE8, 2); // enable USB interrupt
137 | SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt
138 | SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt
139 | SFR(IP_EX, 0xE9); // extend interrupt priority
140 | #define bIP_LEVEL 0x80 // ReadOnly: current interrupt nested level: 0=no interrupt or two levels, 1=one level
141 | #define bIP_GPIO 0x40 // GPIO input interrupt priority level
142 | #define bIP_PWMX 0x20 // PWM1/2 interrupt priority level
143 | #define bIP_UART1 0x10 // UART1 interrupt priority level
144 | #define bIP_ADC 0x08 // ADC interrupt priority level
145 | #define bIP_USB 0x04 // USB interrupt priority level
146 | #define bIP_TKEY 0x02 // touch-key timer interrupt priority level
147 | #define bIP_SPI0 0x01 // SPI0 interrupt priority level
148 | SFR(GPIO_IE, 0xC7); // GPIO interrupt enable
149 | #define bIE_IO_EDGE 0x80 // enable GPIO edge interrupt: 0=low/high level, 1=falling/rising edge
150 | #define bIE_RXD1_LO 0x40 // enable interrupt by RXD1 low level / falling edge
151 | #define bIE_P1_5_LO 0x20 // enable interrupt by pin P1.5 low level / falling edge
152 | #define bIE_P1_4_LO 0x10 // enable interrupt by pin P1.4 low level / falling edge
153 | #define bIE_P1_3_LO 0x08 // enable interrupt by pin P1.3 low level / falling edge
154 | #define bIE_RST_HI 0x04 // enable interrupt by pin RST high level / rising edge
155 | #define bIE_P3_1_LO 0x02 // enable interrupt by pin P3.1 low level / falling edge
156 | #define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge
157 |
158 | /* FlashROM and Data-Flash Registers */
159 | SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian
160 | SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM
161 | SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM
162 | SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian
163 | SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing
164 | SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing
165 | SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control
166 | #define ROM_CMD_WRITE 0x9A // WriteOnly: flash-ROM word or Data-Flash byte write operation command
167 | #define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command
168 | //sfr ROM_STATUS = 0x86; // ReadOnly: flash-ROM status
169 | #define ROM_STATUS ROM_CTRL
170 | #define bROM_ADDR_OK 0x40 // ReadOnly: flash-ROM writing operation address valid flag, can be reviewed before or after operation: 0=invalid parameter, 1=address valid
171 | #define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command
172 |
173 | /* Port Registers */
174 | SFR(P1, 0x90); // port 1 input & output
175 | SBIT(SCK, 0x90, 7); // serial clock for SPI0
176 | SBIT(TXD1, 0x90, 7); // TXD output for UART1
177 | SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key
178 | SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0
179 | SBIT(RXD1, 0x90, 6); // RXD input for UART1
180 | SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key
181 | SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0
182 | SBIT(PWM1, 0x90, 5); // PWM output for PWM1
183 | SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key
184 | SBIT(UCC2, 0x90, 5); // CC2 for USB type-C
185 | SBIT(AIN2, 0x90, 5); // AIN2 for ADC
186 | SBIT(T2_, 0x90, 4); // alternate pin for T2
187 | SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1
188 | SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0
189 | SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key
190 | SBIT(UCC1, 0x90, 4); // CC1 for USB type-C
191 | SBIT(AIN1, 0x90, 4); // AIN1 for ADC
192 | SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0
193 | SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0
194 | SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture
195 | SBIT(CAP2, 0x90, 1); // capture2 input for timer2
196 | SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key
197 | SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C
198 | SBIT(AIN0, 0x90, 1); // AIN0 for ADC
199 | SBIT(T2, 0x90, 0); // external count input
200 | SBIT(CAP1, 0x90, 0); // capture1 input for timer2
201 | SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key
202 | SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain
203 | SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain
204 | // Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3)
205 | // 0 0: float input only, without pullup resistance
206 | // 0 1: push-pull output, strong driving high level and low level
207 | // 1 0: open-drain output and input without pullup resistance
208 | // 1 1: quasi-bidirectional (standard 8051 mode), open-drain output and input with pullup resistance, just driving high level strongly for 2 clocks if turning output level from low to high
209 | #define bSCK 0x80 // serial clock for SPI0
210 | #define bTXD1 0x80 // TXD output for UART1
211 | #define bMISO 0x40 // master serial data input or slave serial data output for SPI0
212 | #define bRXD1 0x40 // RXD input for UART1
213 | #define bMOSI 0x20 // master serial data output or slave serial data input for SPI0
214 | #define bPWM1 0x20 // PWM output for PWM1
215 | #define bUCC2 0x20 // CC2 for USB type-C
216 | #define bAIN2 0x20 // AIN2 for ADC
217 | #define bT2_ 0x10 // alternate pin for T2
218 | #define bCAP1_ 0x10 // alternate pin for CAP1
219 | #define bSCS 0x10 // slave chip-selection input for SPI0
220 | #define bUCC1 0x10 // CC1 for USB type-C
221 | #define bAIN1 0x10 // AIN1 for ADC
222 | #define bTXD_ 0x08 // alternate pin for TXD of UART0
223 | #define bRXD_ 0x04 // alternate pin for RXD of UART0
224 | #define bT2EX 0x02 // external trigger input for timer2 reload & capture
225 | #define bCAP2 bT2EX // capture2 input for timer2
226 | #define bVBUS2 0x02 // VBUS2 for USB type-C
227 | #define bAIN0 0x02 // AIN0 for ADC
228 | #define bT2 0x01 // external count input or clock output for timer2
229 | #define bCAP1 bT2 // capture1 input for timer2
230 | SFR(P2, 0xA0); // port 2
231 | SFR(P3, 0xB0); // port 3 input & output
232 | SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input
233 | SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input
234 | SBIT(T1, 0xB0, 5); // external count input for timer1
235 | SBIT(PWM2, 0xB0, 4); // PWM output for PWM2
236 | SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1
237 | SBIT(T0, 0xB0, 4); // external count input for timer0
238 | SBIT(INT1, 0xB0, 3); // external interrupt 1 input
239 | SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1
240 | SBIT(INT0, 0xB0, 2); // external interrupt 0 input
241 | SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C
242 | SBIT(AIN3, 0xB0, 2); // AIN3 for ADC
243 | SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2
244 | SBIT(TXD, 0xB0, 1); // TXD output for UART0
245 | SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1
246 | SBIT(RXD, 0xB0, 0); // RXD input for UART0
247 | SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain
248 | SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain
249 | #define bUDM 0x80 // ReadOnly: pin UDM input
250 | #define bUDP 0x40 // ReadOnly: pin UDP input
251 | #define bT1 0x20 // external count input for timer1
252 | #define bPWM2 0x10 // PWM output for PWM2
253 | #define bRXD1_ 0x10 // alternate pin for RXD1
254 | #define bT0 0x10 // external count input for timer0
255 | #define bINT1 0x08 // external interrupt 1 input
256 | #define bTXD1_ 0x04 // alternate pin for TXD1
257 | #define bINT0 0x04 // external interrupt 0 input
258 | #define bVBUS1 0x04 // VBUS1 for USB type-C
259 | #define bAIN3 0x04 // AIN3 for ADC
260 | #define bPWM2_ 0x02 // alternate pin for PWM2
261 | #define bTXD 0x02 // TXD output for UART0
262 | #define bPWM1_ 0x01 // alternate pin for PWM1
263 | #define bRXD 0x01 // RXD input for UART0
264 | SFR(PIN_FUNC, 0xC6); // pin function selection
265 | #define bUSB_IO_EN 0x80 // USB UDP/UDM I/O pin enable: 0=P3.6/P3.7 as GPIO, 1=P3.6/P3.7 as USB
266 | #define bIO_INT_ACT 0x40 // ReadOnly: GPIO interrupt request action status
267 | #define bUART1_PIN_X 0x20 // UART1 alternate pin enable: 0=RXD1/TXD1 on P1.6/P1.7, 1=RXD1/TXD1 on P3.4/P3.2
268 | #define bUART0_PIN_X 0x10 // UART0 alternate pin enable: 0=RXD0/TXD0 on P3.0/P3.1, 1=RXD0/TXD0 on P1.2/P1.3
269 | #define bPWM2_PIN_X 0x08 // PWM2 alternate pin enable: 0=PWM2 on P3.4, 1=PWM2 on P3.1
270 | #define bPWM1_PIN_X 0x04 // PWM1 alternate pin enable: 0=PWM1 on P1.5, 1=PWM1 on P3.0
271 | #define bT2EX_PIN_X 0x02 // T2EX/CAP2 alternate pin enable: 0=T2EX/CAP2 on P1.1, 1=T2EX/CAP2 on RST
272 | #define bT2_PIN_X 0x01 // T2/CAP1 alternate pin enable: 0=T2/CAP1 on P1.1, 1=T2/CAP1 on P1.4
273 | SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting
274 | #define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status
275 | #define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status
276 | #define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status
277 | #define GF2 0x08 // general purpose flag bit 2
278 | #define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction
279 | #define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected
280 |
281 | /* Timer0/1 Registers */
282 | SFR(TCON, 0x88); // timer 0/1 control and external interrupt control
283 | SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
284 | SBIT(TR1, 0x88, 6); // timer1 run enable
285 | SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
286 | SBIT(TR0, 0x88, 4); // timer0 run enable
287 | SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine
288 | SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action
289 | SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine
290 | SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action
291 | SFR(TMOD, 0x89); // timer 0/1 mode
292 | #define bT1_GATE 0x80 // gate control of timer1: 0=timer1 run enable while TR1=1, 1=timer1 run enable while P3.3 (INT1) pin is high and TR1=1
293 | #define bT1_CT 0x40 // counter or timer mode selection for timer1: 0=timer, use internal clock, 1=counter, use P3.5 (T1) pin falling edge as clock
294 | #define bT1_M1 0x20 // timer1 mode high bit
295 | #define bT1_M0 0x10 // timer1 mode low bit
296 | #define MASK_T1_MOD 0x30 // bit mask of timer1 mode
297 | // bT1_M1 & bT1_M0: timer1 mode
298 | // 00: mode 0, 13-bit timer or counter by cascaded TH1 and lower 5 bits of TL1, the upper 3 bits of TL1 are ignored
299 | // 01: mode 1, 16-bit timer or counter by cascaded TH1 and TL1
300 | // 10: mode 2, TL1 operates as 8-bit timer or counter, and TH1 provide initial value for TL1 auto-reload
301 | // 11: mode 3, stop timer1
302 | #define bT0_GATE 0x08 // gate control of timer0: 0=timer0 run enable while TR0=1, 1=timer0 run enable while P3.2 (INT0) pin is high and TR0=1
303 | #define bT0_CT 0x04 // counter or timer mode selection for timer0: 0=timer, use internal clock, 1=counter, use P3.4 (T0) pin falling edge as clock
304 | #define bT0_M1 0x02 // timer0 mode high bit
305 | #define bT0_M0 0x01 // timer0 mode low bit
306 | #define MASK_T0_MOD 0x03 // bit mask of timer0 mode
307 | // bT0_M1 & bT0_M0: timer0 mode
308 | // 00: mode 0, 13-bit timer or counter by cascaded TH0 and lower 5 bits of TL0, the upper 3 bits of TL0 are ignored
309 | // 01: mode 1, 16-bit timer or counter by cascaded TH0 and TL0
310 | // 10: mode 2, TL0 operates as 8-bit timer or counter, and TH0 provide initial value for TL0 auto-reload
311 | // 11: mode 3, TL0 is 8-bit timer or counter controlled by standard timer0 bits, TH0 is 8-bit timer using TF1 and controlled by TR1, timer1 run enable if it is not mode 3
312 | SFR(TL0, 0x8A); // low byte of timer 0 count
313 | SFR(TL1, 0x8B); // low byte of timer 1 count
314 | SFR(TH0, 0x8C); // high byte of timer 0 count
315 | SFR(TH1, 0x8D); // high byte of timer 1 count
316 |
317 | /* UART0 Registers */
318 | SFR(SCON, 0x98); // UART0 control (serial port control)
319 | SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data
320 | SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable
321 | // SM0 & SM1: UART0 mode
322 | // 00 - mode 0, shift Register, baud rate fixed at: Fsys/12
323 | // 01 - mode 1, 8-bit UART, baud rate = variable by timer1 or timer2 overflow rate
324 | // 10 - mode 2, 9-bit UART, baud rate fixed at: Fsys/128@SMOD=0, Fsys/32@SMOD=1
325 | // 11 - mode 3, 9-bit UART, baud rate = variable by timer1 or timer2 overflow rate
326 | SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3
327 | #define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode
328 | SBIT(REN, 0x98, 4); // enable UART0 receiving
329 | SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3
330 | SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1
331 | SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear
332 | SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear
333 | SFR(SBUF, 0x99); // UART0 data buffer: reading for receiving, writing for transmittal
334 |
335 | /* Timer2/Capture2 Registers */
336 | SFR(T2CON, 0xC8); // timer 2 control
337 | SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1
338 | SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear
339 | SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear
340 | SBIT(RCLK, 0xC8, 5); // selection UART0 receiving clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse
341 | SBIT(TCLK, 0xC8, 4); // selection UART0 transmittal clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse
342 | SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge
343 | SBIT(TR2, 0xC8, 2); // timer2 run enable
344 | SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge
345 | SBIT(CP_RL2, 0xC8, 0); // timer2 function selection (force 0 if RCLK=1 or TCLK=1): 0=timer and auto reload if count overflow or T2EX edge, 1=capture by T2EX edge
346 | SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode
347 | #define bTMR_CLK 0x80 // fastest internal clock mode for timer 0/1/2 under faster clock mode: 0=use divided clock, 1=use original Fsys as clock without dividing
348 | #define bT2_CLK 0x40 // timer2 internal clock frequency selection: 0=standard clock, Fsys/12 for timer mode, Fsys/4 for UART0 clock mode,
349 | // 1=faster clock, Fsys/4 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for timer mode, Fsys/2 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for UART0 clock mode
350 | #define bT1_CLK 0x20 // timer1 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1
351 | #define bT0_CLK 0x10 // timer0 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1
352 | #define bT2_CAP_M1 0x08 // timer2 capture mode high bit
353 | #define bT2_CAP_M0 0x04 // timer2 capture mode low bit
354 | // bT2_CAP_M1 & bT2_CAP_M0: timer2 capture point selection
355 | // x0: from falling edge to falling edge
356 | // 01: from any edge to any edge (level changing)
357 | // 11: from rising edge to rising edge
358 | #define T2OE 0x02 // enable timer2 generated clock output: 0=disable output, 1=enable clock output at T2 pin, frequency = TF2/2
359 | #define bT2_CAP1_EN 0x01 // enable T2 trigger function for capture 1 of timer2 if RCLK=0 & TCLK=0 & CP_RL2=1 & C_T2=0 & T2OE=0
360 | SFR16(RCAP2, 0xCA); // reload & capture value, little-endian
361 | SFR(RCAP2L, 0xCA); // low byte of reload & capture value
362 | SFR(RCAP2H, 0xCB); // high byte of reload & capture value
363 | SFR16(T2COUNT, 0xCC); // counter, little-endian
364 | SFR(TL2, 0xCC); // low byte of timer 2 count
365 | SFR(TH2, 0xCD); // high byte of timer 2 count
366 | SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2
367 | SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2
368 | SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2
369 |
370 | /* PWM1/2 Registers */
371 | SFR(PWM_DATA2, 0x9B); // PWM data for PWM2
372 | SFR(PWM_DATA1, 0x9C); // PWM data for PWM1
373 | SFR(PWM_CTRL, 0x9D); // PWM 1/2 control
374 | #define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end
375 | #define bPWM2_POLAR 0x40 // PWM2 output polarity: 0=default low and high action, 1=default high and low action
376 | #define bPWM1_POLAR 0x20 // PWM1 output polarity: 0=default low and high action, 1=default high and low action
377 | #define bPWM_IF_END 0x10 // interrupt flag for cycle end, write 1 to clear or write PWM_CYCLE or load new data to clear
378 | #define bPWM2_OUT_EN 0x08 // PWM2 output enable
379 | #define bPWM1_OUT_EN 0x04 // PWM1 output enable
380 | #define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2
381 | SFR(PWM_CK_SE, 0x9E); // clock divisor setting
382 |
383 | /* SPI0/Master0/Slave Registers */
384 | SFR(SPI0_STAT, 0xF8); // SPI 0 status
385 | SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0
386 | SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear
387 | SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear
388 | SBIT(S0_IF_BYTE, 0xF8, 4); // interrupt flag for a byte data exchanged, direct bit address clear or write 1 to clear or accessing FIFO to clear if bS0_AUTO_IF=1
389 | SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status
390 | SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0
391 | SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0
392 | SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receiving, writing for transmittal
393 | SFR(SPI0_CTRL, 0xFA); // SPI 0 control
394 | #define bS0_MISO_OE 0x80 // SPI0 MISO output enable
395 | #define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable
396 | #define bS0_SCK_OE 0x20 // SPI0 SCK output enable
397 | #define bS0_DATA_DIR 0x10 // SPI0 data direction: 0=out(master_write), 1=in(master_read)
398 | #define bS0_MST_CLK 0x08 // SPI0 master clock mode: 0=mode 0 with default low, 1=mode 3 with default high
399 | #define bS0_2_WIRE 0x04 // enable SPI0 two wire mode: 0=3 wire (SCK+MOSI+MISO), 1=2 wire (SCK+MISO)
400 | #define bS0_CLR_ALL 0x02 // force clear FIFO and count of SPI0
401 | #define bS0_AUTO_IF 0x01 // enable FIFO accessing to auto clear S0_IF_BYTE interrupt flag
402 | SFR(SPI0_CK_SE, 0xFB); // clock divisor setting
403 | //sfr SPI0_S_PRE = 0xFB; // preset value for SPI slave
404 | #define SPI0_S_PRE SPI0_CK_SE
405 | SFR(SPI0_SETUP, 0xFC); // SPI 0 setup
406 | #define bS0_MODE_SLV 0x80 // SPI0 slave mode: 0=master, 1=slave
407 | #define bS0_IE_FIFO_OV 0x40 // enable interrupt for slave mode FIFO overflow
408 | #define bS0_IE_FIRST 0x20 // enable interrupt for first byte received for SPI0 slave mode
409 | #define bS0_IE_BYTE 0x10 // enable interrupt for a byte received
410 | #define bS0_BIT_ORDER 0x08 // SPI0 bit data order: 0=MSB first, 1=LSB first
411 | #define bS0_SLV_SELT 0x02 // ReadOnly: SPI0 slave mode chip selected status: 0=unselected, 1=selected
412 | #define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection
413 |
414 | /* UART1 Registers */
415 | SFR(SCON1, 0xC0); // UART1 control (serial port control)
416 | SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data
417 | SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1))
418 | SBIT(U1REN, 0xC0, 4); // enable UART1 receiving
419 | SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode
420 | SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode
421 | SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear
422 | SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear
423 | SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receiving, writing for transmittal
424 | SFR(SBAUD1, 0xC2); // UART1 baud rate setting
425 |
426 | /* ADC and comparator Registers */
427 | SFR(ADC_CTRL, 0x80); // ADC control
428 | SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input
429 | SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear
430 | SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear
431 | SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished
432 | SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3
433 | SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit
434 | SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit
435 | // ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection
436 | // 00: AIN0(P1.1)
437 | // 01: AIN1(P1.4)
438 | // 10: AIN2(P1.5)
439 | // 11: AIN3(P3.2)
440 | SFR(ADC_CFG, 0x9A); // ADC config
441 | #define bADC_EN 0x08 // control ADC power: 0=shut down ADC, 1=enable power for ADC
442 | #define bCMP_EN 0x04 // control comparator power: 0=shut down comparator, 1=enable power for comparator
443 | #define bADC_CLK 0x01 // ADC clock frequency selection: 0=slow clock, 384 Fosc cycles for each ADC, 1=fast clock, 96 Fosc cycles for each ADC
444 | SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data
445 |
446 | /* Touch-key timer Registers */
447 | SFR(TKEY_CTRL, 0xC3); // touch-key control
448 | #define bTKC_IF 0x80 // ReadOnly: interrupt flag for touch-key timer, cleared by writing touch-key control or auto cleared when start touch-key checking
449 | #define bTKC_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS
450 | #define bTKC_CHAN2 0x04 // touch-key channel selection high bit
451 | #define bTKC_CHAN1 0x02 // touch-key channel selection middle bit
452 | #define bTKC_CHAN0 0x01 // touch-key channel selection low bit
453 | // bTKC_CHAN2 & bTKC_CHAN1 & bTKC_CHAN0: touch-key channel selection
454 | // 000: disable touch-key
455 | // 001: TIN0(P1.0)
456 | // 010: TIN1(P1.1)
457 | // 011: TIN2(P1.4)
458 | // 100: TIN3(P1.5)
459 | // 101: TIN4(P1.6)
460 | // 110: TIN5(P1.7)
461 | // 111: enable touch-key but disable all channel
462 | SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian
463 | SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data
464 | SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data
465 | #define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid
466 |
467 | /* USB/Host/Device Registers */
468 | SFR(USB_C_CTRL, 0x91); // USB type-C control
469 | #define bVBUS2_PD_EN 0x80 // USB VBUS2 10K pulldown resistance: 0=disable, 1=enable pullup
470 | #define bUCC2_PD_EN 0x40 // USB CC2 5.1K pulldown resistance: 0=disable, 1=enable pulldown
471 | #define bUCC2_PU1_EN 0x20 // USB CC2 pullup resistance control high bit
472 | #define bUCC2_PU0_EN 0x10 // USB CC2 pullup resistance control low bit
473 | #define bVBUS1_PD_EN 0x08 // USB VBUS1 10K pulldown resistance: 0=disable, 1=enable pullup
474 | #define bUCC1_PD_EN 0x04 // USB CC1 5.1K pulldown resistance: 0=disable, 1=enable pulldown
475 | #define bUCC1_PU1_EN 0x02 // USB CC1 pullup resistance control high bit
476 | #define bUCC1_PU0_EN 0x01 // USB CC1 pullup resistance control low bit
477 | // bUCC?_PU1_EN & bUCC?_PU0_EN: USB CC pullup resistance selection
478 | // 00: disable pullup resistance
479 | // 01: enable 56K pullup resistance for default USB power
480 | // 10: enable 22K pullup resistance for 1.5A USB power
481 | // 11: enable 10K pullup resistance for 3A USB power
482 | SFR(UDEV_CTRL, 0xD1); // USB device physical port control
483 | #define bUD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
484 | #define bUD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
485 | #define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
486 | #define bUD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
487 | #define bUD_GP_BIT 0x02 // general purpose bit
488 | #define bUD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
489 | //sfr UHOST_CTRL = 0xD1; // USB host physical port control
490 | #define UHOST_CTRL UDEV_CTRL
491 | #define bUH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
492 | #define bUH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
493 | #define bUH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
494 | #define bUH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
495 | #define bUH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
496 | #define bUH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
497 | SFR(UEP1_CTRL, 0xD2); // endpoint 1 control
498 | #define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
499 | #define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
500 | #define bUEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
501 | #define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT)
502 | #define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT)
503 | #define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT)
504 | #define UEP_R_RES_ACK 0x00
505 | #define UEP_R_RES_TOUT 0x04
506 | #define UEP_R_RES_NAK 0x08
507 | #define UEP_R_RES_STALL 0x0C
508 | // bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receiving (OUT)
509 | // 00: ACK (ready)
510 | // 01: no response, time out to host, for non-zero endpoint isochronous transactions
511 | // 10: NAK (busy)
512 | // 11: STALL (error)
513 | #define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN)
514 | #define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN)
515 | #define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
516 | #define UEP_T_RES_ACK 0x00
517 | #define UEP_T_RES_TOUT 0x01
518 | #define UEP_T_RES_NAK 0x02
519 | #define UEP_T_RES_STALL 0x03
520 | // bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
521 | // 00: DATA0 or DATA1 then expecting ACK (ready)
522 | // 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
523 | // 10: NAK (busy)
524 | // 11: STALL (error)
525 | SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length
526 | SFR(UEP2_CTRL, 0xD4); // endpoint 2 control
527 | SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length
528 | SFR(UEP3_CTRL, 0xD6); // endpoint 3 control
529 | SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length
530 | SFR(USB_INT_FG, 0xD8); // USB interrupt flag
531 | SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received
532 | SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK
533 | SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status
534 | SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
535 | SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
536 | SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
537 | SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
538 | SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
539 | SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
540 | SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status
541 | #define bUIS_IS_NAK 0x80 // ReadOnly: indicate current USB transfer is NAK received for USB device mode
542 | #define bUIS_TOG_OK 0x40 // ReadOnly: indicate current USB transfer toggle is OK
543 | #define bUIS_TOKEN1 0x20 // ReadOnly: current token PID code bit 1 received for USB device mode
544 | #define bUIS_TOKEN0 0x10 // ReadOnly: current token PID code bit 0 received for USB device mode
545 | #define MASK_UIS_TOKEN 0x30 // ReadOnly: bit mask of current token PID code received for USB device mode
546 | #define UIS_TOKEN_OUT 0x00
547 | #define UIS_TOKEN_SOF 0x10
548 | #define UIS_TOKEN_IN 0x20
549 | #define UIS_TOKEN_SETUP 0x30
550 | // bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode
551 | // 00: OUT token PID received
552 | // 01: SOF token PID received
553 | // 10: IN token PID received
554 | // 11: SETUP token PID received
555 | #define MASK_UIS_ENDP 0x0F // ReadOnly: bit mask of current transfer endpoint number for USB device mode
556 | #define MASK_UIS_H_RES 0x0F // ReadOnly: bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
557 | SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status
558 | #define bUMS_SOF_PRES 0x80 // ReadOnly: indicate host SOF timer presage status
559 | #define bUMS_SOF_ACT 0x40 // ReadOnly: indicate host SOF timer action status for USB host
560 | #define bUMS_SIE_FREE 0x20 // ReadOnly: indicate USB SIE free status
561 | #define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receiving FIFO ready status (not empty)
562 | #define bUMS_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status
563 | #define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend status
564 | #define bUMS_DM_LEVEL 0x02 // ReadOnly: indicate UDM level saved at device attached to USB host
565 | #define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host
566 | SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length
567 | SFR(UEP0_CTRL, 0xDC); // endpoint 0 control
568 | SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length
569 | SFR(UEP4_CTRL, 0xDE); // endpoint 4 control
570 | SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length
571 | SFR(USB_INT_EN, 0xE1); // USB interrupt enable
572 | #define bUIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode
573 | #define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
574 | #define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
575 | #define bUIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode
576 | #define bUIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event
577 | #define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
578 | #define bUIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode
579 | #define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode
580 | SFR(USB_CTRL, 0xE2); // USB base control
581 | #define bUC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode
582 | #define bUC_LOW_SPEED 0x40 // enable USB low speed: 0=full speed, 1=low speed
583 | #define bUC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable
584 | #define bUC_SYS_CTRL1 0x20 // USB system control high bit
585 | #define bUC_SYS_CTRL0 0x10 // USB system control low bit
586 | #define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control
587 | // bUC_HOST_MODE & bUC_SYS_CTRL1 & bUC_SYS_CTRL0: USB system control
588 | // 0 00: disable USB device and disable internal pullup resistance
589 | // 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance
590 | // 0 1x: enable USB device and enable internal pullup resistance
591 | // 1 00: enable USB host and normal status
592 | // 1 01: enable USB host and force UDP/UDM output SE0 state
593 | // 1 10: enable USB host and force UDP/UDM output J state
594 | // 1 11: enable USB host and force UDP/UDM output resume or K state
595 | #define bUC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid
596 | #define bUC_RESET_SIE 0x04 // force reset USB SIE, need software clear
597 | #define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB
598 | #define bUC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB
599 | SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address
600 | #define bUDA_GP_BIT 0x80 // general purpose bit
601 | #define MASK_USB_ADDR 0x7F // bit mask for USB device address
602 | SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian
603 | SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte
604 | SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte
605 | SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian
606 | SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte
607 | SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte
608 | SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode
609 | #define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
610 | #define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
611 | #define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
612 | // bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA
613 | // 0 0 x: disable endpoint and disable buffer
614 | // 1 0 0: 64 bytes buffer for receiving (OUT endpoint)
615 | // 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes
616 | // 0 1 0: 64 bytes buffer for transmittal (IN endpoint)
617 | // 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes
618 | // 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes
619 | // 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes
620 | #define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
621 | #define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
622 | // bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA
623 | // 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
624 | // 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes
625 | // 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes
626 | // 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
627 | // + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes
628 | SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode
629 | #define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
630 | #define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
631 | #define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
632 | #define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
633 | #define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
634 | #define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
635 | SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian
636 | SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte
637 | SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte
638 | SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian
639 | SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte
640 | SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte
641 | //sfr UH_SETUP = 0xD2; // host aux setup
642 | #define UH_SETUP UEP1_CTRL
643 | #define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub
644 | #define bUH_SOF_EN 0x40 // USB host automatic SOF enable
645 | //sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control
646 | #define UH_RX_CTRL UEP2_CTRL
647 | #define bUH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
648 | #define bUH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
649 | #define bUH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
650 | //sfr UH_EP_PID = 0xD5; // host endpoint and token PID, lower 4 bits for endpoint number, upper 4 bits for token PID
651 | #define UH_EP_PID UEP2_T_LEN
652 | #define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer
653 | #define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer
654 | //sfr UH_TX_CTRL = 0xD6; // host transmittal endpoint control
655 | #define UH_TX_CTRL UEP3_CTRL
656 | #define bUH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
657 | #define bUH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
658 | #define bUH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
659 | //sfr UH_TX_LEN = 0xD7; // host transmittal endpoint transmittal length
660 | #define UH_TX_LEN UEP3_T_LEN
661 | //sfr UH_EP_MOD = 0xEB; // host endpoint mode
662 | #define UH_EP_MOD UEP2_3_MOD
663 | #define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
664 | #define bUH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
665 | // bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
666 | // 0 x: disable endpoint and disable buffer
667 | // 1 0: 64 bytes buffer for transmittal (OUT endpoint)
668 | // 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
669 | #define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
670 | #define bUH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
671 | // bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
672 | // 0 x: disable endpoint and disable buffer
673 | // 1 0: 64 bytes buffer for receiving (IN endpoint)
674 | // 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
675 | //sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian
676 | #define UH_RX_DMA UEP2_DMA
677 | //sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte
678 | #define UH_RX_DMA_L UEP2_DMA_L
679 | //sfr UH_RX_DMA_H = 0xE5; // host rx endpoint buffer start address high byte
680 | #define UH_RX_DMA_H UEP2_DMA_H
681 | //sfr16 UH_TX_DMA = 0xE6; // host tx endpoint buffer start address, little-endian
682 | #define UH_TX_DMA UEP3_DMA
683 | //sfr UH_TX_DMA_L = 0xE6; // host tx endpoint buffer start address low byte
684 | #define UH_TX_DMA_L UEP3_DMA_L
685 | //sfr UH_TX_DMA_H = 0xE7; // host tx endpoint buffer start address high byte
686 | #define UH_TX_DMA_H UEP3_DMA_H
687 |
688 | /*----- XDATA: xRAM ------------------------------------------*/
689 |
690 | #define XDATA_RAM_SIZE 0x0400 // size of expanded xRAM, xdata SRAM embedded chip
691 |
692 | /*----- Reference Information --------------------------------------------*/
693 | #define ID_CH554 0x54 // chip ID
694 |
695 | /* Interrupt routine address and interrupt number */
696 | #define INT_ADDR_INT0 0x0003 // interrupt vector address for INT0
697 | #define INT_ADDR_TMR0 0x000B // interrupt vector address for timer0
698 | #define INT_ADDR_INT1 0x0013 // interrupt vector address for INT1
699 | #define INT_ADDR_TMR1 0x001B // interrupt vector address for timer1
700 | #define INT_ADDR_UART0 0x0023 // interrupt vector address for UART0
701 | #define INT_ADDR_TMR2 0x002B // interrupt vector address for timer2
702 | #define INT_ADDR_SPI0 0x0033 // interrupt vector address for SPI0
703 | #define INT_ADDR_TKEY 0x003B // interrupt vector address for touch-key timer
704 | #define INT_ADDR_USB 0x0043 // interrupt vector address for USB
705 | #define INT_ADDR_ADC 0x004B // interrupt vector address for ADC
706 | #define INT_ADDR_UART1 0x0053 // interrupt vector address for UART1
707 | #define INT_ADDR_PWMX 0x005B // interrupt vector address for PWM1/2
708 | #define INT_ADDR_GPIO 0x0063 // interrupt vector address for GPIO
709 | #define INT_ADDR_WDOG 0x006B // interrupt vector address for watch-dog timer
710 | #define INT_NO_INT0 0 // interrupt number for INT0
711 | #define INT_NO_TMR0 1 // interrupt number for timer0
712 | #define INT_NO_INT1 2 // interrupt number for INT1
713 | #define INT_NO_TMR1 3 // interrupt number for timer1
714 | #define INT_NO_UART0 4 // interrupt number for UART0
715 | #define INT_NO_TMR2 5 // interrupt number for timer2
716 | #define INT_NO_SPI0 6 // interrupt number for SPI0
717 | #define INT_NO_TKEY 7 // interrupt number for touch-key timer
718 | #define INT_NO_USB 8 // interrupt number for USB
719 | #define INT_NO_ADC 9 // interrupt number for ADC
720 | #define INT_NO_UART1 10 // interrupt number for UART1
721 | #define INT_NO_PWMX 11 // interrupt number for PWM1/2
722 | #define INT_NO_GPIO 12 // interrupt number for GPIO
723 | #define INT_NO_WDOG 13 // interrupt number for watch-dog timer
724 |
725 | /* Special Program Space */
726 | #define DATA_FLASH_ADDR 0xC000 // start address of Data-Flash
727 | #define BOOT_LOAD_ADDR 0x3800 // start address of boot loader program
728 | #define ROM_CFG_ADDR 0x3FF8 // chip configuration information address
729 | #define ROM_CHIP_ID_HX 0x3FFA // chip ID number highest byte (only low byte valid)
730 | #define ROM_CHIP_ID_LO 0x3FFC // chip ID number low word
731 | #define ROM_CHIP_ID_HI 0x3FFE // chip ID number high word
732 |
733 | /*
734 | New Instruction: MOVX @DPTR1,A
735 | Instruction Code: 0xA5
736 | Instruction Cycle: 1
737 | Instruction Operation:
738 | step-1. write ACC @DPTR1 into xdata SRAM embedded chip
739 | step-2. increase DPTR1
740 | ASM example:
741 | INC XBUS_AUX
742 | MOV DPTR,#TARGET_ADDR ;DPTR1
743 | DEC XBUS_AUX
744 | MOV DPTR,#SOURCE_ADDR ;DPTR0
745 | MOV R7,#xxH
746 | LOOP: MOVX A,@DPTR ;DPTR0
747 | INC DPTR ;DPTR0, if need
748 | DB 0A5H ;MOVX @DPTR1,A & INC DPTR1
749 | DJNZ R7,LOOP
750 | */
751 |
752 | #endif // __CH554_H__
753 |
--------------------------------------------------------------------------------
/include/ch554_datatypes.h:
--------------------------------------------------------------------------------
1 | /*--------------------------------------------------------------------------
2 | CH554.H
3 | Header file for CH554 microcontrollers.
4 | ****************************************
5 | ** Copyright (C) W.ch 1999-2014 **
6 | ** Web: http://wch.cn **
7 | ****************************************
8 | --------------------------------------------------------------------------*/
9 |
10 | #ifndef __BASE_TYPE__
11 | #define __BASE_TYPE__
12 |
13 | /*----- constant and type define -----------------------------------------*/
14 |
15 | #ifndef TRUE
16 | #define TRUE 1
17 | #define FALSE 0
18 | #endif
19 | #ifndef NULL
20 | #define NULL 0
21 | #endif
22 |
23 | #ifndef BOOL
24 | typedef bit BOOL;
25 | #endif
26 | #ifndef UINT8
27 | typedef unsigned char UINT8;
28 | #endif
29 | #ifndef UINT16
30 | typedef unsigned short UINT16;
31 | #endif
32 | #ifndef UINT32
33 | typedef unsigned long UINT32;
34 | #endif
35 | #ifndef UINT8D
36 | typedef unsigned char data UINT8D;
37 | #endif
38 | #ifndef UINT16D
39 | typedef unsigned short data UINT16D;
40 | #endif
41 | #ifndef UINT32D
42 | typedef unsigned long data UINT32D;
43 | #endif
44 | #ifndef UINT8I
45 | typedef unsigned char idata UINT8I;
46 | #endif
47 | #ifndef UINT16I
48 | typedef unsigned short idata UINT16I;
49 | #endif
50 | #ifndef UINT32I
51 | typedef unsigned long idata UINT32I;
52 | #endif
53 | #ifndef UINT8X
54 | typedef unsigned char xdata UINT8X;
55 | #endif
56 | #ifndef UINT16X
57 | typedef unsigned short xdata UINT16X;
58 | #endif
59 | #ifndef UINT32X
60 | typedef unsigned long xdata UINT32X;
61 | #endif
62 | #ifndef UINT8V
63 | typedef unsigned char volatile UINT8V;
64 | #endif
65 | #ifndef UINT8DV
66 | typedef unsigned char volatile data UINT8DV;
67 | #endif
68 | #ifndef UINT8XV
69 | typedef unsigned char volatile xdata UINT8XV;
70 | #endif
71 | #ifndef UINT8PV
72 | typedef unsigned char volatile pdata UINT8PV;
73 | #endif
74 | #ifndef UINT8C
75 | typedef const unsigned char code UINT8C;
76 | #endif
77 | #ifndef PUINT8
78 | typedef unsigned char *PUINT8;
79 | #endif
80 | #ifndef PUINT16
81 | typedef unsigned short *PUINT16;
82 | #endif
83 | #ifndef PUINT32
84 | typedef unsigned long *PUINT32;
85 | #endif
86 | #ifndef PUINT8I
87 | typedef unsigned char idata *PUINT8I;
88 | #endif
89 | #ifndef PUINT16I
90 | typedef unsigned short idata *PUINT16I;
91 | #endif
92 | #ifndef PUINT32I
93 | typedef unsigned long idata *PUINT32I;
94 | #endif
95 | #ifndef PUINT8X
96 | typedef unsigned char xdata *PUINT8X;
97 | #endif
98 | #ifndef PUINT16X
99 | typedef unsigned short xdata *PUINT16X;
100 | #endif
101 | #ifndef PUINT32X
102 | typedef unsigned long xdata *PUINT32X;
103 | #endif
104 | #ifndef PUINT8V
105 | typedef unsigned char volatile *PUINT8V;
106 | #endif
107 | #ifndef PUINT8DV
108 | typedef unsigned char volatile data *PUINT8DV;
109 | #endif
110 | #ifndef PUINT8XV
111 | typedef unsigned char volatile xdata *PUINT8XV;
112 | #endif
113 | #ifndef PUINT8PV
114 | typedef unsigned char volatile pdata *PUINT8PV;
115 | #endif
116 | #ifndef PUINT8C
117 | typedef const unsigned char code *PUINT8C;
118 | #endif
119 |
120 | #ifndef STRUCT_OFFSET
121 | #define STRUCT_OFFSET( s, m ) ( (UINT8)( & (((s) *)0) -> (m) ) ) /* get the offset address for a member of a structure */
122 | #endif
123 |
124 | #endif // __BASE_TYPE__
125 |
--------------------------------------------------------------------------------
/include/ch554_usb.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/include/ch554_usb.h
--------------------------------------------------------------------------------
/keilc51/CH554.H:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/keilc51/CH554.H
--------------------------------------------------------------------------------
/keilc51/CH554.INC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/keilc51/CH554.INC
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | #include "Delay.H"
2 | #include "usb_cdc.h"
3 |
4 | #include "ch554_platform.h"
5 |
6 | void main(void) {
7 | CDC_InitBaud();
8 | CH554_Init();
9 |
10 | while(1) {
11 | CDC_USB_Poll();
12 | CDC_UART_Poll();
13 | };
14 | }
15 |
16 | /*
17 | * According to SDCC specification, interrupt handlers MUST be placed within the file which contains
18 | * the void main(void) function, otherwise SDCC won't be able to recognize it. It's not a bug but a feature.
19 | * If you know how to fix this, please let me know.
20 | */
21 | void USBInterruptEntry(void) interrupt INT_NO_USB {
22 | USBInterrupt();
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/spi.c:
--------------------------------------------------------------------------------
1 | #include "spi.h"
2 |
3 | #include "ch554_platform.h"
4 |
5 | void SPI_SetMasterMode0(void) {
6 | SPI0_SETUP = 0; // Master, MSB first
7 | SPI0_CTRL = 0x60; // Mode 0
8 | }
9 |
10 | void SPI_SetMasterMode3(void) {
11 | SPI0_SETUP = 0; // Master, MSB first
12 | SPI0_CTRL = 0x68; // Mode 3
13 | }
14 |
15 | void SPI_SetMasterIO(void) {
16 | P1_MOD_OC &= 0x0F;
17 | P1_DIR_PU |= 0xB0; // SCS,MOSI,SCK push-pull
18 | P1_DIR_PU &= 0xBF; // MISO floating
19 | }
20 |
21 | void SPI_SetMasterIOFloat(void) {
22 | P1_MOD_OC |= 0xF0;
23 | P1_DIR_PU &= 0x0F; // SCS,MOSI,SCK,MISO floating, no pull-up
24 | }
25 |
26 | uint8_t SPI_MasterData(uint8_t dat) {
27 | SPI0_DATA = dat;
28 | while(S0_FREE == 0);
29 | return SPI0_DATA;
30 | }
31 |
--------------------------------------------------------------------------------
/spi.h:
--------------------------------------------------------------------------------
1 | #ifndef __SPI_H_
2 | #define __SPI_H_
3 |
4 | #include "ch554_platform.h"
5 |
6 | #define SPI_SetCS(cs) (SCS = cs)
7 | #define SPI_SetClockDivider(n) (SPI0_CK_SE = n)
8 |
9 | void SPI_SetMasterMode0(void);
10 | void SPI_SetMasterMode3(void);
11 | void SPI_SetMasterIO(void);
12 | void SPI_SetMasterIOFloat(void);
13 | uint8_t SPI_MasterData(uint8_t dat);
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/usb_cdc.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/usb_cdc.c
--------------------------------------------------------------------------------
/usb_cdc.h:
--------------------------------------------------------------------------------
1 | #ifndef __USB_CDC_H
2 | #define __USB_CDC_H
3 |
4 | #include "ch554_platform.h"
5 |
6 | // CDC bRequests:
7 | // bmRequestType = 0xA1
8 | #define SERIAL_STATE 0x20
9 | #define GET_LINE_CODING 0X21 // This request allows the host to find out the currently configured line coding.
10 | // bmRequestType = 21
11 | #define SET_LINE_CODING 0X20 // Configures DTE rate, stop-bits, parity, and number-of-character
12 | #define SET_CONTROL_LINE_STATE 0X22 // This request generates RS-232/V.24 style control signals.
13 | #define SEND_BREAK 0x23
14 |
15 | // CDC Rx state machine
16 | #define CDC_STATE_IDLE 0
17 | #define CDC_STATE_I2C_TXSTART 1
18 | #define CDC_STATE_I2C_TXING 2
19 | #define CDC_STATE_I2C_RXSTART 3
20 | #define CDC_STATE_I2C_RXING 4
21 | #define CDC_STATE_SPI_TXSTART 5
22 | #define CDC_STATE_SPI_TXING 6
23 | #define CDC_STATE_SPI_RXING 7
24 | #define CDC_STATE_SPI_TEST 8
25 |
26 | #define CDC_FLAG_NOSTOP 0x80
27 |
28 |
29 | #define LINECODING_ADDR 0xCA
30 | #define LINECODING_SIZE 7
31 | extern_xdatabuf(LINECODING_ADDR, LineCoding);
32 | extern uint32_t CDC_Baud;
33 |
34 |
35 | #define CDC_PUTCHARBUF_LEN 64
36 |
37 | void CDC_InitBaud(void);
38 | void CDC_SetBaud(void);
39 | void CDC_USB_Poll(void);
40 | void CDC_UART_Poll(void);
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/usb_desc.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/usb_desc.c
--------------------------------------------------------------------------------
/usb_desc.h:
--------------------------------------------------------------------------------
1 | #ifndef __USB_DESC_H
2 | #define __USB_DESC_H
3 |
4 | #include "ch554_platform.h"
5 |
6 | // Note: to make the code more structural and human-readable, ideas have been borrowed from:
7 | // https://github.com/libopencm3/libopencm3-examples/blob/master/examples/stm32/f4/stm32f4-discovery/usb_midi/usbmidi.c#L259
8 | // https://github.com/libopencm3/libopencm3/blob/master/include/libopencm3/usb/usbstd.h
9 |
10 | #ifdef __SDCC
11 | #define USB_UINT8(name, val) .name = val
12 | // A Helper to set a 16-bit field in USB descriptors, USB int16s are little-endian (Except USB Attached SCSI)
13 | #define USB_UINT16(name, leVal) .name##L = leVal&0xFF, .name##H = (leVal>>8)&0xFF
14 | #elif defined __C51__
15 | #define USB_UINT8(name,val) val
16 | #define USB_UINT16(name, leVal) leVal&0xFF, (leVal>>8)&0xFF
17 | #endif
18 |
19 | // USB Descriptors
20 | typedef struct _USB_DEVICE_DESCR usb_device_descriptor;
21 | #define USB_DESCSIZE_DEVICE sizeof(usb_device_descriptor)
22 | typedef struct _USB_CONFIG_DESCR usb_config_descriptor_header;
23 | #define USB_DESCSIZE_CONFIG sizeof(usb_config_descriptor)
24 |
25 | //typedef struct usb_config_descriptor_st {
26 | // usb_config_descriptor_header header;
27 | //} usb_config_descriptor;
28 |
29 |
30 | #define USB_INTERFACES 2
31 |
32 | // Common USB Descriptors
33 |
34 | #define USB_DESCSIZE_CONFIG_H 0
35 | #define USB_DESCSIZE_CONFIG_L 75 // Actual size of your CfgDesc, set according to your configuration
36 | // Device Descriptor
37 | extern code const usb_device_descriptor DevDesc;
38 | //extern code const uint8_t DevDesc[];
39 | // Configuration Descriptor, Interface Descriptors, Endpoint Descriptors and ...
40 | extern code const uint8_t CfgDesc[];
41 | // String Descriptors
42 | #define USB_STRINGDESC_COUNT 4 // Number of String Descriptors available
43 | extern code const uint8_t* StringDescs[];
44 |
45 | #endif /* __USB_DESC_H */
46 |
--------------------------------------------------------------------------------
/usb_endp.c:
--------------------------------------------------------------------------------
1 | #include "usb_endp.h"
2 | #include "usb_cdc.h"
3 |
4 | #include "ch554_platform.h"
5 |
6 | #define MAX_PACKET_SIZE 64
7 |
8 | // The buffer (Tx and Rx) must have an even address, size: 64 (0x42)
9 | xdatabuf(EP1_ADDR, Ep1Buffer, 64);
10 | // The buffer (Tx and Rx) must have an even address, size: 128 (0x84)
11 | xdatabuf(EP2_ADDR, Ep2Buffer, EP2_SIZE + EP2_SIZE); // Rx + Tx
12 |
13 | uint8_t USB_EP_HALT_SET(uint8_t ep) {
14 | switch (ep) {
15 | case 0x82:
16 | UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;
17 | return 0;
18 | case 0x02:
19 | UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;
20 | return 0;
21 | case 0x83:
22 | UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;
23 | return 0;
24 | case 0x03:
25 | UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;
26 | return 0;
27 | case 0x81:
28 | UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;
29 | return 0;
30 | default:
31 | return 0xFF;
32 | }
33 | }
34 |
35 | uint8_t USB_EP_HALT_CLEAR(uint8_t ep) {
36 | switch (ep)
37 | {
38 | case 0x82:
39 | UEP2_CTRL = UEP2_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK;
40 | return 0;
41 | case 0x02:
42 | UEP2_CTRL = UEP2_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES) | UEP_R_RES_ACK;
43 | return 0;
44 | case 0x83:
45 | UEP3_CTRL = UEP3_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK;
46 | return 0;
47 | case 0x03:
48 | UEP3_CTRL = UEP3_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES) | UEP_R_RES_ACK;
49 | return 0;
50 | case 0x81:
51 | UEP1_CTRL = UEP1_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK;
52 | return 0;
53 | default:
54 | return 0xFF;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/usb_endp.h:
--------------------------------------------------------------------------------
1 | #ifndef __USB_ENDP_H
2 | #define __USB_ENDP_H
3 |
4 | #include "ch554_platform.h"
5 | uint8_t USB_EP_HALT_SET(uint8_t ep);
6 | uint8_t USB_EP_HALT_CLEAR(uint8_t ep);
7 |
8 | // EP0
9 | #define EP0_ADDR 0x0000
10 | extern_xdatabuf(EP0_ADDR, Ep0Buffer);
11 | void USB_EP0_SETUP(void);
12 | void USB_EP0_IN(void);
13 | void USB_EP0_OUT(void);
14 |
15 | // EP1
16 | #define EP1_ADDR 0x000A
17 | extern_xdatabuf(EP1_ADDR, Ep1Buffer);
18 | void USB_EP1_IN(void);
19 |
20 | // EP2
21 | #define EP2_ADDR 0x004A
22 | extern_xdatabuf(EP2_ADDR, Ep2Buffer);
23 | #define EP2_SIZE 64
24 | #define EP2_RX_BUF (Ep2Buffer)
25 | #define EP2_TX_BUF (Ep2Buffer + EP2_SIZE)
26 | void USB_EP2_IN(void);
27 | void USB_EP2_OUT(void);
28 |
29 | void NOP_Process(void);
30 |
31 | // Out
32 | #define EP0_OUT_Callback USB_EP0_OUT
33 | #define EP1_OUT_Callback NOP_Process
34 | #define EP2_OUT_Callback USB_EP2_OUT
35 | #define EP3_OUT_Callback NOP_Process
36 | #define EP4_OUT_Callback NOP_Process
37 |
38 | // SOF
39 | #define EP0_SOF_Callback NOP_Process
40 | #define EP1_SOF_Callback NOP_Process
41 | #define EP2_SOF_Callback NOP_Process
42 | #define EP3_SOF_Callback NOP_Process
43 | #define EP4_SOF_Callback NOP_Process
44 |
45 | // IN
46 | #define EP0_IN_Callback USB_EP0_IN
47 | #define EP1_IN_Callback USB_EP1_IN
48 | #define EP2_IN_Callback USB_EP2_IN
49 | #define EP3_IN_Callback NOP_Process
50 | #define EP4_IN_Callback NOP_Process
51 |
52 | // SETUP
53 | #define EP0_SETUP_Callback USB_EP0_SETUP
54 | #define EP1_SETUP_Callback NOP_Process
55 | #define EP2_SETUP_Callback NOP_Process
56 | #define EP3_SETUP_Callback NOP_Process
57 | #define EP4_SETUP_Callback NOP_Process
58 |
59 | #endif /*__USB_ENDP_H*/
60 |
--------------------------------------------------------------------------------
/usb_ep0.c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikka0w0/CH55x_USB_CDC/b8811ad3a681cdea571ef0e45942b5a60996f336/usb_ep0.c
--------------------------------------------------------------------------------
/usb_it.c:
--------------------------------------------------------------------------------
1 | #include "ch554_platform.h"
2 | #include "usb_desc.h"
3 | #include "usb_endp.h"
4 |
5 | void NOP_Process(void) {}
6 |
7 | // See CH554 datasheet page 42
8 | code const void (*pEndPoint_OUT_CallBack[])(void) =
9 | {
10 | EP0_OUT_Callback,
11 | EP1_OUT_Callback,
12 | EP2_OUT_Callback,
13 | EP3_OUT_Callback,
14 | EP4_OUT_Callback,
15 | };
16 |
17 | code const void (*pEndPoint_SOF_CallBack[])(void) =
18 | {
19 | EP0_SOF_Callback,
20 | EP1_SOF_Callback,
21 | EP2_SOF_Callback,
22 | EP3_SOF_Callback,
23 | EP4_SOF_Callback,
24 | };
25 |
26 | code const void (*pEndPoint_IN_CallBack[])(void) =
27 | {
28 | EP0_IN_Callback,
29 | EP1_IN_Callback,
30 | EP2_IN_Callback,
31 | EP3_IN_Callback,
32 | EP4_IN_Callback,
33 | };
34 |
35 | code const void (*pEndPoint_SETUP_CallBack[])(void) =
36 | {
37 | EP0_SETUP_Callback,
38 | EP1_SETUP_Callback,
39 | EP2_SETUP_Callback,
40 | EP3_SETUP_Callback,
41 | EP4_SETUP_Callback,
42 | };
43 |
44 | void USBInterrupt(void) {
45 | if(UIF_TRANSFER) {
46 | // Dispatch to service functions
47 | switch (USB_INT_ST & MASK_UIS_TOKEN) {
48 | case UIS_TOKEN_OUT:
49 | (*pEndPoint_OUT_CallBack[USB_INT_ST & MASK_UIS_ENDP])();
50 | break;
51 | case UIS_TOKEN_SOF:
52 | (*pEndPoint_SOF_CallBack[USB_INT_ST & MASK_UIS_ENDP])();
53 | break;
54 | case UIS_TOKEN_IN:
55 | (*pEndPoint_IN_CallBack[USB_INT_ST & MASK_UIS_ENDP])();
56 | break;
57 | case UIS_TOKEN_SETUP:
58 | (*pEndPoint_SETUP_CallBack[USB_INT_ST & MASK_UIS_ENDP])();
59 | break;
60 | }
61 |
62 | UIF_TRANSFER = 0; // Clear interrupt flag
63 | }
64 |
65 | // Device mode USB bus reset
66 | if(UIF_BUS_RST) {
67 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
68 | UEP1_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK;
69 | UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
70 | UEP3_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
71 | USB_DEV_AD = 0x00;
72 | UIF_SUSPEND = 0;
73 | UIF_TRANSFER = 0;
74 | UIF_BUS_RST = 0; // Clear interrupt flag
75 | }
76 |
77 | // USB bus suspend / wake up
78 | if (UIF_SUSPEND) {
79 | UIF_SUSPEND = 0;
80 | if ( USB_MIS_ST & bUMS_SUSPEND ) { // Suspend
81 |
82 | // while ( XBUS_AUX & bUART0_TX ); // Wait for Tx
83 | // SAFE_MOD = 0x55;
84 | // SAFE_MOD = 0xAA;
85 | // WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO; // Wake up by USB or RxD0
86 | // PCON |= PD; // Chip sleep
87 | // SAFE_MOD = 0x55;
88 | // SAFE_MOD = 0xAA;
89 | // WAKE_CTRL = 0x00;
90 |
91 | } else { // Unexpected interrupt, not supposed to happen !
92 | USB_INT_FG = 0xFF; // Clear interrupt flag
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/usb_string_desc.c:
--------------------------------------------------------------------------------
1 | #include "ch554_platform.h"
2 | #include "usb_desc.h"
3 |
4 | // Language Descriptor
5 | code const uint8_t LangDesc[] = {
6 | 4, 0x03, // Length = 4 bytes, String Descriptor (0x03)
7 | 0x09, 0x04 // 0x0409 English - United States
8 | };
9 |
10 | // String Descriptors:
11 |
12 | code const uint8_t DevName1[] = {
13 | 20, 0x03, // Length = 20 bytes, String Descriptor (0x03)
14 | 'C', 0, 'H', 0, '5', 0, '5', 0, '4', 0, ' ', 0, 'C', 0, 'D', 0, 'C', 0
15 | };
16 |
17 | code const uint8_t ProductName[] = {
18 | 38, 0x03, // Length = 38 bytes, String Descriptor (0x03)
19 | 'R', 0, 'i', 0, 'k', 0, 'k', 0, 'a', 0, '`', 0, 's', 0, ' ', 0, 'C', 0, 'H', 0, '5', 0, '5', 0, '4', 0, ' ', 0, 'D', 0, 'e', 0, 'm', 0, 'o', 0
20 | };
21 |
22 | code const uint8_t ManuName[] = {
23 | 18, 0x03, // Length = 18 bytes, String Descriptor (0x03)
24 | 'R', 0, 'i', 0, 'k', 0, 'k', 0, 'a', 0, '0', 0, 'w', 0, '0', 0
25 | };
26 |
27 | code const uint8_t* StringDescs[USB_STRINGDESC_COUNT] = {
28 | LangDesc, // 0 (If you want to support string descriptors, you must have this!)
29 | ProductName, // 1
30 | ManuName, // 2
31 | DevName1 // 3
32 | };
33 |
--------------------------------------------------------------------------------