Compare commits

..

61 Commits

Author SHA1 Message Date
Mikael Ågren
3cd2f6c2b5
Merge b02c2d67d6450cd1bea6942d293a6f6ea8a607f1 into d2c7fb0ba9b0cb11791c94b38d17372899479d6a 2025-02-13 08:30:43 +00:00
Mikael Ågren
b02c2d67d6
PoC: fpga/tb: Allow access to syscall irq trigger area 2025-02-13 09:12:07 +01:00
Mikael Ågren
1968b3614c
PoC: tb: Check security monitor read access protection 2025-02-13 09:12:06 +01:00
Mikael Ågren
0cc991fea2
PoC: fpga: Revert back to 21 MHz
To avoid having to find a new nextpnr seed, for small changes, during
development
2025-02-12 17:23:26 +01:00
Mikael Ågren
d65e1eec4e
PoC: fpga: Update next-pnr seed to reach 24 MHz 2025-02-12 16:40:26 +01:00
Mikael Ågren
a68b646edf
PoC: testapp: Call reset syscall 2025-02-12 16:40:25 +01:00
Mikael Ågren
e4df068bb4
PoC: testapp: Call syscall accessing SPI flash 2025-02-12 16:40:25 +01:00
Mikael Ågren
e5e2ab2787
PoC: testfw: Check that SPI flash is available in firmware mode 2025-02-12 16:40:25 +01:00
Mikael Ågren
cbc7adf706
PoC: Integrate spi and flash code 2025-02-12 16:40:24 +01:00
Daniel Jobson
12c23cc149
PoC: fw: Import spi.[ch] and flash.[ch] 2025-02-12 16:40:24 +01:00
Mikael Ågren
b45489730a
PoC: testfw: Break out tests running in app mode into separate app
App mode can no longer be controlled from software. So the tests have to
run from firmware RAM.
2025-02-12 16:40:24 +01:00
Mikael Ågren
6c439b3a4f
PoC: testfw: Remove blake2s test
Removing the blake2s test since the possibility for the firmware to
expose a blake2s function to the app has been removed.
2025-02-12 16:40:23 +01:00
Mikael Ågren
f686c59e03
PoC: fw: Add experimental syscalls to firmware
Adds:
- SYSCALL_RESET
- SYSCALL_SET_LED
2025-02-12 16:40:23 +01:00
Mikael Ågren
1e959bebb6
PoC: tb: Expand existing tests with access checks in app mode and syscalls
Checks availability of:
- CDI
- UDI
- RAM
- SPI
2025-02-12 16:40:23 +01:00
Mikael Ågren
4a27940bf1
PoC: tb: Fix tb_tk1 test10 (SPI loop back test)
Fix test10. It broke while implementing interrupt based syscalls.

Cleaning up after the previous test. We reset the memory bus to a known
idle state. We also reset the DUT to make the SPI master visible.
2025-02-12 11:08:31 +01:00
Mikael Ågren
d07abc7ad2
PoC: tb: Fix tb_tk1 test5 (APP_START/APP_SIZE)
Fix test1. It broke while implementing interrupt based syscalls.

Instead of writing to ADDR_SYSTEM_MODE_CTRL, app mode is now entered
automatically when executing outside of ROM.
2025-02-12 11:08:31 +01:00
Mikael Ågren
fe16cc9f72
PoC: tb: Fix tb_tk1 test3 (CDI)
Fix test1. It broke while implementing interrupt based syscalls.

Instead of writing to ADDR_SYSTEM_MODE_CTRL, app mode is now entered
automatically when executing outside of ROM.
2025-02-12 11:08:30 +01:00
Mikael Ågren
e9f72a8530
PoC: tb: Add fetch instruction helper task to tb_tk1 2025-02-12 11:08:30 +01:00
Mikael Ågren
ed10222999
PoC: tb: Remove tb_tk1 blake2s test
Removing the blake2s test since the blake2s registers are removed.
2025-02-12 11:08:30 +01:00
Mikael Ågren
1179324f10
PoC: tb: Update tk1 test bench with new ports
Fixing tests that broke when adding interrupt based syscalls
2025-02-12 11:08:29 +01:00
Mikael Ågren
43239759e6
tb: Display errors in tb_tk1 even if DEBUG is 0
Always display errors to make them easy to find and troubleshoot.
2025-02-12 11:08:29 +01:00
Mikael Ågren
4532bec84d
PoC: tb: Write data only once per call to write_word() in tb_tk1
Keep WE and CS high for one clock cycle instead of two. To avoid writing
the same address twice.
2025-02-12 11:08:29 +01:00
Mikael Ågren
a9484d9cf4
PoC: Remove IRQ30 from fw/irqpoc_c_example
Removing IRQ30 since it us no longer exist
2025-02-12 11:08:28 +01:00
Mikael Ågren
91625c05bb
PoC: Remove IRQ30 from fw/irqpoc_with_app
Removing IRQ30 since it us no longer exist
2025-02-12 11:08:28 +01:00
Mikael Ågren
38b029f1c4
PoC: Remove IRQ30 from fw/irqpoc_led_toggle
Removing IRQ30 since it us no longer exist
2025-02-12 11:08:28 +01:00
Mikael Ågren
7f718b298b
PoC: Remove IRQ30 from fw/irqpoc
Removing IRQ30 since it us no longer exist
2025-02-12 11:08:27 +01:00
Daniel Jobson
833bf63bc8
PoC: Make sensitive assets only readable/writable before system_mode is set
After the first time system_mode is set to one, the assets will no
longer be read- or writeable, even if system_mode is set to zero at a
later syscall. This is to make sure syscalls does not have the same
privilege as the firmware has at first boot.

We need to monitor when system_mode is set to one, otherwise we might
accedentially lock the assets before actually leaving firmware, for
example if firmware would use a function set in any of the registers
used in system_mode_ctrl.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-02-12 11:08:27 +01:00
Mikael Ågren
eacfd6eddc
PoC: Remove low privilege syscall 2025-02-12 11:08:27 +01:00
Daniel Jobson
beb325b683
PoC: Deny access to the SPI master in app mode
Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-02-12 11:08:26 +01:00
Mikael Ågren
2e1925555d
PoC: Add example firmware with embedded that calls syscalls implemented in C
App is embedded in firmware and is loaded into app RAM when firmware
starts.
App continuously calls SET_LED syscalls.

Simulation: `make tb_application_fpga_irqpoc_c_example`
2025-02-12 11:08:26 +01:00
Mikael Ågren
e1d7608897
PoC: Control access to FW RAM
Allow FW RAM access only in the following execution contexts:
- Firmware mode
- IRQ_SYSCALL_HI

Input port `system_mode` of the `fw_ram` module is replaced with an
enable port. Since access to FW RAM not longer depend only on
system_mode
2025-02-12 11:08:26 +01:00
Mikael Ågren
0183f25170
PoC: Add basic syscall example firmware
Adds a basic example firmware that copies an app to app RAM. The app
triggers syscall interrupts and tries to execute ROM code from app mode.

A make target (`tb_application_fpga_irqpoc_with_app`) that simulates a
Tkey running the firmware is added.
2025-02-12 11:08:25 +01:00
Mikael Ågren
89c77ca4de
PoC: Trap when executing from ROM in app mode
Only allow executing from ROM when in one of the following execution
contexts:
- Firmware mode
- IRQ_SYSCALL_LO
- IRQ_SYSCALL_HI

Co-authored-by: Daniel Jobson <jobson@tillitis.se>
2025-02-12 11:08:25 +01:00
Mikael Ågren
cd959e9966
PoC: Remove Blake2s register 2025-02-12 11:08:25 +01:00
Daniel Jobson
e18eb03c4f
PoC: Automatically control system_mode in hardware
Instead of manually switching to app mode using the system mode
register, app mode will be enabled when executing outside of firmware
ROM.

Co-authored-by: Mikael Ågren <mikael@tillitis.se>
2025-02-12 11:08:24 +01:00
Mikael Ågren
5dfe549969
PoC: Add LED toggling interrupt example
Add example firmware for demoing interrupts on Tkey hardware.
2025-02-12 11:08:24 +01:00
Mikael Ågren
5e15b40a86
PoC: PicoRV32 interrupts
A proof-of-concept of enabling PicoRV32 interrupts. Two interrupt
sources, which can be triggered by writes to memory addresses, are
added.  The design has only been simulated, not run on hardware.

Synthesis:

Ice40 LC utilization is 93% (4934/5280) when built using tkey-builder:4

Simulation:

A `tb_application_fpga_irqpoc` target is added. Running `make
tb_application_fpga_irqpoc` creates `tb_application_fpga_sim.fst` which
can be inspected in GTKWave or Surfer.

Firmware:

A simple firmware is added in `fw/irqpoc`. It enables both interrupts
and triggers each interrupt once.

Custom PicoRV32 instructions are located in `custom_ops.S`. It is
imported from upstream PicoRV32 commit:
70f3c33ac8
2025-02-12 11:08:15 +01:00
Michael Cardell Widerkrantz
d2c7fb0ba9
doc: Update firmware README to include USB Mode Protocol
+ minor link and typo fixes.
2025-02-11 15:21:02 +01:00
Michael Cardell Widerkrantz
179c13e9bf
build: Update digests of firmware and bitstream 2025-02-11 14:40:01 +01:00
Michael Cardell Widerkrantz
050e0f2673
fpga: Format Verilog 2025-02-11 14:37:29 +01:00
Michael Cardell Widerkrantz
aedd6102ea
testfw: Add support for USB Mode Protocol 2025-02-11 14:10:57 +01:00
Michael Cardell Widerkrantz
f68414c4aa
ci: Include Verilog formatting check in CI
- Change checkfmt make target to run both Verilog formatting check and
  C code formatting check.

- Make check formatting it's own job in the CI.
2025-02-11 13:50:08 +01:00
Michael Cardell Widerkrantz
75ad033e03
build: Add -Wno-GENUNNAMED to LINT_FLAGS
For ages we have had a comment saying:

  For Verilator 5.019 -Wno-GENUNNAMED needs to be added to LINT_FLAGS for the
  cell library.

With the new tkey-builder we have 5.028, so it's time to apply this flag.
2025-02-11 13:50:08 +01:00
Michael Cardell Widerkrantz
05bb999759
build/ci: Use new tkey-builder
Use the release candidate for tkey-builder:5
2025-02-11 13:50:07 +01:00
Michael Cardell Widerkrantz
81ac7bffa0
podman/docker: Run bash as login shell
To get bash to source /etc/profile and get the goodness of
/etc/profile/bash_completion.sh, run bash as a login shell.
2025-02-11 13:50:07 +01:00
Michael Cardell Widerkrantz
bb18d5b9e9
toolchain: Introduce buildtools.sh script
Instead of repeated RUNs in Dockerfile, move the entire build of
specific tools to a script.

- Make commands more shell script-like.
- icestorm: Make sure we checkout the right commit.
- Add checks for the right digest for all git clones, so no history
  has been changed.
- Add digest file and check for the downloaded tarball.
2025-02-11 13:50:07 +01:00
Michael Cardell Widerkrantz
8ed16fff6a
docs: Add Castor release notes so far
Breaking change! The introduction of the USB Controller Protocol means
we have a breaking change that makes device apps unable to
communicate.
2025-02-11 13:50:06 +01:00
Jonas Thörnblad
c292595ee3
ch552: Raise UART IRQ priority and tune USB polling period
Set UART1 IRQ to high priority to not miss any incoming bytes
and tune USB polling period (bInterval).
2025-02-11 13:50:06 +01:00
Jonas Thörnblad
361890042a
ch552: Update USB polling period
Update USB polling period (bInterval) for CDC, HID and TKEYCTRL
endpoints.
2025-02-11 13:50:06 +01:00
Jonas Thörnblad
5029eb1d39
ch552: Fix CDC configuration problem on Windows
Fix CDC configuration problem on Windows when we have a composite
device (multiple different Device Classes). Add "Interface Association
Descriptor" to make it work.
2025-02-11 13:50:05 +01:00
Jonas Thörnblad
04ec938200
ch552: Add new USB debug pipe (TKEYCTRL)
Make the CH552 present a new HID endpoint used for debug data.
2025-02-11 13:50:05 +01:00
Jonas Thörnblad
bfc43093ec
fpga: Fix bitrate counter bug
Fix off-by-one UART bitrate counter value that will make the RX
sampling and TX sending drift. The impact gets higher as the baudrate
increases and the bitrate counter value gets smaller.
2025-02-11 13:50:05 +01:00
Jonas Thörnblad
07dc20e4e1
fpga/testfw: Update clock frequency to 24 MHz
Reconfigure the baudrate to keep 500 kbaud.

Correct a forgotten test in testfw that wasn't updated the last time
frequency was raised in commit
75b028505f0d6dc685d37b84d73ddb9db5ee7ea2 in June 17, 2024.
2025-02-11 13:50:04 +01:00
Jonas Thörnblad
0a634c76da
ch552: Use the new hardware CTS signals for UART access
- Use CTS signals to let the FPGA and CH552 signal each other that
    it is OK send UART data.
  - Update the CH552 rx and frame handling logic.
  - Fix minor spelling errors and indentation
2025-02-11 13:50:04 +01:00
Jonas Thörnblad
ab4ef5fdf9
fpga: Introduce CTS signals for UART
Add incoming and outgoing CTS (Clear To Send) signals for the FPGA to
let the CH552 and FPGA signal each other that it is OK to send UART
data. The CTS signals indicate "OK to send" if high. If an incoming
CTS signal goes low, the receiver of that signal should immediatly
stop sending UART data.
2025-02-11 13:50:04 +01:00
Mikael Ågren
f3706dcfcc
fpga: Increase UART baud rate to 500k 2025-02-11 13:50:03 +01:00
Mikael Ågren
a0c031eb25
fw: Minimal CDC implementation of new framing protocol
Throwing away mode and length from incoming data. Adding mode and
length to outgoing data.

Splitting responses into frames small enough for the USB<->UART
transceiver to handle.
2025-02-11 13:50:03 +01:00
Mikael Ågren
1b9bbc4eba
ch552: Wrap accesses to UART output buffers 2025-02-06 16:20:34 +01:00
Jonas Thörnblad
b443359e9c
ch552: Add USB HID and protocol support over UART
- Add USB HID support.
- Introduce a small protocol to distinguish between CDC and HID data
  sent over the UART.
- Add some debug printing.
- Cleanup of code and formatting.
2025-02-06 16:20:34 +01:00
Jonas Thörnblad
90fca5d3dd
ch552: Move usb_strings.h to the include directory 2025-02-06 16:20:34 +01:00
Jonas Thörnblad
0af82ee566
fpga/fw: Extend checks for invalid memory accesses
- Extend hardware checks for invalid memory accesses to include
  checking more address space.

- In fw include file: fix two typos for memory ranges that relates to
  above that fortunately have no impact on functionality.
2025-02-06 16:16:46 +01:00
41 changed files with 3432 additions and 1476 deletions

View File

@ -10,10 +10,10 @@ on:
workflow_dispatch: {}
jobs:
check-firmware:
check-formatting:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:4
image: ghcr.io/tillitis/tkey-builder:5rc1
steps:
- name: checkout
uses: actions/checkout@v4
@ -26,11 +26,26 @@ jobs:
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: check indentation in firmware C code
- name: check formatting on Verilog and C
working-directory: hw/application_fpga
run: |
make -C fw/tk1 checkfmt
make -C fw/testfw checkfmt
make checkfmt
check-firmware:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:5rc1
steps:
- name: checkout
uses: actions/checkout@v4
with:
# fetch-depth: 0
persist-credentials: false
- name: fix
# https://github.com/actions/runner-images/issues/6775
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: run static analysis on firmware C code
working-directory: hw/application_fpga
@ -44,7 +59,7 @@ jobs:
check-verilog:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:4
image: ghcr.io/tillitis/tkey-builder:5rc1
steps:
- name: checkout
uses: actions/checkout@v4
@ -64,7 +79,7 @@ jobs:
build-usb-firmware:
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:4
image: ghcr.io/tillitis/tkey-builder:5rc1
steps:
- name: checkout
uses: actions/checkout@v4
@ -86,7 +101,7 @@ jobs:
commit_sha: ${{ github.sha }}
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:4
image: ghcr.io/tillitis/tkey-builder:5rc1
steps:
- name: checkout
uses: actions/checkout@v4
@ -115,7 +130,7 @@ jobs:
needs: build-bitstream
runs-on: ubuntu-latest
container:
image: ghcr.io/tillitis/tkey-builder:4
image: ghcr.io/tillitis/tkey-builder:5rc1
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@ -12,6 +12,7 @@ RUN apt-get -qq update -y \
clang-format \
clang-tidy \
cmake \
curl \
flex \
g++ \
gawk \
@ -57,109 +58,12 @@ RUN apt-get -qq update -y \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
# Enable bash completion
RUN sed -i '/#if ! shopt -oq posix; then/ s/^#//' /etc/bash.bashrc
RUN sed -i '/# if \[ -f \/usr\/share\/bash-completion\/bash_completion \]; then/ s/^#//' /etc/bash.bashrc
RUN sed -i '/# . \/usr\/share\/bash-completion\/bash_completion/ s/^#//' /etc/bash.bashrc
RUN sed -i '/# elif \[ -f \/etc\/bash_completion \]; then/ s/^#//' /etc/bash.bashrc
RUN sed -i '/# . \/etc\/bash_completion/ s/^#//' /etc/bash.bashrc
RUN sed -i '/# fi/ s/^#//' /etc/bash.bashrc
RUN sed -i '/#fi/ s/^#//' /etc/bash.bashrc
FROM base as toolsbuilder
RUN git clone --depth=1 https://github.com/YosysHQ/icestorm /src
WORKDIR /src
RUN git checkout 738af822905fdcf0466e9dd784b9ae4b0b34987f \
&& make -j$(nproc --ignore=2) \
&& make install \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-icestorm
WORKDIR /
RUN rm -rf /src
COPY buildtools.sh /buildtools.sh
COPY verible.sha512 /verible.sha512
# Custom iceprog for the RPi 2040-based programmer (will be upstreamed).
RUN git clone -b interfaces --depth=1 https://github.com/tillitis/icestorm /src
WORKDIR /src/iceprog
RUN make -j$(nproc --ignore=2) \
&& make PROGRAM_PREFIX=tillitis- install \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-tillitis--icestorm
WORKDIR /
RUN rm -rf /src
RUN git clone -b 0.45 --depth=1 https://github.com/YosysHQ/yosys /src
WORKDIR /src
RUN git submodule update --init \
&& make -j$(nproc --ignore=2) \
&& make install \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-yosys
WORKDIR /
RUN rm -rf /src
RUN git clone -b nextpnr-0.7 https://github.com/YosysHQ/nextpnr /src
WORKDIR /src
# Add "Fix handling of RNG seed" #1369
RUN git cherry-pick --no-commit 6ca64526bb18ace8690872b09ca1251567c116de
# Add early exit if place fails on timing
RUN sed -i \
'345i \ \ \ \ general.add_options()("exit-on-failed-target-frequency",' \
common/kernel/command.cc
RUN sed -i \
'346i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "exit if target frequency is not achieved (use together with "' \
common/kernel/command.cc
RUN sed -i \
'347i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "--randomize-seed option)");' \
common/kernel/command.cc
RUN sed -i \
'348i \\' \
common/kernel/command.cc
RUN sed -i \
'662s/if (do_route) {/if (do_route \&\& (vm.count("exit-on-failed-target-frequency") ? !had_nonfatal_error : true)) {/' \
common/kernel/command.cc
RUN sed -i \
'244s/bool warn_on_failure = false/bool warn_on_failure = true/' \
common/kernel/timing.h
RUN cmake -DARCH=ice40 . \
&& make -j$(nproc --ignore=2) \
&& make install \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-nextpnr
WORKDIR /
RUN rm -rf /src
RUN git clone -b v12_0 --depth=1 https://github.com/steveicarus/iverilog /src
WORKDIR /src
RUN sh autoconf.sh \
&& ./configure \
&& make -j$(nproc --ignore=2) \
&& make install \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-iverilog
WORKDIR /
RUN rm -rf /src
RUN git clone -b v5.028 --depth=1 https://github.com/verilator/verilator /src
WORKDIR /src
RUN autoconf \
&& ./configure \
&& make -j$(nproc --ignore=2) \
&& make test \
&& make install \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-verilator
WORKDIR /
RUN rm -rf /src
ADD https://github.com/chipsalliance/verible/releases/download/v0.0-3795-gf4d72375/verible-v0.0-3795-gf4d72375-linux-static-x86_64.tar.gz /src/verible.tar.gz
WORKDIR /src
RUN tar xvf verible.tar.gz
RUN mv -v verible*/bin/* /usr/local/bin
RUN verible-verilog-format --version | head -1 > /usr/local/repo-commit-verible
WORKDIR /
RUN rm -rf /src
RUN git clone -b v1.9.1 https://github.com/cocotb/cocotb.git /src
WORKDIR /src
RUN pip install . --break-system-packages \
&& git describe --all --always --long --dirty > /usr/local/repo-commit-cocotb
WORKDIR /
RUN rm -rf /src
RUN /buildtools.sh
FROM base
LABEL org.opencontainers.image.description="Toolchain for building TKey FPGA bitstream"

View File

@ -5,7 +5,7 @@
BUILDIMAGE=tkey-builder-local
# default image used when running a container
IMAGE=ghcr.io/tillitis/tkey-builder:4
IMAGE=ghcr.io/tillitis/tkey-builder:5rc1
all:
@echo "Targets:"
@ -23,11 +23,11 @@ all:
run:
podman run --rm --mount type=bind,source="`pwd`/../",target=/build -w /build -it \
$(IMAGE) /usr/bin/bash
$(IMAGE) /usr/bin/bash -l
docker-run:
docker run --rm --mount type=bind,source="`pwd`/../",target=/build -w /build -it \
$(IMAGE) /usr/bin/bash
$(IMAGE) /usr/bin/bash -l
run-make:
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \

134
contrib/buildtools.sh Executable file
View File

@ -0,0 +1,134 @@
#! /bin/sh -e
# Copyright (C) 2025 Tillitis AB
# SPDX-License-Identifier: GPL-2.0-only
## Build the specific versions of the tools we need to build the TKey
## FPGA bitstream and apps.
cd /
mkdir src
# ----------------------------------------------------------------------
# Project icestorm
# ----------------------------------------------------------------------
git clone https://github.com/YosysHQ/icestorm /src/icestorm
cd /src/icestorm
# No tags or releases yet. Pin down to a specific commit.
git checkout 738af822905fdcf0466e9dd784b9ae4b0b34987f
make -j$(nproc --ignore=2)
make install
git describe --all --always --long --dirty > /usr/local/repo-commit-icestorm
# ----------------------------------------------------------------------
# Our own custom iceprog for the RPi 2040-based programmer. Will be
# upstreamed.
# ----------------------------------------------------------------------
git clone -b interfaces --depth=1 https://github.com/tillitis/icestorm /src/icestorm-tillitis
cd /src/icestorm-tillitis/iceprog
make -j$(nproc --ignore=2)
make PROGRAM_PREFIX=tillitis- install
git describe --all --always --long --dirty > /usr/local/repo-commit-tillitis--icestorm
# ----------------------------------------------------------------------
# yosys
# ----------------------------------------------------------------------
git clone -b 0.45 --depth=1 https://github.com/YosysHQ/yosys /src/yosys
cd /src/yosys
# Make sure the digest is correct and no history has changed
git checkout 9ed031ddd588442f22be13ce608547a5809b62f0
git submodule update --init
make -j$(nproc --ignore=2)
make install
git describe --all --always --long --dirty > /usr/local/repo-commit-yosys
# ----------------------------------------------------------------------
# nextpnr
# ----------------------------------------------------------------------
git clone -b nextpnr-0.7 https://github.com/YosysHQ/nextpnr /src/nextpnr
cd /src/nextpnr
# Make sure the digest is correct and no history has changed
git checkout 73b7de74a5769095acb96eb6c6333ffe161452f2
# Add "Fix handling of RNG seed" #1369
git cherry-pick --no-commit 6ca64526bb18ace8690872b09ca1251567c116de
# Add early exit if place fails on timing
sed -i \
'345i \ \ \ \ general.add_options()("exit-on-failed-target-frequency",' \
common/kernel/command.cc
sed -i \
'346i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "exit if target frequency is not achieved (use together with "' \
common/kernel/command.cc
sed -i \
'347i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ "--randomize-seed option)");' \
common/kernel/command.cc
sed -i \
'348i \\' \
common/kernel/command.cc
sed -i \
'662s/if (do_route) {/if (do_route \&\& (vm.count("exit-on-failed-target-frequency") ? !had_nonfatal_error : true)) {/' \
common/kernel/command.cc
sed -i \
'244s/bool warn_on_failure = false/bool warn_on_failure = true/' \
common/kernel/timing.h
cmake -DARCH=ice40 .
make -j$(nproc --ignore=2)
make install
git describe --all --always --long --dirty > /usr/local/repo-commit-nextpnr
# ----------------------------------------------------------------------
# icarus verilog
# ----------------------------------------------------------------------
git clone -b v12_0 --depth=1 https://github.com/steveicarus/iverilog /src/iverilog
cd /src/iverilog
# Make sure the digest is correct and no history has changed
git checkout 4fd5291632232fbe1ba49b2c26bb6b2bf1c6c9cf
sh autoconf.sh
./configure
make -j$(nproc --ignore=2)
make install
git describe --all --always --long --dirty > /usr/local/repo-commit-iverilog
# ----------------------------------------------------------------------
# verilator
# ----------------------------------------------------------------------
git clone -b v5.028 --depth=1 https://github.com/verilator/verilator /src/verilator
cd /src/verilator
# Make sure the digest is correct and no history has changed
git checkout 8ca45df9c75c611989ae5bfc4112a32212c3dacf
autoconf
./configure
make -j$(nproc --ignore=2)
make test
make install
git describe --all --always --long --dirty > /usr/local/repo-commit-verilator
# ----------------------------------------------------------------------
# verible
# ----------------------------------------------------------------------
curl --output /src/verible.tar.gz -L https://github.com/chipsalliance/verible/releases/download/v0.0-3795-gf4d72375/verible-v0.0-3795-gf4d72375-linux-static-x86_64.tar.gz
# Check against the expected digest
sha512sum -c /verible.sha512
cd /src
tar xvf verible.tar.gz
mv -v verible*/bin/* /usr/local/bin
verible-verilog-format --version | head -1 > /usr/local/repo-commit-verible
# ----------------------------------------------------------------------
# cocotb
# ----------------------------------------------------------------------
git clone -b v1.9.1 https://github.com/cocotb/cocotb.git /src/cocotb
cd /src/cocotb
pip install . --break-system-packages
git describe --all --always --long --dirty > /usr/local/repo-commit-cocotb

1
contrib/verible.sha512 Normal file
View File

@ -0,0 +1 @@
3e997b8cd494556fa107b96a6daa4e51133208a85b3c0250c0223d7194aedbc98b3f5213fedaee083edd96c317e50057aa9cdc0517197f4638be3834133e2c9f /src/verible.tar.gz

View File

@ -2,6 +2,104 @@
Descriptions of the tagged TKey releases.
## Upcoming release: Castor
Overview of changes since TK TK1-24.03 for the Castor milestone so
far.
**Note well**: BREAKING CHANGE! The introduction of the USB Controller
Protocol betwen the programs running on the PicoRV32 CPU and the CH552
means that device apps that have not been changed to use the protocol
will not have any way to communicate with the outside world.
### General
- Split repo:
- tk1, mta1-usb-dev, mta-usb-v1 and mta1-library moves to
https://github.com/tillitis/tk1-pcba
- tp1, mta1-usb-programmer, mta1-library and KiCad-RP Pico moves to
https://github.com/tillitis/tp1
For full change log [see](https://github.com/tillitis/tillitis-key1/compare/TK1-23.03.2...coming-tag)
### FPGA
- Security Monitor memory access checks are now more complete.
- Add SPI main controller mainly to access flash.
- Add system reset API. Device apps can reset the system and restart
the firmware. The FPGA is not reset.
- Increase clock frequence to 24 MHz.
- Increase UART baudrate to 500,000.
- Fix missing clock cycles in timer core.
- Remove the UART runtime configuration API.
- Several clean ups and testbench changes.
- Make Verilator simulation work again.
- Add hardware clear to send (CTS) signals for communication between
UART and CH552.
### Firmware
- At startup, fill RAM with random data using the xorwow PRNG, seeded
by TRNG.
- Add support for the new USB Controller Protocol to communicate with
different endpoints.
### CH552
- Use the new CTS signals for communication over the UART.
- Add support for two HID endpoints.
- Add protocol to communicate with the three different endpoints: CDC,
HID, debug.
- Change USB frame sending from a software timer to instead be
controlled by the USB Controller Protocol.
### tkey-builder
- New versions of:
- clang (18.1.3, part of ubuntu 24.04)
- icestorm (commit 738af822905fdcf0466e9dd784b9ae4b0b34987f
)
- yosys (0.45)
- nextpnr (0.7) + extra patches for RNG seed handling and early exit
- iverilog (v12)
- verilator (v5.028)
- verible (v0.0-3795)
- cocotb (v1.9.1)
- Remove TKey Programmer (TP) toolchain:
- gcc-arm-none-eabi: Used for the TKey Programmer firmware, now
moved to it's own repo.
- libnewlib-arm-none-eabi
- libstdc++-arm-none-eabi-newlib
- pico-sdk
TP1 is now in https://github.com/tillitis/tp1
- Remove Go compiler support.
### Docs
- All docs now in READMEs close to the design or code.
- Protocol docs moved to [the Developer
Handbook](https://dev.tillitis.se/)
[repo](https://github.com/tillitis/dev-tillitis)
## TK1-24.03

View File

@ -147,6 +147,7 @@ TESTFW_OBJS = \
$(P)/fw/testfw/main.o \
$(P)/fw/testfw/start.o \
$(P)/fw/tk1/proto.o \
$(P)/fw/tk1/assert.o \
$(P)/fw/tk1/lib.o \
$(P)/fw/tk1/spi.o \
$(P)/fw/tk1/flash.o
@ -309,7 +310,8 @@ LINT_FLAGS = \
-Wno-WIDTHEXPAND \
-Wno-UNOPTFLAT \
--timescale 1ns/1ns \
-DNO_ICE40_DEFAULT_ASSIGNMENTS
-DNO_ICE40_DEFAULT_ASSIGNMENTS \
-Wno-GENUNNAMED
lint: $(FPGA_VERILOG_SRCS) \
$(SIM_VERILOG_SRCS) \
@ -351,6 +353,8 @@ fmt: $(FPGA_VERILOG_SRCS) $(SIM_VERILOG_SRCS) $(VERILATOR_VERILOG_SRCS) $(VERILO
# Temporary fix using grep, since the verible with --verify flag only returns
# error if the last file is malformatted.
checkfmt: $(FPGA_VERILOG_SRCS) $(SIM_VERILOG_SRCS) $(VERILATOR_VERILOG_SRCS) $(VERILOG_SRCS)
make -C fw/tk1 checkfmt
make -C fw/testfw checkfmt
$(FORMAT) $(CHECK_FORMAT_FLAGS) $^ 2>&1 | \
grep "Needs formatting" && exit 1 || true
.PHONY: checkfmt
@ -415,6 +419,7 @@ synth.json: $(FPGA_VERILOG_SRCS) $(VERILOG_SRCS) $(PICORV32_SRCS) bram_fw.hex
application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE)
$(NEXTPNR_PATH)nextpnr-ice40 \
-l application_fpga_par.txt \
--seed 4127945014473118301 \
--freq $(TARGET_FREQ) \
--ignore-loops \
--up5k \

View File

@ -1 +1 @@
44086edb70377991b57d3f1c231f743fcf0c2c9d2303843ec133f76cc42449a8 application_fpga.bin
93e311e4bfa7e2f8c3c89f194b5fbe7b83eff81e6d32fd73c8859d5d76324b48 application_fpga.bin

View File

@ -152,8 +152,9 @@ ADDR_CPU_MON_LAST: 0x62
Monitors events and state changes in the SoC and handles security
violations. Currently checks for:
1. Trying to execute instructions in FW\_RAM. *Always enabled.*
2. Trying to access RAM outside of the physical memory. *Always enabled*
1. Trying to access memory that is outside of the defined size of the
defined memory areas. *Always enabled*
2. Trying to execute instructions in FW\_RAM. *Always enabled.*
3. Trying to execute instructions from a memory area in RAM defined by
the application.

View File

@ -386,7 +386,8 @@ module tk1 #(
// Monitor events and state changes in the SoC, and handle
// security violations. We currently check for:
//
// Any access to RAM but outside of the size of the physical mem.
// Any memory access that is outside of the defined size of the
// defined memory areas.
//
// Trying to execute instructions in FW-RAM.
//
@ -401,10 +402,77 @@ module tk1 #(
force_trap_set = 1'h0;
if (cpu_valid) begin
// Outside ROM area
if (cpu_addr[31 : 30] == 2'h0 & |cpu_addr[29 : 14]) begin
force_trap_set = 1'h1;
end
// Outside RAM area
if (cpu_addr[31 : 30] == 2'h1 & |cpu_addr[29 : 17]) begin
force_trap_set = 1'h1;
end
// In RESERVED area
if (cpu_addr[31 : 30] == 2'h2) begin
force_trap_set = 1'h1;
end
// MMIO
if (cpu_addr[31 : 30] == 2'h3) begin
// Outside TRNG
if (cpu_addr[29 : 24] == 6'h00 & |cpu_addr[23 : 10]) begin
force_trap_set = 1'h1;
end
// Outside TIMER
if (cpu_addr[29 : 24] == 6'h01 & |cpu_addr[23 : 10]) begin
force_trap_set = 1'h1;
end
// Outside UDS
if (cpu_addr[29 : 24] == 6'h02 & |cpu_addr[23 : 5]) begin
force_trap_set = 1'h1;
end
// Outside UART
if (cpu_addr[29 : 24] == 6'h03 & |cpu_addr[23 : 10]) begin
force_trap_set = 1'h1;
end
// Outside TOUCH_SENSE
if (cpu_addr[29 : 24] == 6'h04 & |cpu_addr[23 : 10]) begin
force_trap_set = 1'h1;
end
// In unused space
if ((cpu_addr[29 : 24] > 6'h04) && (cpu_addr[29 : 24] < 6'h10)) begin
force_trap_set = 1'h1;
end
// Outside FW_RAM
if (cpu_addr[29 : 24] == 6'h10 & |cpu_addr[23 : 11]) begin
force_trap_set = 1'h1;
end
// In unused space
if ((cpu_addr[29 : 24] > 6'h10) && (cpu_addr[29 : 24] < 6'h21)) begin
force_trap_set = 1'h1;
end
// Entire IRQ31 trigger area is accessible
// In unused space
if ((cpu_addr[29 : 24] > 6'h21) && (cpu_addr[29 : 24] < 6'h3f)) begin
force_trap_set = 1'h1;
end
// Outside TK1
if (cpu_addr[29 : 24] == 6'h3f & |cpu_addr[23 : 10]) begin
force_trap_set = 1'h1;
end
end
if (cpu_instr) begin
if ((cpu_addr >= FW_RAM_FIRST) && (cpu_addr <= FW_RAM_LAST)) begin
force_trap_set = 1'h1;

View File

@ -236,7 +236,6 @@ module tb_tk1 ();
//----------------------------------------------------------------
task reset_dut;
begin
$display("--- Toggle reset.");
tb_reset_n = 0;
#(2 * CLK_PERIOD);
tb_reset_n = 1;
@ -350,12 +349,16 @@ module tb_tk1 ();
reg [31 : 0] read_data;
tb_address = address;
tb_cs = 1'h1;
tb_cpu_instr = 1'h0;
tb_cpu_valid = 1'h1;
tb_we = 1'h0;
tb_cs = 1'h1;
#(CLK_PERIOD);
read_data = tb_read_data;
#(CLK_PERIOD);
tb_cpu_valid = 1'h0;
tb_cs = 1'h0;
end
endtask // read_word
@ -406,7 +409,7 @@ module tb_tk1 ();
task check_equal(input [31 : 0] value, input [31 : 0] expected);
begin : check_equal
if (value != expected) begin
$display("--- Error: Got 0x%08x, expected 0x%08x", expected, value);
$display("--- Error: Got 0x%08x, expected 0x%08x", value, expected);
error_ctr = error_ctr + 1;
end
end
@ -430,6 +433,91 @@ module tb_tk1 ();
end
endtask // fetch_instruction
// cpu_read_word()
//
// Read a data word from the given CPU address in the DUT.
// the word read will be available in the global variable
// tb_read_data.
//----------------------------------------------------------------
task cpu_read_word(input [31 : 0] address);
begin : cpu_read_word
reg [31 : 0] read_data;
tb_cpu_addr = address;
tb_address = tb_cpu_addr[13:2];
tb_cpu_instr = 1'h0;
tb_cpu_valid = 1'h1;
tb_we = 1'h0;
tb_cs = 1'h1;
#(CLK_PERIOD);
read_data = tb_read_data;
#(CLK_PERIOD);
tb_cpu_addr = 32'h0;
tb_cpu_valid = 1'h0;
tb_address = 12'h0;
tb_cs = 1'h0;
end
endtask // read_word
//----------------------------------------------------------------
// cpu_read_check_range_should_trap()
//
// Read data in a range of CPU addresses (32-bit addresses). Fail
// if trap signal is not asserted.
// Range is inclusive.
//----------------------------------------------------------------
task cpu_read_check_range_should_trap(input [31 : 0] start_address, input [31 : 0] end_address);
begin : read_check_range_should_not_trap
reg [32 : 0] address;
reg error_detected;
address = start_address;
error_detected = 0;
while (!error_detected && (address <= end_address)) begin
reset_dut();
cpu_read_word(address);
if (tb_force_trap == 0) begin
$display("--- Error: Expected trap when reading from address 0x%08x", address);
error_ctr += 1;
error_detected = 1;
end
address += 1;
end
end
endtask
//----------------------------------------------------------------
// cpu_read_check_range_should_not_trap()
//
// Read data in a range of CPU addresses (32-bit addresses). Fail
// if trap signal is asserted.
// Range is inclusive.
//----------------------------------------------------------------
task cpu_read_check_range_should_not_trap(input [31 : 0] start_address, input [31 : 0] end_address);
begin : read_check_should_not_trap
reg [31 : 0] address;
reg error_detected;
address = start_address;
error_detected = 0;
while (!error_detected && (address <= end_address)) begin
reset_dut();
cpu_read_word(address);
if (tb_force_trap == 1) begin
$display("--- Error: Did not expected trap when reading from address 0x%08x", address);
error_ctr += 1;
error_detected = 1;
end
address += 1;
end
end
endtask
//----------------------------------------------------------------
// test1()
@ -882,6 +970,106 @@ module tb_tk1 ();
end
endtask // test10
//----------------------------------------------------------------
// test11()
// Test security monitor trap ranges.
// - Check that reading accessible areas does not trap
// - Check that reading the start and end of inaccessible areas
// trap
//----------------------------------------------------------------
task test11;
begin
tc_ctr = tc_ctr + 1;
$display("");
$display("--- test11: Test trap ranges.");
// ROM trap range: 0x00004000-0x3fffffff
$display("--- test11: ROM");
cpu_read_check_range_should_not_trap(32'h0, 32'h3fff);
cpu_read_check_range_should_trap(32'h4000, 32'h400f);
cpu_read_check_range_should_trap(32'h3ffffff0, 32'h3fffffff);
// RAM trap range: 0x40020000-0x7fffffff
$display("--- test11: RAM");
cpu_read_check_range_should_not_trap(32'h40000000, 32'h4000000f);
cpu_read_check_range_should_trap(32'h40020000, 32'h4002000f);
cpu_read_check_range_should_trap(32'h7ffffff0, 32'h7fffffff);
// Reserved trap range: 0x80000000-0xbfffffff
$display("--- test11: Reserved");
cpu_read_check_range_should_trap(32'h80000000, 32'h8000000f);
cpu_read_check_range_should_trap(32'hbffffff0, 32'hbfffffff);
// TRNG trap range: 0xc0000400-0xc0ffffff
$display("--- test11: TRNG");
cpu_read_check_range_should_not_trap(32'hc0000000, 32'hc00003ff);
cpu_read_check_range_should_trap(32'hc0000400, 32'hc000040f);
cpu_read_check_range_should_trap(32'hc0fffff0, 32'hc0ffffff);
// TIMER trap range: 0xc1000400-0xc1ffffff
$display("--- test11: TIMER");
cpu_read_check_range_should_not_trap(32'hc1000000, 32'hc10003ff);
cpu_read_check_range_should_trap(32'hc1000400, 32'hc100040f);
cpu_read_check_range_should_trap(32'hc1fffff0, 32'hc1ffffff);
// UDS trap range: 0xc2000020-0xc2ffffff
$display("--- test11: UDS");
cpu_read_check_range_should_not_trap(32'hc2000000, 32'hc200001f);
cpu_read_check_range_should_trap(32'hc2000020, 32'hc200002f);
cpu_read_check_range_should_trap(32'hc2fffff0, 32'hc2ffffff);
// UART trap range: 0xc3000400-0xc3ffffff
$display("--- test11: UART");
cpu_read_check_range_should_not_trap(32'hc3000000, 32'hc30003ff);
cpu_read_check_range_should_trap(32'hc3000400, 32'hc300040f);
cpu_read_check_range_should_trap(32'hc3fffff0, 32'hc3ffffff);
// TOUCH_SENSE trap range: 0xc4000400-0xc4ffffff
$display("--- test11: TOUCH_SENSE");
cpu_read_check_range_should_not_trap(32'hc4000000, 32'hc40003ff);
cpu_read_check_range_should_trap(32'hc4000400, 32'hc400040f);
cpu_read_check_range_should_trap(32'hc4fffff0, 32'hc4ffffff);
// Unused trap range: 0xc5000000-0xcfffffff
$display("--- test11: Unused");
cpu_read_check_range_should_trap(32'hc5000000, 32'hc500000f);
cpu_read_check_range_should_trap(32'hc5fffff0, 32'hc5ffffff);
// FW_RAM trap range: 0xd0000800-0xd0ffffff
$display("--- test11: FW_RAM");
cpu_read_check_range_should_not_trap(32'hd0000000, 32'hd00007ff);
cpu_read_check_range_should_trap(32'hd0000800, 32'hd000080f);
cpu_read_check_range_should_trap(32'hd0fffff0, 32'hd0ffffff);
// Unused trap range: 0xd1000000-0xfeffffff
$display("--- test11: Unused");
cpu_read_check_range_should_trap(32'hd1000000, 32'hd100000f);
cpu_read_check_range_should_trap(32'he0fffff0, 32'he0ffffff);
// IRQ31 No trap range. Entire 0xe1 range is accessible.
cpu_read_check_range_should_not_trap(32'he1000000, 32'he100000f);
cpu_read_check_range_should_not_trap(32'he1fffff0, 32'he1ffffff);
// Unused trap range: 0xe2000000-0xfeffffff
//
$display("--- test11: Unused");
cpu_read_check_range_should_trap(32'he2000000, 32'he200000f);
cpu_read_check_range_should_trap(32'hfefffff0, 32'hfeffffff);
// TK1 trap range: 0xff000400-0xffffffff
$display("--- test11: TK1");
cpu_read_check_range_should_not_trap(32'hff000000, 32'hff0003ff);
cpu_read_check_range_should_trap(32'hff000400, 32'hff00040f);
cpu_read_check_range_should_trap(32'hfffffff0, 32'hffffffff);
$display("--- test11: completed.");
$display("");
end
endtask // test11
//----------------------------------------------------------------
// exit_with_error_code()
//
@ -921,6 +1109,7 @@ module tb_tk1 ();
test9();
test9();
test10();
test11();
display_test_result();
$display("");

View File

@ -55,6 +55,9 @@ module uart (
input wire rxd,
output wire txd,
input wire ch552_cts,
output wire fpga_cts,
input wire cs,
input wire we,
input wire [ 7 : 0] address,
@ -79,10 +82,10 @@ module uart (
// The default bit rate is based on target clock frequency
// divided by the bit rate times in order to hit the
// center of the bits. I.e.
// Clock: 21 MHz, 62500 bps
// Divisor = 21E6 / 62500 = 336
// Clock: 21 MHz, 500 kbps
// Divisor = 21E6 / 500E3 = 42
// This also satisfies 1E6 % bps == 0 for the CH552 MCU used for USB-serial
localparam DEFAULT_BIT_RATE = 16'd336;
localparam DEFAULT_BIT_RATE = 16'd42;
localparam DEFAULT_DATA_BITS = 4'h8;
localparam DEFAULT_STOP_BITS = 2'h1;
@ -110,6 +113,7 @@ module uart (
reg [31 : 0] tmp_read_data;
reg tmp_ready;
reg [ 1 : 0] ch552_cts_reg;
//----------------------------------------------------------------
// Concurrent connectivity for ports etc.
@ -158,9 +162,24 @@ module uart (
.out_syn (fifo_out_syn),
.out_data(fifo_out_data),
.out_ack (fifo_out_ack)
.out_ack (fifo_out_ack),
.fpga_cts(fpga_cts)
);
//----------------------------------------------------------------
// reg_update
//----------------------------------------------------------------
always @(posedge clk) begin : reg_update
if (!reset_n) begin
ch552_cts_reg <= 2'h0;
end
else begin
ch552_cts_reg[0] <= ch552_cts;
ch552_cts_reg[1] <= ch552_cts_reg[0];
end
end // reg_update
//----------------------------------------------------------------
// api
//
@ -208,7 +227,7 @@ module uart (
end
ADDR_TX_STATUS: begin
tmp_read_data = {31'h0, core_txd_ready};
tmp_read_data = {31'h0, core_txd_ready & ch552_cts_reg[1]};
end
default: begin

View File

@ -81,10 +81,9 @@ module uart_core (
parameter ERX_SYN = 4;
parameter ETX_IDLE = 0;
parameter ETX_ACK = 1;
parameter ETX_START = 2;
parameter ETX_BITS = 3;
parameter ETX_STOP = 4;
parameter ETX_START = 1;
parameter ETX_BITS = 2;
parameter ETX_STOP = 3;
//----------------------------------------------------------------
@ -171,19 +170,19 @@ module uart_core (
//----------------------------------------------------------------
always @(posedge clk) begin : reg_update
if (!reset_n) begin
rxd0_reg <= 1'b0;
rxd_reg <= 1'b0;
rxd0_reg <= 0;
rxd_reg <= 0;
rxd_byte_reg <= 8'h0;
rxd_bit_ctr_reg <= 4'h0;
rxd_bitrate_ctr_reg <= 16'h0;
rxd_syn_reg <= 0;
erx_ctrl_reg <= ERX_IDLE;
txd_reg <= 1'b1;
txd_reg <= 1;
txd_byte_reg <= 8'h0;
txd_bit_ctr_reg <= 4'h0;
txd_bitrate_ctr_reg <= 16'h0;
txd_ready_reg <= 1'b1;
txd_ready_reg <= 1;
etx_ctrl_reg <= ETX_IDLE;
end
@ -246,16 +245,16 @@ module uart_core (
//----------------------------------------------------------------
always @* begin : rxd_bit_ctr
rxd_bit_ctr_new = 4'h0;
rxd_bit_ctr_we = 1'b0;
rxd_bit_ctr_we = 0;
if (rxd_bit_ctr_rst) begin
rxd_bit_ctr_new = 4'h0;
rxd_bit_ctr_we = 1'b1;
rxd_bit_ctr_we = 1;
end
else if (rxd_bit_ctr_inc) begin
rxd_bit_ctr_new = rxd_bit_ctr_reg + 1'h1;
rxd_bit_ctr_we = 1'b1;
rxd_bit_ctr_we = 1;
end
end // rxd_bit_ctr
@ -267,22 +266,21 @@ module uart_core (
// serial interface.
//----------------------------------------------------------------
always @* begin : rxd_bitrate_ctr
rxd_bitrate_ctr_new = 16'h0;
rxd_bitrate_ctr_we = 1'h0;
rxd_bitrate_ctr_new = 16'h1;
rxd_bitrate_ctr_we = 0;
if (rxd_bitrate_ctr_rst) begin
rxd_bitrate_ctr_new = 16'h0;
rxd_bitrate_ctr_we = 1'b1;
rxd_bitrate_ctr_new = 16'h1;
rxd_bitrate_ctr_we = 1;
end
else if (rxd_bitrate_ctr_inc) begin
rxd_bitrate_ctr_new = rxd_bitrate_ctr_reg + 1'h1;
rxd_bitrate_ctr_we = 1'b1;
rxd_bitrate_ctr_we = 1;
end
end // rxd_bitrate_ctr
//----------------------------------------------------------------
// txd_bit_ctr
//
@ -291,16 +289,16 @@ module uart_core (
//----------------------------------------------------------------
always @* begin : txd_bit_ctr
txd_bit_ctr_new = 4'h0;
txd_bit_ctr_we = 1'h0;
txd_bit_ctr_we = 0;
if (txd_bit_ctr_rst) begin
txd_bit_ctr_new = 4'h0;
txd_bit_ctr_we = 1'h1;
txd_bit_ctr_we = 1;
end
else if (txd_bit_ctr_inc) begin
txd_bit_ctr_new = txd_bit_ctr_reg + 1'h1;
txd_bit_ctr_we = 1'b1;
txd_bit_ctr_we = 1;
end
end // txd_bit_ctr
@ -312,11 +310,11 @@ module uart_core (
// serial interface.
//----------------------------------------------------------------
always @* begin : txd_bitrate_ctr
txd_bitrate_ctr_new = 16'h0;
txd_bitrate_ctr_new = 16'h1;
txd_bitrate_ctr_we = 0;
if (txd_bitrate_ctr_rst) begin
txd_bitrate_ctr_new = 16'h0;
txd_bitrate_ctr_new = 16'h1;
txd_bitrate_ctr_we = 1;
end
@ -350,25 +348,32 @@ module uart_core (
ERX_IDLE: begin
if (!rxd_reg) begin
// Possible start bit detected.
rxd_bitrate_ctr_rst = 1;
rxd_bitrate_ctr_inc = 1;
erx_ctrl_new = ERX_START;
erx_ctrl_we = 1;
end
end
ERX_START: begin
rxd_bitrate_ctr_inc = 1;
if (rxd_reg) begin
// Just a glitch.
rxd_bitrate_ctr_rst = 1;
erx_ctrl_new = ERX_IDLE;
erx_ctrl_we = 1;
erx_ctrl_we = 1;
end
else begin
if (rxd_bitrate_ctr_reg == half_bit_rate) begin
// start bit assumed. We start sampling data.
rxd_bit_ctr_rst = 1;
if (rxd_bitrate_ctr_reg < half_bit_rate) begin
rxd_bitrate_ctr_inc = 1;
end
else begin
// Start bit assumed.
// We are in the middle of the start bit.
// Start sampling data.
rxd_bitrate_ctr_rst = 1;
rxd_bit_ctr_rst = 1;
erx_ctrl_new = ERX_BITS;
erx_ctrl_we = 1;
end
@ -382,11 +387,14 @@ module uart_core (
end
else begin
rxd_byte_we = 1;
rxd_bit_ctr_inc = 1;
rxd_bitrate_ctr_rst = 1;
if (rxd_bit_ctr_reg == (data_bits - 1)) begin
erx_ctrl_new = ERX_STOP;
if (rxd_bit_ctr_reg < data_bits) begin
rxd_bitrate_ctr_rst = 1;
rxd_bit_ctr_inc = 1;
rxd_byte_we = 1; // We are in the middle of a data bit, make a sample
end
else begin
erx_ctrl_new = ERX_STOP; // We are now in the middle of the stop bit
erx_ctrl_we = 1;
end
end
@ -394,12 +402,17 @@ module uart_core (
ERX_STOP: begin
rxd_bitrate_ctr_inc = 1;
if (rxd_bitrate_ctr_reg == bit_rate * stop_bits) begin
rxd_syn_new = 1;
rxd_syn_we = 1;
erx_ctrl_new = ERX_SYN;
erx_ctrl_we = 1;
// stop_bits can be removed from line below if we are only using one stop bit
if (rxd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
rxd_bitrate_ctr_inc = 1;
end
else begin
rxd_bitrate_ctr_rst = 1;
rxd_syn_new = 1;
rxd_syn_we = 1;
erx_ctrl_new = ERX_SYN;
erx_ctrl_we = 1;
end
end
@ -442,39 +455,35 @@ module uart_core (
case (etx_ctrl_reg)
ETX_IDLE: begin
txd_new = 1;
txd_we = 1;
txd_new = 1;
txd_we = 1;
txd_bit_ctr_rst = 1;
if (txd_syn) begin
txd_new = 0;
txd_we = 1;
txd_byte_new = txd_data;
txd_byte_we = 1;
txd_ready_new = 0;
txd_ready_we = 1;
txd_bitrate_ctr_rst = 1;
etx_ctrl_new = ETX_ACK;
etx_ctrl_new = ETX_START;
etx_ctrl_we = 1;
end
end
ETX_ACK: begin
if (!txd_syn) begin
txd_new = 0;
txd_we = 1;
etx_ctrl_new = ETX_START;
etx_ctrl_we = 1;
end
end
ETX_START: begin
if (txd_bitrate_ctr_reg == bit_rate) begin
txd_bit_ctr_rst = 1;
etx_ctrl_new = ETX_BITS;
etx_ctrl_we = 1;
if (txd_bitrate_ctr_reg < bit_rate) begin
txd_bitrate_ctr_inc = 1;
end
else begin
txd_bitrate_ctr_inc = 1;
txd_bitrate_ctr_rst = 1;
txd_bit_ctr_inc = 1;
txd_new = txd_byte_reg[txd_bit_ctr_reg[2 : 0]];
txd_we = 1;
etx_ctrl_new = ETX_BITS;
etx_ctrl_we = 1;
end
end
@ -486,29 +495,36 @@ module uart_core (
else begin
txd_bitrate_ctr_rst = 1;
if (txd_bit_ctr_reg == data_bits) begin
if (txd_bit_ctr_reg < data_bits) begin
txd_bit_ctr_inc = 1;
txd_new = txd_byte_reg[txd_bit_ctr_reg[2 : 0]];
txd_we = 1;
end
else begin
txd_new = 1;
txd_we = 1;
etx_ctrl_new = ETX_STOP;
etx_ctrl_we = 1;
end
else begin
txd_new = txd_byte_reg[txd_bit_ctr_reg[2 : 0]];
txd_we = 1;
txd_bit_ctr_inc = 1;
end
end
end
ETX_STOP: begin
txd_bitrate_ctr_inc = 1;
if (txd_bitrate_ctr_reg == bit_rate * stop_bits) begin
txd_ready_new = 1;
txd_ready_we = 1;
etx_ctrl_new = ETX_IDLE;
etx_ctrl_we = 1;
// stop_bits can be removed from line below if we are only using one stop bit
if (txd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
txd_bitrate_ctr_inc = 1;
end
else begin
txd_bitrate_ctr_rst = 1;
txd_bit_ctr_rst = 1;
txd_ready_new = 1;
txd_ready_we = 1;
etx_ctrl_new = ETX_IDLE;
etx_ctrl_we = 1;
end
end

View File

@ -48,7 +48,9 @@ module uart_fifo (
output wire out_syn,
output wire [7 : 0] out_data,
input wire out_ack
input wire out_ack,
output wire fpga_cts
);
@ -75,6 +77,7 @@ module uart_fifo (
reg in_ack_reg;
reg in_ack_new;
reg fpga_cts_reg;
//----------------------------------------------------------------
// Wires
@ -90,6 +93,7 @@ module uart_fifo (
assign out_syn = ~fifo_empty;
assign out_data = fifo_mem[out_ptr_reg];
assign fifo_bytes = byte_ctr_reg;
assign fpga_cts = fpga_cts_reg;
//----------------------------------------------------------------
@ -101,6 +105,7 @@ module uart_fifo (
out_ptr_reg <= 9'h0;
byte_ctr_reg <= 9'h0;
in_ack_reg <= 1'h0;
fpga_cts_reg <= 1'h1;
end
else begin
in_ack_reg <= in_ack_new;
@ -120,6 +125,14 @@ module uart_fifo (
if (byte_ctr_we) begin
byte_ctr_reg <= byte_ctr_new;
end
if (byte_ctr_reg >= 9'd486) begin // FIFO is filled to ~95% or more
fpga_cts_reg <= 0; // Signal to not send more data
end
else begin
fpga_cts_reg <= 1; // Signal to send more data
end
end
end // reg_update

View File

@ -14,8 +14,8 @@
# UART.
set_io interface_rx 26
set_io interface_tx 25
# set_io interface_cts 27
# set_io interface_rts 28
set_io interface_ch552_cts 27
set_io interface_fpga_cts 28
# SPI master to flash memory.

View File

@ -1 +1 @@
edb39fca7dafb8ea0b89fdeecd960d7656e14ce461e49af97160a8bd6e67d9987e816adad37ba0fcfa63d107c3160988e4c3423ce4a71c39544bc0045888fec1 firmware.bin
5e655ba4f25e7f5bc033ce0d9707c9a0b8990258c4b87470c2bcef90d50df79813705c1ef9d22c8670a37aff68f0e5146e5d0c21406916aabf7704579eb7f15c firmware.bin

View File

@ -37,15 +37,38 @@ memory access control.
## Communication
The firmware communicates to the host via the
`UART_{RX,TX}_{STATUS,DATA}` registers, using the framing protocol
described in the [Framing
Protocol](https://dev.tillitis.se/protocol/).
The firmware communicates with the client using the
`UART_{RX,TX}_{STATUS,DATA}` registers. On top of that is uses three
protocols: The USB Mode protocol, the TKey framing protocol, and the
firmware's own protocol.
To communicate between the CPU and the CH552 USB controller it uses an
internal protocol, used only within the TKey, which we call the USB
Mode Protocol. It is used in both directions.
| *Name* | *Size* | *Comment* |
|----------|-----------|------------------------------------|
| Endpoint | 1B | Origin or destination USB endpoint |
| Length | 1B | Number of bytes following |
| Payload | See above | Actual data from or to firmware |
The different endpoints:
| *Name* | *Value* | *Comment* |
|--------|---------|---------------------------------------------------------------------|
| CTRL | 0x20 | A USB HID special debug pipe. Useful for debug prints. |
| CDC | 0x40 | USB CDC-ACM, a serial port on the client. |
| HID | 0x80 | A USB HID security token device, useful for FIDO-type applications. |
On top of the USB Mode Protocol is [the TKey Framing
Protocol](https://dev.tillitis.se/protocol/) which is described in the
Developer Handbook.
The firmware uses a protocol on top of this framing layer which is
used to bootstrap the application. All commands are initiated by the
used to bootstrap an application. All commands are initiated by the
client. All commands receive a reply. See [Firmware
protocol](#firmware-protocol) for specific details.
protocol](http://dev.tillitis.se/protocol/#firmware-protocol) in the
Dev Handbook for specific details.
## Memory constraints
@ -137,12 +160,9 @@ application mode, but with no privileged access.
Firmware loads the application at the start of RAM (`0x4000_0000`). It
uses the special FW\_RAM for its own stack.
When the firmware starts it clears all FW\_RAM, then sets up a stack
there before jumping to `main()`.
When reset is released, the CPU starts executing the firmware. It
begins by clearing all CPU registers, and then sets up a stack for
itself and then jumps to main().
begins by clearing all CPU registers, clears all FW\_RAM, sets up a
stack for itself there, and then jumps to `main()`.
Beginning at `main()` it sets up the "system calls", then fills the
entire RAM with pseudo random data and setting up the RAM address and
@ -187,8 +207,8 @@ Typical expected use scenario:
stack. After this it performs no more function calls and uses no
more automatic variables.
8. Firmware starts the application by first switching to from
firmware mode to application mode by writing to the `SYSTEM_MODE_CTRL`
8. Firmware starts the application by first switching from firmware
mode to application mode by writing to the `SYSTEM_MODE_CTRL`
register. In this mode the MMIO region is restricted, e.g. some
registers are removed (`UDS`), and some are switched from
read/write to read-only (see [the memory

View File

@ -49,6 +49,7 @@ TESTAPP_OBJS = \
$(P)/main.o \
$(P)/crt0.o \
$(P)/syscall.o \
$(P)/../tk1/assert.o \
$(P)/../tk1/led.o \
$(P)/../tk1/lib.o \
$(P)/../tk1/proto.o

View File

@ -11,6 +11,8 @@
#include "../tk1_mem.h"
#include "syscall.h"
#define USBMODE_PACKET_SIZE 64
// clang-format off
volatile uint32_t *tk1name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
volatile uint32_t *tk1name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
@ -31,38 +33,68 @@ volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY
#define UDI_WORDS 2
#define CDI_WORDS 8
void *memcpy(void *dest, const void *src, size_t n)
static void write_with_header(const uint8_t *buf, size_t nbytes, enum mode mode)
{
uint8_t *src_byte = (uint8_t *)src;
uint8_t *dest_byte = (uint8_t *)dest;
// Append USB Mode Protocol header:
// 1 byte mode
// 1 byte length
writebyte(mode);
writebyte(nbytes);
for (int i = 0; i < n; i++) {
dest_byte[i] = src_byte[i];
}
return dest;
}
void puts(char *reason)
{
for (char *c = reason; *c != '\0'; c++) {
writebyte(*c);
for (int i = 0; i < nbytes; i++) {
writebyte(buf[i]);
}
}
void putsn(char *p, int n)
static void write(const uint8_t *buf, size_t nbytes)
{
for (int i = 0; i < n; i++) {
writebyte(p[i]);
uint8_t len;
while (nbytes > 0) {
// We split the data into chunks that will fit in the
// USB Mode Protocol with some spare change.
len =
nbytes < USBMODE_PACKET_SIZE ? nbytes : USBMODE_PACKET_SIZE;
write_with_header((const uint8_t *)buf, len, MODE_CDC);
buf += len;
nbytes -= len;
}
}
unsigned strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
void puts(char *buf)
{
size_t nbytes = strlen(buf);
write((const uint8_t *)buf, nbytes);
}
void hex(uint8_t buf[2], const uint8_t c)
{
unsigned int upper = (c >> 4) & 0xf;
unsigned int lower = c & 0xf;
buf[0] = upper < 10 ? '0' + upper : 'a' - 10 + upper;
buf[1] = lower < 10 ? '0' + lower : 'a' - 10 + lower;
}
void puthex(uint8_t c)
{
unsigned int upper = (c >> 4) & 0xf;
unsigned int lower = c & 0xf;
writebyte(upper < 10 ? '0' + upper : 'a' - 10 + upper);
writebyte(lower < 10 ? '0' + lower : 'a' - 10 + lower);
uint8_t buf[2];
hex(buf, c);
write(buf, 2);
}
void puthexn(uint8_t *p, int n)
@ -72,24 +104,6 @@ void puthexn(uint8_t *p, int n)
}
}
void hexdump(void *buf, int len)
{
uint8_t *byte_buf = (uint8_t *)buf;
for (int i = 0; i < len; i++) {
puthex(byte_buf[i]);
if (i % 2 == 1) {
writebyte(' ');
}
if (i != 1 && i % 16 == 1) {
puts("\r\n");
}
}
puts("\r\n");
}
void reverseword(uint32_t *wordp)
{
*wordp = ((*wordp & 0xff000000) >> 24) | ((*wordp & 0x00ff0000) >> 8) |
@ -107,42 +121,6 @@ uint32_t wait_timer_tick(uint32_t last_timer)
}
}
void zero_fwram(void)
{
for (int i = 0; i < TK1_MMIO_FW_RAM_SIZE; i++) {
fw_ram[i] = 0x00;
}
}
int check_fwram_zero_except(unsigned int offset, uint8_t expected_val)
{
int failed = 0;
for (unsigned int i = 0; i < TK1_MMIO_FW_RAM_SIZE; i++) {
uint32_t addr = TK1_MMIO_FW_RAM_BASE + i;
uint8_t *p = (uint8_t *)addr;
uint8_t val = *(volatile uint8_t *)p;
int failed_now = 0;
if (i == offset) {
if (val != expected_val) {
failed_now = 1;
puts(" wrong value at: ");
}
} else {
if (val != 0) {
failed_now = 1;
puts(" not zero at: ");
}
}
if (failed_now) {
failed = 1;
reverseword(&addr);
puthexn((uint8_t *)&addr, 4);
puts("\r\n");
}
}
return failed;
}
void failmsg(char *s)
{
puts("FAIL: ");
@ -152,23 +130,25 @@ void failmsg(char *s)
int main(void)
{
uint8_t in;
uint8_t in = 0;
uint8_t mode = 0;
uint8_t mode_bytes_left = 0;
set_led(LED_BLUE);
// Wait for terminal program and a character to be typed
in = readbyte();
in = readbyte(&mode, &mode_bytes_left);
puts("\r\nI'm testapp on:");
// Output the TK1 core's NAME0 and NAME1
uint32_t name;
wordcpy_s(&name, 1, (void *)tk1name0, 1);
reverseword(&name);
putsn((char *)&name, 4);
write((const uint8_t *)&name, 4);
puts(" ");
wordcpy_s(&name, 1, (void *)tk1name1, 1);
reverseword(&name);
putsn((char *)&name, 4);
write((const uint8_t *)&name, 4);
puts("\r\n");
uint32_t zeros[8];
@ -288,10 +268,13 @@ int main(void)
puts("Now echoing what you type...Type + to reset device\r\n");
for (;;) {
in = readbyte(); // blocks
in = readbyte(&mode, &mode_bytes_left);
if (in == '+') {
syscall(TK1_SYSCALL_RESET, 0);
}
writebyte(MODE_CDC);
writebyte(1);
writebyte(in);
}
}

View File

@ -9,6 +9,8 @@
#include "../tk1/types.h"
#include "../tk1_mem.h"
#define USBMODE_PACKET_SIZE 64
// clang-format off
volatile uint32_t *tk1name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
volatile uint32_t *tk1name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
@ -41,26 +43,68 @@ void *memcpy(void *dest, const void *src, size_t n)
return dest;
}
void puts(char *reason)
static void write_with_header(const uint8_t *buf, size_t nbytes, enum mode mode)
{
for (char *c = reason; *c != '\0'; c++) {
writebyte(*c);
// Append USB Mode Protocol header:
// 1 byte mode
// 1 byte length
writebyte(mode);
writebyte(nbytes);
for (int i = 0; i < nbytes; i++) {
writebyte(buf[i]);
}
}
void putsn(char *p, int n)
static void write(const uint8_t *buf, size_t nbytes)
{
for (int i = 0; i < n; i++) {
writebyte(p[i]);
uint8_t len;
while (nbytes > 0) {
// We split the data into chunks that will fit in the
// USB Mode Protocol with some spare change.
len =
nbytes < USBMODE_PACKET_SIZE ? nbytes : USBMODE_PACKET_SIZE;
write_with_header((const uint8_t *)buf, len, MODE_CDC);
buf += len;
nbytes -= len;
}
}
unsigned strlen(const char *str)
{
const char *s;
for (s = str; *s; ++s)
;
return (s - str);
}
void puts(char *buf)
{
size_t nbytes = strlen(buf);
write((const uint8_t *)buf, nbytes);
}
void hex(uint8_t buf[2], const uint8_t c)
{
unsigned int upper = (c >> 4) & 0xf;
unsigned int lower = c & 0xf;
buf[0] = upper < 10 ? '0' + upper : 'a' - 10 + upper;
buf[1] = lower < 10 ? '0' + lower : 'a' - 10 + lower;
}
void puthex(uint8_t c)
{
unsigned int upper = (c >> 4) & 0xf;
unsigned int lower = c & 0xf;
writebyte(upper < 10 ? '0' + upper : 'a' - 10 + upper);
writebyte(lower < 10 ? '0' + lower : 'a' - 10 + lower);
uint8_t buf[2];
hex(buf, c);
write(buf, 2);
}
void puthexn(uint8_t *p, int n)
@ -77,7 +121,7 @@ void hexdump(void *buf, int len)
for (int i = 0; i < len; i++) {
puthex(byte_buf[i]);
if (i % 2 == 1) {
writebyte(' ');
puts(" ");
}
if (i != 1 && i % 16 == 1) {
@ -150,7 +194,10 @@ void failmsg(char *s)
int main(void)
{
uint8_t in;
uint8_t in = 0;
uint8_t mode = 0;
uint8_t mode_bytes_left = 0;
// Hard coded test UDS in ../../data/uds.hex
// clang-format off
uint32_t uds_test[8] = {
@ -166,18 +213,18 @@ int main(void)
// clang-format on
// Wait for terminal program and a character to be typed
in = readbyte();
in = readbyte(&mode, &mode_bytes_left);
puts("\r\nI'm testfw on:");
// Output the TK1 core's NAME0 and NAME1
uint32_t name;
wordcpy_s(&name, 1, (void *)tk1name0, 1);
reverseword(&name);
putsn((char *)&name, 4);
write((const uint8_t *)&name, 4);
puts(" ");
wordcpy_s(&name, 1, (void *)tk1name1, 1);
reverseword(&name);
putsn((char *)&name, 4);
write((const uint8_t *)&name, 4);
puts("\r\n");
uint32_t zeros[8];
@ -268,8 +315,8 @@ int main(void)
}
puts("\r\nTesting timer... 3");
// Matching clock at 18 MHz, giving us timer in seconds
*timer_prescaler = 18 * 1000000;
// Matching clock at 21 MHz, giving us timer in seconds
*timer_prescaler = 21 * 1000000;
// Test timer expiration after 1s
*timer = 1;
@ -312,6 +359,7 @@ int main(void)
}
puts("\r\nHere are 256 bytes from the TRNG:\r\n");
for (int j = 0; j < 8; j++) {
for (int i = 0; i < 8; i++) {
while ((*trng_status &
@ -327,7 +375,10 @@ int main(void)
puts("Now echoing what you type...\r\n");
for (;;) {
in = readbyte(); // blocks
in = readbyte(&mode, &mode_bytes_left);
writebyte(MODE_CDC);
writebyte(1);
writebyte(in);
}
}

View File

@ -420,6 +420,9 @@ int main(void)
/*@+mustfreeonly@*/
ctx.use_uss = FALSE;
uint8_t mode = 0;
uint8_t mode_bytes_left = 0;
scramble_ram();
#if defined(SIMULATION)
@ -429,7 +432,8 @@ int main(void)
for (;;) {
switch (state) {
case FW_STATE_INITIAL:
if (readcommand(&hdr, cmd, state) == -1) {
if (readcommand(&hdr, cmd, state, &mode,
&mode_bytes_left) == -1) {
state = FW_STATE_FAIL;
break;
}
@ -438,7 +442,8 @@ int main(void)
break;
case FW_STATE_LOADING:
if (readcommand(&hdr, cmd, state) == -1) {
if (readcommand(&hdr, cmd, state, &mode,
&mode_bytes_left) == -1) {
state = FW_STATE_FAIL;
break;
}

View File

@ -22,7 +22,8 @@ static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
enum cmdlen len);
static int parseframe(uint8_t b, struct frame_header *hdr);
static void write(uint8_t *buf, size_t nbytes);
static int read(uint8_t *buf, size_t bufsize, size_t nbytes);
static int read(uint8_t *buf, size_t bufsize, size_t nbytes, uint8_t *mode,
uint8_t *mode_bytes_left);
static size_t bytelen(enum cmdlen cmdlen);
static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
@ -31,12 +32,13 @@ static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
return (id << 5) | (endpoint << 3) | (status << 2) | len;
}
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state)
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state,
uint8_t *mode, uint8_t *mode_bytes_left)
{
uint8_t in = 0;
set_led((state == FW_STATE_LOADING) ? LED_BLACK : LED_WHITE);
in = readbyte();
in = readbyte(mode, mode_bytes_left);
if (parseframe(in, hdr) == -1) {
htif_puts("Couldn't parse header\n");
@ -45,7 +47,7 @@ int readcommand(struct frame_header *hdr, uint8_t *cmd, int state)
(void)memset(cmd, 0, CMDLEN_MAXBYTES);
// Now we know the size of the cmd frame, read it all
if (read(cmd, CMDLEN_MAXBYTES, hdr->len) != 0) {
if (read(cmd, CMDLEN_MAXBYTES, hdr->len, mode, mode_bytes_left) != 0) {
htif_puts("read: buffer overrun\n");
return -1;
}
@ -115,6 +117,10 @@ void fwreply(struct frame_header hdr, enum fwcmd rspcode, uint8_t *buf)
nbytes = bytelen(len);
// Mode Protocol Header
writebyte(MODE_CDC);
writebyte(2);
// Frame Protocol Header
writebyte(genhdr(hdr.id, hdr.endpoint, 0x0, len));
@ -122,7 +128,19 @@ void fwreply(struct frame_header hdr, enum fwcmd rspcode, uint8_t *buf)
writebyte(rspcode);
nbytes--;
write(buf, nbytes);
while (nbytes > 0) {
// Limit transfers to 64 bytes (2 byte header + 62 byte data) to
// fit in a single USB frame.
size_t tx_count = nbytes > 62 ? 62 : nbytes;
// Mode Protocol Header
writebyte(MODE_CDC);
writebyte(tx_count & 0xff);
// Data
write(buf, tx_count);
nbytes -= tx_count;
buf += tx_count;
}
}
void writebyte(uint8_t b)
@ -142,23 +160,41 @@ static void write(uint8_t *buf, size_t nbytes)
}
}
uint8_t readbyte(void)
uint8_t readbyte_(void)
{
for (;;) {
if (*can_rx) {
return *rx;
uint32_t b = *rx;
return b;
}
}
}
static int read(uint8_t *buf, size_t bufsize, size_t nbytes)
uint8_t readbyte(uint8_t *mode, uint8_t *mode_bytes_left)
{
if (*mode_bytes_left == 0) {
*mode = readbyte_();
if (*mode != MODE_CDC) {
htif_puts("We only support MODE_CDC\n");
assert(1 == 2);
} else {
*mode_bytes_left = readbyte_();
}
}
uint8_t b = readbyte_();
*mode_bytes_left -= 1;
return b;
}
static int read(uint8_t *buf, size_t bufsize, size_t nbytes, uint8_t *mode,
uint8_t *mode_bytes_left)
{
if (nbytes > bufsize) {
return -1;
}
for (int n = 0; n < nbytes; n++) {
buf[n] = readbyte();
buf[n] = readbyte(mode, mode_bytes_left);
}
return 0;

View File

@ -8,6 +8,12 @@
#ifndef PROTO_H
#define PROTO_H
enum mode {
MODE_TKEYCTRL = 0x20,
MODE_CDC = 0x40,
MODE_HID = 0x80,
};
enum endpoints {
DST_HW_IFPGA,
DST_HW_AFPGA,
@ -52,7 +58,8 @@ struct frame_header {
/*@ -exportlocal @*/
void writebyte(uint8_t b);
uint8_t readbyte(void);
uint8_t readbyte(uint8_t *mode, uint8_t *mode_bytes_left);
void fwreply(struct frame_header hdr, enum fwcmd rspcode, uint8_t *buf);
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state);
int readcommand(struct frame_header *hdr, uint8_t *cmd, int state,
uint8_t *mode, uint8_t *mode_bytes_left);
#endif

View File

@ -82,8 +82,8 @@
#define TK1_MMIO_TIMER_TIMER 0xc100002c
#define TK1_MMIO_UDS_BASE 0xc2000000
#define TK1_MMIO_UDS_FIRST 0xc2000040
#define TK1_MMIO_UDS_LAST 0xc200005c
#define TK1_MMIO_UDS_FIRST 0xc2000000
#define TK1_MMIO_UDS_LAST 0xc200001c
#define TK1_MMIO_UART_BASE 0xc3000000
#define TK1_MMIO_UART_RX_STATUS 0xc3000080

View File

@ -20,6 +20,9 @@ module application_fpga (
output wire interface_rx,
input wire interface_tx,
input wire interface_ch552_cts, // CH552 clear to send, 1 = OK, 0 = NOK
output wire interface_fpga_cts, // FPGA clear to send, 1 = OK, 0 = NOK
output wire spi_ss,
output wire spi_sck,
output wire spi_mosi,
@ -307,6 +310,9 @@ module application_fpga (
.rxd(interface_tx),
.txd(interface_rx),
.ch552_cts(interface_ch552_cts),
.fpga_cts (interface_fpga_cts),
.cs(uart_cs),
.we(uart_we),
.address(uart_address),
@ -424,7 +430,7 @@ module application_fpga (
ram_cs = 1'h0;
ram_we = 4'h0;
ram_address = cpu_addr[17 : 2];
ram_address = cpu_addr[16 : 2];
ram_write_data = cpu_wdata;
fw_ram_cs = 1'h0;

View File

@ -33,6 +33,9 @@ module application_fpga_sim (
output wire interface_rx,
input wire interface_tx,
input wire interface_ch552_cts,
output wire interface_fpga_cts,
output wire spi_ss,
output wire spi_sck,
output wire spi_mosi,
@ -318,6 +321,9 @@ module application_fpga_sim (
.rxd(interface_tx),
.txd(interface_rx),
.ch552_cts(interface_ch552_cts),
.fpga_cts (interface_fpga_cts),
.cs(uart_cs),
.we(uart_we),
.address(uart_address),
@ -438,7 +444,7 @@ module application_fpga_sim (
ram_cs = 1'h0;
ram_we = 4'h0;
ram_address = cpu_addr[17 : 2];
ram_address = cpu_addr[16 : 2];
ram_write_data = cpu_wdata;
fw_ram_cs = 1'h0;

View File

@ -315,6 +315,7 @@ int main(int argc, char **argv, char **env)
uart_init(&u, &top.interface_tx, &top.interface_rx, BIT_DIV);
top.clk = 0;
top.interface_ch552_cts = 1;
while (!Verilated::gotFinish()) {
uint8_t to_host = 0;

View File

@ -29,6 +29,8 @@ module tb_application_fpga_sim ();
reg tb_clk = 0;
wire tb_interface_rx;
reg tb_interface_tx = 1'h1; // Set to 1 to simulate inactive UART
reg tb_interface_ch552_cts = 1'h1; // Set to 1 to simulate OK to send
reg tb_interface_fpga_cts;
wire tb_spi_ss;
wire tb_spi_sck;
wire tb_spi_mosi;
@ -49,6 +51,8 @@ module tb_application_fpga_sim ();
.clk(tb_clk),
.interface_rx(tb_interface_rx),
.interface_tx(tb_interface_tx),
.interface_ch552_cts(tb_interface_ch552_cts),
.interface_fpga_cts(tb_interface_fpga_cts),
.spi_ss(tb_spi_ss),
.spi_sck(tb_spi_sck),
.spi_mosi(tb_spi_mosi),

View File

@ -3,7 +3,6 @@ TARGET = usb_device_cdc
CH554_SDCC=~/ch554_sdcc/
CHPROG=chprog
# Adjust the XRAM location and size to leave space for the USB DMA buffers
# Buffer layout in XRAM:
# 0x0000 Ep0Buffer[8]
@ -11,8 +10,11 @@ CHPROG=chprog
# 0x0080 EP2Buffer[2*64]
#
# This takes a total of 256bytes, so there are 768 bytes left.
XRAM_SIZE = 0x0300
XRAM_LOC = 0x0100
#XRAM_SIZE = 0x0300
#XRAM_LOC = 0x0100
XRAM_SIZE = 0x0400
XRAM_LOC = 0x0000
FREQ_SYS = 16000000
@ -21,7 +23,8 @@ usb_strings.h: encode_usb_strings.py
C_FILES = \
main.c \
include/debug.c
include/debug.c \
include/print.c
pre-flash:

View File

@ -8,6 +8,8 @@ WCHISP ?= wchisptool -g -f
#######################################################
EXTRA_FLAGS = -D BUILD_CODE
FREQ_SYS ?= 24000000
XRAM_SIZE ?= 0x0400

View File

@ -37,17 +37,17 @@ if __name__ == "__main__":
f.write('#ifndef USB_STRINGS\n')
f.write('#define USB_STRINGS\n')
f.write('unsigned char __code Prod_Des[]={{ // "{}"\n'.format(product))
f.write('unsigned char __code ProdDesc[]={{ // "{}"\n'.format(product))
f.write(' ')
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(product)]))
f.write('\n};\n\n')
f.write('unsigned char __code Manuf_Des[]={{ // "{}"\n'.format(manufacturer))
f.write('unsigned char __code ManufDesc[]={{ // "{}"\n'.format(manufacturer))
f.write(' ')
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(manufacturer)]))
f.write('\n};\n\n')
f.write('unsigned char __code SerDes[]={{ // "{}"\n'.format(serial))
f.write('unsigned char __code SerialDesc[]={{ // "{}"\n'.format(serial))
f.write(' ')
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(serial)]))
f.write('\n};\n\n')

View File

@ -16,31 +16,31 @@ Header file for CH554 microcontrollers.
/* sbit are bit addressable, others are byte addressable */
/* System Registers */
SFR(PSW, 0xD0); // program status word
SBIT(CY, 0xD0, 7); // carry flag
SBIT(AC, 0xD0, 6); // auxiliary carry flag
SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0
SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit
SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit
SFR(PSW, 0xD0); // program status word
SBIT(CY, 0xD0, 7); // carry flag
SBIT(AC, 0xD0, 6); // auxiliary carry flag
SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0
SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit
SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit
#define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection
// RS1 & RS0: register R0-R7 bank selection
// 00 - bank 0, R0-R7 @ address 0x00-0x07
// 01 - bank 1, R0-R7 @ address 0x08-0x0F
// 10 - bank 2, R0-R7 @ address 0x10-0x17
// 11 - bank 3, R0-R7 @ address 0x18-0x1F
SBIT(OV, 0xD0, 2); // overflow flag
SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1
SBIT(P, 0xD0, 0); // ReadOnly: parity flag
SFR(ACC, 0xE0); // accumulator
SFR(B, 0xF0); // general purpose register B
SFR(SP, 0x81); // stack pointer
SBIT(OV, 0xD0, 2); // overflow flag
SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1
SBIT(P, 0xD0, 0); // ReadOnly: parity flag
SFR(ACC, 0xE0); // accumulator
SFR(B, 0xF0); // general purpose register B
SFR(SP, 0x81); // stack pointer
//sfr16 DPTR = 0x82; // DPTR pointer, little-endian
SFR(DPL, 0x82); // data pointer low
SFR(DPH, 0x83); // data pointer high
SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode
SFR(DPL, 0x82); // data pointer low
SFR(DPH, 0x83); // data pointer high
SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode
//sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID
#define CHIP_ID SAFE_MOD
SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode
SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode
#define bBOOT_LOAD 0x20 // ReadOnly: boot loader status for discriminating BootLoader or Application: set 1 by power on reset, clear 0 by software reset
#define bSW_RESET 0x10 // software reset bit, auto clear by hardware
#define bCODE_WE 0x08 // enable flash-ROM (include code & Data-Flash) being program or erasing: 0=writing protect, 1=enable program and erase
@ -49,7 +49,7 @@ SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode
#define bWDOG_EN 0x01 // enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow
/* Clock and Sleep and Power Registers */
SFR(PCON, 0x87); // power control and reset flag
SFR(PCON, 0x87); // power control and reset flag
#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),
// 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2)
#define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit
@ -67,7 +67,7 @@ SFR(PCON, 0x87); // power control and reset flag
#define GF1 0x08 // general purpose flag bit 1
#define GF0 0x04 // general purpose flag bit 0
#define PD 0x02 // power-down enable bit, auto clear by wake-up hardware
SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode
SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode
#define bOSC_EN_INT 0x80 // internal oscillator enable and original clock selection: 1=enable & select internal clock, 0=disable & select external clock
#define bOSC_EN_XT 0x40 // external oscillator enable, need quartz crystal or ceramic resonator between XI and XO pins
#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
@ -91,7 +91,7 @@ SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys
Fsys = Fpll/128 = 750KHz: 0 0 1
Fsys = Fpll/512 =187.5KHz: 0 0 0
*/
SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode
SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode
#define bWAK_BY_USB 0x80 // enable wake-up by USB event
#define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level
#define bWAK_P1_5_LO 0x20 // enable wake-up by pin P1.5 low level
@ -100,43 +100,43 @@ SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode
#define bWAK_RST_HI 0x04 // enable wake-up by pin RST high level
#define bWAK_P3_2E_3L 0x02 // enable wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level
#define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level
SFR(RESET_KEEP, 0xFE); // value keeper during reset
SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536
SFR(RESET_KEEP, 0xFE); // value keeper during reset
SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536
/* Interrupt Registers */
SFR(IE, 0xA8); // interrupt enable
SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0
SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable
SBIT(ET2, 0xA8, 5); // enable timer2 interrupt
SBIT(ES, 0xA8, 4); // enable UART0 interrupt
SBIT(ET1, 0xA8, 3); // enable timer1 interrupt
SBIT(EX1, 0xA8, 2); // enable external interrupt INT1
SBIT(ET0, 0xA8, 1); // enable timer0 interrupt
SBIT(EX0, 0xA8, 0); // enable external interrupt INT0
SFR(IP, 0xB8); // interrupt priority and current priority
SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag
SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag
SFR(IE, 0xA8); // interrupt enable
SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0
SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable
SBIT(ET2, 0xA8, 5); // enable timer2 interrupt
SBIT(ES, 0xA8, 4); // enable UART0 interrupt
SBIT(ET1, 0xA8, 3); // enable timer1 interrupt
SBIT(EX1, 0xA8, 2); // enable external interrupt INT1
SBIT(ET0, 0xA8, 1); // enable timer0 interrupt
SBIT(EX0, 0xA8, 0); // enable external interrupt INT0
SFR(IP, 0xB8); // interrupt priority and current priority
SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag
SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag
// PH_FLAG & PL_FLAG: current interrupt priority
// 00 - no interrupt now
// 01 - low level priority interrupt action now
// 10 - high level priority interrupt action now
// 11 - unknown error
SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level
SBIT(PS, 0xB8, 4); // UART0 interrupt priority level
SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level
SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level
SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level
SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level
SFR(IE_EX, 0xE8); // extend interrupt enable
SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt
SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt
SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt
SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt
SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt
SBIT(IE_USB, 0xE8, 2); // enable USB interrupt
SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt
SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt
SFR(IP_EX, 0xE9); // extend interrupt priority
SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level
SBIT(PS, 0xB8, 4); // UART0 interrupt priority level
SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level
SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level
SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level
SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level
SFR(IE_EX, 0xE8); // extend interrupt enable
SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt
SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt
SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt
SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt
SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt
SBIT(IE_USB, 0xE8, 2); // enable USB interrupt
SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt
SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt
SFR(IP_EX, 0xE9); // extend interrupt priority
#define bIP_LEVEL 0x80 // ReadOnly: current interrupt nested level: 0=no interrupt or two levels, 1=one level
#define bIP_GPIO 0x40 // GPIO input interrupt priority level
#define bIP_PWMX 0x20 // PWM1/2 interrupt priority level
@ -145,7 +145,7 @@ SFR(IP_EX, 0xE9); // extend interrupt priority
#define bIP_USB 0x04 // USB interrupt priority level
#define bIP_TKEY 0x02 // touch-key timer interrupt priority level
#define bIP_SPI0 0x01 // SPI0 interrupt priority level
SFR(GPIO_IE, 0xC7); // GPIO interrupt enable
SFR(GPIO_IE, 0xC7); // GPIO interrupt enable
#define bIE_IO_EDGE 0x80 // enable GPIO edge interrupt: 0=low/high level, 1=falling/rising edge
#define bIE_RXD1_LO 0x40 // enable interrupt by RXD1 low level / falling edge
#define bIE_P1_5_LO 0x20 // enable interrupt by pin P1.5 low level / falling edge
@ -156,13 +156,13 @@ SFR(GPIO_IE, 0xC7); // GPIO interrupt enable
#define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge
/* FlashROM and Data-Flash Registers */
SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian
SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM
SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM
SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian
SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing
SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing
SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control
SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian
SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM
SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM
SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian
SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing
SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing
SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control
#define ROM_CMD_WRITE 0x9A // WriteOnly: flash-ROM word or Data-Flash byte write operation command
#define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command
//sfr ROM_STATUS = 0x86; // ReadOnly: flash-ROM status
@ -171,36 +171,36 @@ SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control
#define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command
/* Port Registers */
SFR(P1, 0x90); // port 1 input & output
SBIT(SCK, 0x90, 7); // serial clock for SPI0
SBIT(TXD1, 0x90, 7); // TXD output for UART1
SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key
SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0
SBIT(RXD1, 0x90, 6); // RXD input for UART1
SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key
SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0
SBIT(PWM1, 0x90, 5); // PWM output for PWM1
SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key
SBIT(UCC2, 0x90, 5); // CC2 for USB type-C
SBIT(AIN2, 0x90, 5); // AIN2 for ADC
SBIT(T2_, 0x90, 4); // alternate pin for T2
SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1
SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0
SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key
SBIT(UCC1, 0x90, 4); // CC1 for USB type-C
SBIT(AIN1, 0x90, 4); // AIN1 for ADC
SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0
SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0
SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture
SBIT(CAP2, 0x90, 1); // capture2 input for timer2
SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key
SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C
SBIT(AIN0, 0x90, 1); // AIN0 for ADC
SBIT(T2, 0x90, 0); // external count input
SBIT(CAP1, 0x90, 0); // capture1 input for timer2
SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key
SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain
SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain
SFR(P1, 0x90); // port 1 input & output
SBIT(SCK, 0x90, 7); // serial clock for SPI0
SBIT(TXD1, 0x90, 7); // TXD output for UART1
SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key
SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0
SBIT(RXD1, 0x90, 6); // RXD input for UART1
SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key
SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0
SBIT(PWM1, 0x90, 5); // PWM output for PWM1
SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key
SBIT(UCC2, 0x90, 5); // CC2 for USB type-C
SBIT(AIN2, 0x90, 5); // AIN2 for ADC
SBIT(T2_, 0x90, 4); // alternate pin for T2
SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1
SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0
SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key
SBIT(UCC1, 0x90, 4); // CC1 for USB type-C
SBIT(AIN1, 0x90, 4); // AIN1 for ADC
SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0
SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0
SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture
SBIT(CAP2, 0x90, 1); // capture2 input for timer2
SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key
SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C
SBIT(AIN0, 0x90, 1); // AIN0 for ADC
SBIT(T2, 0x90, 0); // external count input
SBIT(CAP1, 0x90, 0); // capture1 input for timer2
SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key
SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain
SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain
// Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3)
// 0 0: float input only, without pullup resistance
// 0 1: push-pull output, strong driving high level and low level
@ -227,25 +227,25 @@ SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for ope
#define bAIN0 0x02 // AIN0 for ADC
#define bT2 0x01 // external count input or clock output for timer2
#define bCAP1 bT2 // capture1 input for timer2
SFR(P2, 0xA0); // port 2
SFR(P3, 0xB0); // port 3 input & output
SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input
SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input
SBIT(T1, 0xB0, 5); // external count input for timer1
SBIT(PWM2, 0xB0, 4); // PWM output for PWM2
SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1
SBIT(T0, 0xB0, 4); // external count input for timer0
SBIT(INT1, 0xB0, 3); // external interrupt 1 input
SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1
SBIT(INT0, 0xB0, 2); // external interrupt 0 input
SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C
SBIT(AIN3, 0xB0, 2); // AIN3 for ADC
SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2
SBIT(TXD, 0xB0, 1); // TXD output for UART0
SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1
SBIT(RXD, 0xB0, 0); // RXD input for UART0
SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain
SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain
SFR(P2, 0xA0); // port 2
SFR(P3, 0xB0); // port 3 input & output
SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input
SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input
SBIT(T1, 0xB0, 5); // external count input for timer1
SBIT(PWM2, 0xB0, 4); // PWM output for PWM2
SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1
SBIT(T0, 0xB0, 4); // external count input for timer0
SBIT(INT1, 0xB0, 3); // external interrupt 1 input
SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1
SBIT(INT0, 0xB0, 2); // external interrupt 0 input
SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C
SBIT(AIN3, 0xB0, 2); // AIN3 for ADC
SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2
SBIT(TXD, 0xB0, 1); // TXD output for UART0
SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1
SBIT(RXD, 0xB0, 0); // RXD input for UART0
SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain
SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain
#define bUDM 0x80 // ReadOnly: pin UDM input
#define bUDP 0x40 // ReadOnly: pin UDP input
#define bT1 0x20 // external count input for timer1
@ -261,7 +261,7 @@ SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for ope
#define bTXD 0x02 // TXD output for UART0
#define bPWM1_ 0x01 // alternate pin for PWM1
#define bRXD 0x01 // RXD input for UART0
SFR(PIN_FUNC, 0xC6); // pin function selection
SFR(PIN_FUNC, 0xC6); // pin function selection
#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
#define bIO_INT_ACT 0x40 // ReadOnly: GPIO interrupt request action status
#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
@ -270,25 +270,25 @@ SFR(PIN_FUNC, 0xC6); // pin function selection
#define bPWM1_PIN_X 0x04 // PWM1 alternate pin enable: 0=PWM1 on P1.5, 1=PWM1 on P3.0
#define bT2EX_PIN_X 0x02 // T2EX/CAP2 alternate pin enable: 0=T2EX/CAP2 on P1.1, 1=T2EX/CAP2 on RST
#define bT2_PIN_X 0x01 // T2/CAP1 alternate pin enable: 0=T2/CAP1 on P1.1, 1=T2/CAP1 on P1.4
SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting
#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status
#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status
SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting
#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmit status
#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receive status
#define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status
#define GF2 0x08 // general purpose flag bit 2
#define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction
#define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected
/* Timer0/1 Registers */
SFR(TCON, 0x88); // timer 0/1 control and external interrupt control
SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(TR1, 0x88, 6); // timer1 run enable
SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(TR0, 0x88, 4); // timer0 run enable
SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action
SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action
SFR(TMOD, 0x89); // timer 0/1 mode
SFR(TCON, 0x88); // timer 0/1 control and external interrupt control
SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(TR1, 0x88, 6); // timer1 run enable
SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(TR0, 0x88, 4); // timer0 run enable
SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action
SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine
SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action
SFR(TMOD, 0x89); // timer 0/1 mode
#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
#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
#define bT1_M1 0x20 // timer1 mode high bit
@ -309,41 +309,41 @@ SFR(TMOD, 0x89); // timer 0/1 mode
// 01: mode 1, 16-bit timer or counter by cascaded TH0 and TL0
// 10: mode 2, TL0 operates as 8-bit timer or counter, and TH0 provide initial value for TL0 auto-reload
// 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
SFR(TL0, 0x8A); // low byte of timer 0 count
SFR(TL1, 0x8B); // low byte of timer 1 count
SFR(TH0, 0x8C); // high byte of timer 0 count
SFR(TH1, 0x8D); // high byte of timer 1 count
SFR(TL0, 0x8A); // low byte of timer 0 count
SFR(TL1, 0x8B); // low byte of timer 1 count
SFR(TH0, 0x8C); // high byte of timer 0 count
SFR(TH1, 0x8D); // high byte of timer 1 count
/* UART0 Registers */
SFR(SCON, 0x98); // UART0 control (serial port control)
SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data
SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable
SFR(SCON, 0x98); // UART0 control (serial port control)
SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data
SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable
// SM0 & SM1: UART0 mode
// 00 - mode 0, shift Register, baud rate fixed at: Fsys/12
// 01 - mode 1, 8-bit UART, baud rate = variable by timer1 or timer2 overflow rate
// 10 - mode 2, 9-bit UART, baud rate fixed at: Fsys/128@SMOD=0, Fsys/32@SMOD=1
// 11 - mode 3, 9-bit UART, baud rate = variable by timer1 or timer2 overflow rate
SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3
SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3
#define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode
SBIT(REN, 0x98, 4); // enable UART0 receiving
SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3
SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1
SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear
SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear
SFR(SBUF, 0x99); // UART0 data buffer: reading for receiving, writing for transmittal
SBIT(REN, 0x98, 4); // enable UART0 receive
SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3
SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1
SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmit, need software clear
SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receive, need software clear
SFR(SBUF, 0x99); // UART0 data buffer: reading for receive, writing for transmit
/* Timer2/Capture2 Registers */
SFR(T2CON, 0xC8); // timer 2 control
SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1
SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear
SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear
SBIT(RCLK, 0xC8, 5); // selection UART0 receiving clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse
SBIT(TCLK, 0xC8, 4); // selection UART0 transmittal clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse
SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge
SBIT(TR2, 0xC8, 2); // timer2 run enable
SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge
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
SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode
SFR(T2CON, 0xC8); // timer 2 control
SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1
SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear
SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear
SBIT(RCLK, 0xC8, 5); // selection UART0 receive clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse
SBIT(TCLK, 0xC8, 4); // selection UART0 transmit clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse
SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge
SBIT(TR2, 0xC8, 2); // timer2 run enable
SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge
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
SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode
#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
#define bT2_CLK 0x40 // timer2 internal clock frequency selection: 0=standard clock, Fsys/12 for timer mode, Fsys/4 for UART0 clock mode,
// 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
@ -357,20 +357,20 @@ SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode
// 11: from rising edge to rising edge
#define T2OE 0x02 // enable timer2 generated clock output: 0=disable output, 1=enable clock output at T2 pin, frequency = TF2/2
#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
SFR16(RCAP2, 0xCA); // reload & capture value, little-endian
SFR(RCAP2L, 0xCA); // low byte of reload & capture value
SFR(RCAP2H, 0xCB); // high byte of reload & capture value
SFR16(T2COUNT, 0xCC); // counter, little-endian
SFR(TL2, 0xCC); // low byte of timer 2 count
SFR(TH2, 0xCD); // high byte of timer 2 count
SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2
SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2
SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2
SFR16(RCAP2, 0xCA); // reload & capture value, little-endian
SFR(RCAP2L, 0xCA); // low byte of reload & capture value
SFR(RCAP2H, 0xCB); // high byte of reload & capture value
SFR16(T2COUNT, 0xCC); // counter, little-endian
SFR(TL2, 0xCC); // low byte of timer 2 count
SFR(TH2, 0xCD); // high byte of timer 2 count
SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2
SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2
SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2
/* PWM1/2 Registers */
SFR(PWM_DATA2, 0x9B); // PWM data for PWM2
SFR(PWM_DATA1, 0x9C); // PWM data for PWM1
SFR(PWM_CTRL, 0x9D); // PWM 1/2 control
SFR(PWM_DATA2, 0x9B); // PWM data for PWM2
SFR(PWM_DATA1, 0x9C); // PWM data for PWM1
SFR(PWM_CTRL, 0x9D); // PWM 1/2 control
#define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end
#define bPWM2_POLAR 0x40 // PWM2 output polarity: 0=default low and high action, 1=default high and low action
#define bPWM1_POLAR 0x20 // PWM1 output polarity: 0=default low and high action, 1=default high and low action
@ -378,19 +378,19 @@ SFR(PWM_CTRL, 0x9D); // PWM 1/2 control
#define bPWM2_OUT_EN 0x08 // PWM2 output enable
#define bPWM1_OUT_EN 0x04 // PWM1 output enable
#define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2
SFR(PWM_CK_SE, 0x9E); // clock divisor setting
SFR(PWM_CK_SE, 0x9E); // clock divisor setting
/* SPI0/Master0/Slave Registers */
SFR(SPI0_STAT, 0xF8); // SPI 0 status
SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0
SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear
SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear
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
SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status
SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0
SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0
SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receiving, writing for transmittal
SFR(SPI0_CTRL, 0xFA); // SPI 0 control
SFR(SPI0_STAT, 0xF8); // SPI 0 status
SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0
SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear
SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear
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
SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status
SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0
SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0
SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receive, writing for transmit
SFR(SPI0_CTRL, 0xFA); // SPI 0 control
#define bS0_MISO_OE 0x80 // SPI0 MISO output enable
#define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable
#define bS0_SCK_OE 0x20 // SPI0 SCK output enable
@ -399,10 +399,10 @@ SFR(SPI0_CTRL, 0xFA); // SPI 0 control
#define bS0_2_WIRE 0x04 // enable SPI0 two wire mode: 0=3 wire (SCK+MOSI+MISO), 1=2 wire (SCK+MISO)
#define bS0_CLR_ALL 0x02 // force clear FIFO and count of SPI0
#define bS0_AUTO_IF 0x01 // enable FIFO accessing to auto clear S0_IF_BYTE interrupt flag
SFR(SPI0_CK_SE, 0xFB); // clock divisor setting
SFR(SPI0_CK_SE, 0xFB); // clock divisor setting
//sfr SPI0_S_PRE = 0xFB; // preset value for SPI slave
#define SPI0_S_PRE SPI0_CK_SE
SFR(SPI0_SETUP, 0xFC); // SPI 0 setup
SFR(SPI0_SETUP, 0xFC); // SPI 0 setup
#define bS0_MODE_SLV 0x80 // SPI0 slave mode: 0=master, 1=slave
#define bS0_IE_FIFO_OV 0x40 // enable interrupt for slave mode FIFO overflow
#define bS0_IE_FIRST 0x20 // enable interrupt for first byte received for SPI0 slave mode
@ -412,39 +412,39 @@ SFR(SPI0_SETUP, 0xFC); // SPI 0 setup
#define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection
/* UART1 Registers */
SFR(SCON1, 0xC0); // UART1 control (serial port control)
SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data
SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1))
SBIT(U1REN, 0xC0, 4); // enable UART1 receiving
SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode
SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode
SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear
SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear
SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receiving, writing for transmittal
SFR(SBAUD1, 0xC2); // UART1 baud rate setting
SFR(SCON1, 0xC0); // UART1 control (serial port control)
SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data
SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1))
SBIT(U1REN, 0xC0, 4); // enable UART1 receive
SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode
SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode
SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmit, need software clear
SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receive, need software clear
SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receive, writing for transmit
SFR(SBAUD1, 0xC2); // UART1 baud rate setting
/* ADC and comparator Registers */
SFR(ADC_CTRL, 0x80); // ADC control
SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input
SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear
SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear
SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished
SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3
SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit
SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit
SFR(ADC_CTRL, 0x80); // ADC control
SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input
SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear
SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear
SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished
SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3
SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit
SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit
// ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection
// 00: AIN0(P1.1)
// 01: AIN1(P1.4)
// 10: AIN2(P1.5)
// 11: AIN3(P3.2)
SFR(ADC_CFG, 0x9A); // ADC config
SFR(ADC_CFG, 0x9A); // ADC config
#define bADC_EN 0x08 // control ADC power: 0=shut down ADC, 1=enable power for ADC
#define bCMP_EN 0x04 // control comparator power: 0=shut down comparator, 1=enable power for comparator
#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
SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data
SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data
/* Touch-key timer Registers */
SFR(TKEY_CTRL, 0xC3); // touch-key control
SFR(TKEY_CTRL, 0xC3); // touch-key control
#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
#define bTKC_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS
#define bTKC_CHAN2 0x04 // touch-key channel selection high bit
@ -459,13 +459,13 @@ SFR(TKEY_CTRL, 0xC3); // touch-key control
// 101: TIN4(P1.6)
// 110: TIN5(P1.7)
// 111: enable touch-key but disable all channel
SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian
SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data
SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data
SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian
SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data
SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data
#define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid
/* USB/Host/Device Registers */
SFR(USB_C_CTRL, 0x91); // USB type-C control
SFR(USB_C_CTRL, 0x91); // USB type-C control
#define bVBUS2_PD_EN 0x80 // USB VBUS2 10K pulldown resistance: 0=disable, 1=enable pullup
#define bUCC2_PD_EN 0x40 // USB CC2 5.1K pulldown resistance: 0=disable, 1=enable pulldown
#define bUCC2_PU1_EN 0x20 // USB CC2 pullup resistance control high bit
@ -479,7 +479,7 @@ SFR(USB_C_CTRL, 0x91); // USB type-C control
// 01: enable 56K pullup resistance for default USB power
// 10: enable 22K pullup resistance for 1.5A USB power
// 11: enable 10K pullup resistance for 3A USB power
SFR(UDEV_CTRL, 0xD1); // USB device physical port control
SFR(UDEV_CTRL, 0xD1); // USB device physical port control
#define bUD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
#define bUD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
#define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
@ -494,50 +494,50 @@ SFR(UDEV_CTRL, 0xD1); // USB device physical port control
#define bUH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
#define bUH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
#define bUH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
SFR(UEP1_CTRL, 0xD2); // endpoint 1 control
#define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
#define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
SFR(UEP1_CTRL, 0xD2); // endpoint 1 control
#define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receive (OUT): 0=DATA0, 1=DATA1
#define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmit (IN): 0=DATA0, 1=DATA1
#define bUEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
#define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT)
#define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT)
#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT)
#define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receive (OUT)
#define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receive (OUT)
#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receive (OUT)
#define UEP_R_RES_ACK 0x00
#define UEP_R_RES_TOUT 0x04
#define UEP_R_RES_NAK 0x08
#define UEP_R_RES_STALL 0x0C
// bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receiving (OUT)
// bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receive (OUT)
// 00: ACK (ready)
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
// 10: NAK (busy)
// 11: STALL (error)
#define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN)
#define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN)
#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
#define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmit (IN)
#define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmit (IN)
#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmit (IN)
#define UEP_T_RES_ACK 0x00
#define UEP_T_RES_TOUT 0x01
#define UEP_T_RES_NAK 0x02
#define UEP_T_RES_STALL 0x03
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmit (IN)
// 00: DATA0 or DATA1 then expecting ACK (ready)
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
// 10: NAK (busy)
// 11: STALL (error)
SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length
SFR(UEP2_CTRL, 0xD4); // endpoint 2 control
SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length
SFR(UEP3_CTRL, 0xD6); // endpoint 3 control
SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length
SFR(USB_INT_FG, 0xD8); // USB interrupt flag
SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received
SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK
SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status
SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status
SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmit length
SFR(UEP2_CTRL, 0xD4); // endpoint 2 control
SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmit length
SFR(UEP3_CTRL, 0xD6); // endpoint 3 control
SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmit length
SFR(USB_INT_FG, 0xD8); // USB interrupt flag
SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received
SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK
SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status
SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status
#define bUIS_IS_NAK 0x80 // ReadOnly: indicate current USB transfer is NAK received for USB device mode
#define bUIS_TOG_OK 0x40 // ReadOnly: indicate current USB transfer toggle is OK
#define bUIS_TOKEN1 0x20 // ReadOnly: current token PID code bit 1 received for USB device mode
@ -554,21 +554,21 @@ SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status
// 11: SETUP token PID received
#define MASK_UIS_ENDP 0x0F // ReadOnly: bit mask of current transfer endpoint number for USB device mode
#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
SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status
SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status
#define bUMS_SOF_PRES 0x80 // ReadOnly: indicate host SOF timer presage status
#define bUMS_SOF_ACT 0x40 // ReadOnly: indicate host SOF timer action status for USB host
#define bUMS_SIE_FREE 0x20 // ReadOnly: indicate USB SIE free status
#define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receiving FIFO ready status (not empty)
#define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receive FIFO ready status (not empty)
#define bUMS_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status
#define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend status
#define bUMS_DM_LEVEL 0x02 // ReadOnly: indicate UDM level saved at device attached to USB host
#define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host
SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length
SFR(UEP0_CTRL, 0xDC); // endpoint 0 control
SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length
SFR(UEP4_CTRL, 0xDE); // endpoint 4 control
SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length
SFR(USB_INT_EN, 0xE1); // USB interrupt enable
SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receive length
SFR(UEP0_CTRL, 0xDC); // endpoint 0 control
SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmit length
SFR(UEP4_CTRL, 0xDE); // endpoint 4 control
SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmit length
SFR(USB_INT_EN, 0xE1); // USB interrupt enable
#define bUIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode
#define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
#define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
@ -577,7 +577,7 @@ SFR(USB_INT_EN, 0xE1); // USB interrupt enable
#define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
#define bUIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode
#define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode
SFR(USB_CTRL, 0xE2); // USB base control
SFR(USB_CTRL, 0xE2); // USB base control
#define bUC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode
#define bUC_LOW_SPEED 0x40 // enable USB low speed: 0=full speed, 1=low speed
#define bUC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable
@ -596,82 +596,82 @@ SFR(USB_CTRL, 0xE2); // USB base control
#define bUC_RESET_SIE 0x04 // force reset USB SIE, need software clear
#define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB
#define bUC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB
SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address
SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address
#define bUDA_GP_BIT 0x80 // general purpose bit
#define MASK_USB_ADDR 0x7F // bit mask for USB device address
SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian
SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte
SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte
SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian
SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte
SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte
SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode
#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian
SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte
SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte
SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian
SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte
SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte
SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode
#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receive (OUT)
#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmit (IN)
#define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
// bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA
// 0 0 x: disable endpoint and disable buffer
// 1 0 0: 64 bytes buffer for receiving (OUT endpoint)
// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes
// 0 1 0: 64 bytes buffer for transmittal (IN endpoint)
// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes
// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes
// 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
#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
// 1 0 0: 64 bytes buffer for receive (OUT endpoint)
// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receive (OUT endpoint), total=128bytes
// 0 1 0: 64 bytes buffer for transmit (IN endpoint)
// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmit (IN endpoint), total=128bytes
// 1 1 0: 64 bytes buffer for receive (OUT endpoint) + 64 bytes buffer for transmit (IN endpoint), total=128bytes
// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receive (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmit (IN endpoint), total=256bytes
#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receive (OUT)
#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmit (IN)
// bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA
// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
// 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
// 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
// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint)
// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes
SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode
#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
// 0 0: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint)
// 1 0: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receive (OUT endpoint), total=128bytes
// 0 1: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmit (IN endpoint), total=128bytes
// 1 1: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint)
// + 64 bytes buffer for endpoint 4 receive (OUT endpoint) + 64 bytes buffer for endpoint 4 transmit (IN endpoint), total=192bytes
SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode
#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receive (OUT)
#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmit (IN)
#define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receive (OUT)
#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmit (IN)
#define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian
SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte
SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte
SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian
SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte
SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte
SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian
SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte
SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte
SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian
SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte
SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte
//sfr UH_SETUP = 0xD2; // host aux setup
#define UH_SETUP UEP1_CTRL
#define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub
#define bUH_SOF_EN 0x40 // USB host automatic SOF enable
//sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control
#define UH_RX_CTRL UEP2_CTRL
#define bUH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
#define bUH_R_TOG 0x80 // expected data toggle flag of host receive (IN): 0=DATA0, 1=DATA1
#define bUH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#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
#define bUH_R_RES 0x04 // prepared handshake response type for host receive (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
//sfr UH_EP_PID = 0xD5; // host endpoint and token PID, lower 4 bits for endpoint number, upper 4 bits for token PID
#define UH_EP_PID UEP2_T_LEN
#define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer
#define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer
//sfr UH_TX_CTRL = 0xD6; // host transmittal endpoint control
//sfr UH_TX_CTRL = 0xD6; // host transmit endpoint control
#define UH_TX_CTRL UEP3_CTRL
#define bUH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
#define bUH_T_TOG 0x40 // prepared data toggle flag of host transmit (SETUP/OUT): 0=DATA0, 1=DATA1
#define bUH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
#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
//sfr UH_TX_LEN = 0xD7; // host transmittal endpoint transmittal length
#define bUH_T_RES 0x01 // expected handshake response type for host transmit (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
//sfr UH_TX_LEN = 0xD7; // host transmit endpoint transmit length
#define UH_TX_LEN UEP3_T_LEN
//sfr UH_EP_MOD = 0xEB; // host endpoint mode
#define UH_EP_MOD UEP2_3_MOD
#define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
#define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmit
#define bUH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
// 0 x: disable endpoint and disable buffer
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
#define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
// 1 0: 64 bytes buffer for transmit (OUT endpoint)
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmit (OUT endpoint), total=128bytes
#define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receive
#define bUH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
// 0 x: disable endpoint and disable buffer
// 1 0: 64 bytes buffer for receiving (IN endpoint)
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
// 1 0: 64 bytes buffer for receive (IN endpoint)
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receive (IN endpoint), total=128bytes
//sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian
#define UH_RX_DMA UEP2_DMA
//sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte

View File

@ -11,6 +11,8 @@ Header file for CH554 microcontrollers.
#ifndef __USB_DEF__
#define __USB_DEF__
#include "mem.h"
/*----- USB constant and structure define --------------------------------*/
/* USB PID */
@ -53,34 +55,41 @@ Header file for CH554 microcontrollers.
#define HUB_SET_DESCRIPTOR 0x07
#endif
/* USB HID class request code */
#ifndef HID_GET_REPORT
#define HID_GET_REPORT 0x01
#define HID_GET_IDLE 0x02
#define HID_GET_PROTOCOL 0x03
#define HID_SET_REPORT 0x09
#define HID_SET_IDLE 0x0A
#define HID_SET_PROTOCOL 0x0B
#endif
/* Bit define for USB request type */
#ifndef USB_REQ_TYP_MASK
#define USB_REQ_TYP_IN 0x80 /* control IN, device to host */
#define USB_REQ_TYP_OUT 0x00 /* control OUT, host to device */
#define USB_REQ_TYP_READ 0x80 /* control read, device to host */
#define USB_REQ_TYP_WRITE 0x00 /* control write, host to device */
#define USB_REQ_TYP_MASK 0x60 /* bit mask of request type */
#define USB_REQ_TYP_STANDARD 0x00
#define USB_REQ_TYP_CLASS 0x20
#define USB_REQ_TYP_VENDOR 0x40
#define USB_REQ_TYP_RESERVED 0x60
#define USB_REQ_RECIP_MASK 0x1F /* bit mask of request recipient */
#ifndef USB_REQ_TYPE_MASK
#define USB_REQ_TYPE_IN 0x80 /* Control IN, device to host */
#define USB_REQ_TYPE_OUT 0x00 /* Control OUT, host to device */
#define USB_REQ_TYPE_READ 0x80 /* Control read, device to host */
#define USB_REQ_TYPE_WRITE 0x00 /* Control write, host to device */
#define USB_REQ_TYPE_MASK 0x60 /* Bit mask of request type */
#define USB_REQ_TYPE_STANDARD 0x00
#define USB_REQ_TYPE_CLASS 0x20
#define USB_REQ_TYPE_VENDOR 0x40
#define USB_REQ_TYPE_RESERVED 0x60
#define USB_REQ_RECIP_MASK 0x1F /* Bit mask of request recipient */
#define USB_REQ_RECIP_DEVICE 0x00
#define USB_REQ_RECIP_INTERF 0x01
#define USB_REQ_RECIP_ENDP 0x02
#define USB_REQ_RECIP_OTHER 0x03
#endif
/* USB HID class request code */
#ifndef USB_HID_REQ_TYPE
#define USB_HID_REQ_TYPE_GET_REPORT 0x01
#define USB_HID_REQ_TYPE_GET_IDLE 0x02
#define USB_HID_REQ_TYPE_GET_PROTOCOL 0x03
#define USB_HID_REQ_TYPE_SET_REPORT 0x09
#define USB_HID_REQ_TYPE_SET_IDLE 0x0A
#define USB_HID_REQ_TYPE_SET_PROTOCOL 0x0B
#endif
/* USB CDC class request code */
#ifndef USB_CDC_REQ_TYPE
#define USB_CDC_REQ_TYPE_SET_LINE_CODING 0x20
#define USB_CDC_REQ_TYPE_GET_LINE_CODING 0x21
#define USB_CDC_REQ_TYPE_SET_CONTROL_LINE_STATE 0x22
#endif
/* USB request type for hub class request */
#ifndef HUB_GET_HUB_DESCRIPTOR
#define HUB_CLEAR_HUB_FEATURE 0x20
@ -96,95 +105,129 @@ Header file for CH554 microcontrollers.
/* Hub class feature selectors */
#ifndef HUB_PORT_RESET
#define HUB_C_HUB_LOCAL_POWER 0
#define HUB_C_HUB_OVER_CURRENT 1
#define HUB_PORT_CONNECTION 0
#define HUB_PORT_ENABLE 1
#define HUB_PORT_SUSPEND 2
#define HUB_PORT_OVER_CURRENT 3
#define HUB_PORT_RESET 4
#define HUB_PORT_POWER 8
#define HUB_PORT_LOW_SPEED 9
#define HUB_C_PORT_CONNECTION 16
#define HUB_C_PORT_ENABLE 17
#define HUB_C_PORT_SUSPEND 18
#define HUB_C_PORT_OVER_CURRENT 19
#define HUB_C_PORT_RESET 20
#define HUB_C_HUB_LOCAL_POWER 0
#define HUB_C_HUB_OVER_CURRENT 1
#define HUB_PORT_CONNECTION 0
#define HUB_PORT_ENABLE 1
#define HUB_PORT_SUSPEND 2
#define HUB_PORT_OVER_CURRENT 3
#define HUB_PORT_RESET 4
#define HUB_PORT_POWER 8
#define HUB_PORT_LOW_SPEED 9
#define HUB_C_PORT_CONNECTION 16
#define HUB_C_PORT_ENABLE 17
#define HUB_C_PORT_SUSPEND 18
#define HUB_C_PORT_OVER_CURRENT 19
#define HUB_C_PORT_RESET 20
#endif
/* USB descriptor type */
#ifndef USB_DESCR_TYP_DEVICE
#define USB_DESCR_TYP_DEVICE 0x01
#define USB_DESCR_TYP_CONFIG 0x02
#define USB_DESCR_TYP_STRING 0x03
#define USB_DESCR_TYP_INTERF 0x04
#define USB_DESCR_TYP_ENDP 0x05
#define USB_DESCR_TYP_QUALIF 0x06
#define USB_DESCR_TYP_SPEED 0x07
#define USB_DESCR_TYP_OTG 0x09
#define USB_DESCR_TYP_HID 0x21
#define USB_DESCR_TYP_REPORT 0x22
#define USB_DESCR_TYP_PHYSIC 0x23
#define USB_DESCR_TYP_CS_INTF 0x24
#define USB_DESCR_TYP_CS_ENDP 0x25
#define USB_DESCR_TYP_HUB 0x29
#ifndef USB_DESC_TYPE_DEVICE
#define USB_DESC_TYPE_DEVICE 0x01 // USB 1.1
#define USB_DESC_TYPE_CONFIGURATION 0x02 // USB 1.1
#define USB_DESC_TYPE_STRING 0x03 // USB 1.1
#define USB_DESC_TYPE_INTERFACE 0x04 // USB 1.1
#define USB_DESC_TYPE_ENDPOINT 0x05 // USB 1.1
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 // USB 2.0
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 // USB 2.0
#define USB_DESC_TYPE_INTERFACE_POWER 0x08 // USB 2.0
#define USB_DESC_TYPE_OTG 0x09 // USB 2.0
#define USB_DESC_TYPE_DEBUG 0x0A // USB 2.0
#define USB_DESC_TYPE_INTERFACE_ASSOCIATION 0x0B // USB 2.0
#define USB_DESC_TYPE_BOS 0x0F // USB 3.x (Binary Object Store)
#define USB_DESC_TYPE_DEVICE_CAPABILITY 0x10 // USB 3.x
#define USB_DESC_TYPE_HID 0x21 // HID 1.11
#define USB_DESC_TYPE_REPORT 0x22 // HID 1.11
#define USB_DESC_TYPE_PHYSICAL 0x23 // HID 1.11
#define USB_DESC_TYPE_CS_INTERFACE 0x24 // Class-Specific (Audio, HID, CDC, etc.)
#define USB_DESC_TYPE_CS_ENDPOINT 0x25 // Class-Specific (Audio, Not HID normally, CDC, etc.)
#define USB_DESC_TYPE_SUPERSPEED_USB_ENDPOINT_COMPANION 0x30 // USB 3.x
#define USB_DESC_TYPE_SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION 0x31 // USB 3.x
#endif
/* USB device class */
#ifndef USB_DEV_CLASS_HUB
#define USB_DEV_CLASS_RESERVED 0x00
#define USB_DEV_CLASS_AUDIO 0x01
#define USB_DEV_CLASS_COMMUNIC 0x02
#define USB_DEV_CLASS_HID 0x03
#define USB_DEV_CLASS_MONITOR 0x04
#define USB_DEV_CLASS_PHYSIC_IF 0x05
#define USB_DEV_CLASS_POWER 0x06
#define USB_DEV_CLASS_PRINTER 0x07
#define USB_DEV_CLASS_STORAGE 0x08
#define USB_DEV_CLASS_HUB 0x09
#define USB_DEV_CLASS_VEN_SPEC 0xFF
#ifndef USB_DEV_CLASS
// Descriptor Usage; Description ; Examples
#define USB_DEV_CLASS_RESERVED 0x00 // Device ; Unspecified ; Device class is unspecified, interface descriptors are used to determine needed drivers
#define USB_DEV_CLASS_AUDIO 0x01 // Interface ; Audio ; Speaker, microphone, sound card, MIDI
#define USB_DEV_CLASS_CDC_CONTROL 0x02 // Both ; Communications and CDC control ; UART and RS-232 serial adapter, modem, Wi-Fi adapter, Ethernet adapter. Used together with class 0Ah (CDC-Data) below
#define USB_DEV_CLASS_HID 0x03 // Interface ; Human interface device (HID) ; Keyboard, mouse, joystick
#define USB_DEV_CLASS_PHYSICAL 0x05 // Interface ; Physical interface device (PID) ; Force feedback joystick
#define USB_DEV_CLASS_IMAGE 0x06 // Interface ; Media (PTP/MTP) ; Scanner, Camera
#define USB_DEV_CLASS_PRINTER 0x07 // Interface ; Printer ; Laser printer, inkjet printer, CNC machine
#define USB_DEV_CLASS_MASS_STORAGE 0x08 // Interface ; USB mass storage, USB Attached SCSI ; USB flash drive, memory card reader, digital audio player, digital camera, external drive
#define USB_DEV_CLASS_HUB 0x09 // Device ; USB hub ; High speed USB hub
#define USB_DEV_CLASS_CDC_DATA 0x0A // Interface ; CDC-Data ; Used together with class 02h (Communications and CDC Control) above
#define USB_DEV_CLASS_SMART_CARD 0x0B // Interface ; Smart card ; USB smart card reader
#define USB_DEV_CLASS_CONTENT_SECURITY 0x0D // Interface ; Content security ; Fingerprint reader
#define USB_DEV_CLASS_VIDEO 0x0E // Interface ; Video ; Webcam
#define USB_DEV_CLASS_PERSONAL_HEALTHCARE 0x0F // Interface ; Personal healthcare device class (PHDC) ; Pulse monitor (watch)
#define USB_DEV_CLASS_AUDIO_VIDEO DEVICES 0x10 // Interface ; Audio/Video (AV) ; Webcam, TV
#define USB_DEV_CLASS_BILLBOARD 0x11 // Device ; Billboard ; Describes USB-C alternate modes supported by device
#define USB_DEV_CLASS_USB_TYPE_C_BRIDGE 0x12 // Interface ; ;
#define USB_DEV_CLASS_USB_BULK_DISPLAY 0x13 // Interface ; ;
#define USB_DEV_CLASS_MCTP_OVER_USB 0x14 // Interface ; ;
#define USB_DEV_CLASS_I3C_DEVICE_CLASS 0x3C // Interface ; ;
#define USB_DEV_CLASS_DIAGNOSTIC_DEVICE 0xDC // Both ; Diagnostic device ; USB compliance testing device
#define USB_DEV_CLASS_WIRELESS_CONTROLLER 0xE0 // Interface ; Wireless Controller ; Bluetooth adapter, Microsoft RNDIS
#define USB_DEV_CLASS_MISCELLANEOUS 0xEF // Both ; Miscellaneous ; ActiveSync device
#define USB_DEV_CLASS_APPLICATION_SPECIFIC 0xFE // Interface ; Application-specific ; IrDA Bridge, Test & Measurement Class (USBTMC), USB DFU (Device Firmware Upgrade)
#define USB_DEV_CLASS_VENDOR_SPECIFIC 0xFF // Both ; Vendor-specific ; Indicates that a device needs vendor-specific drivers
#endif
/* USB endpoint type and attributes */
#ifndef USB_ENDP_TYPE_MASK
#define USB_ENDP_DIR_MASK 0x80
#define USB_ENDP_ADDR_MASK 0x0F
#define USB_ENDP_TYPE_MASK 0x03
#define USB_ENDP_TYPE_CTRL 0x00
#define USB_ENDP_TYPE_ISOCH 0x01
#define USB_ENDP_TYPE_BULK 0x02
#define USB_ENDP_TYPE_INTER 0x03
#ifndef USB_EP_TYPE_MASK
#define USB_EP_TYPE_CONTROL 0x00
#define USB_EP_TYPE_ISOCHRONOUS 0x01
#define USB_EP_TYPE_BULK 0x02
#define USB_EP_TYPE_INTERRUPT 0x03
#define USB_EP_DIR_MASK 0x80
#define USB_EP_ADDR_MASK 0x0F
#define USB_EP_TYPE_MASK 0x03
#endif
/* USB string index */
#ifndef USB_IDX_STR
#define USB_IDX_LANGID_STR 0x00
#define USB_IDX_MFC_STR 0x01
#define USB_IDX_PRODUCT_STR 0x02
#define USB_IDX_SERIAL_STR 0x03
#define USB_IDX_INTERFACE_CDC_CTRL_STR 0x04
#define USB_IDX_INTERFACE_CDC_DATA_STR 0x05
#define USB_IDX_INTERFACE_FIDO_HID_STR 0x06
#define USB_IDX_INTERFACE_TKEY_CTRL_STR 0x07
#endif
#ifndef USB_DEVICE_ADDR
#define USB_DEVICE_ADDR 0x02 /* 默认的USB设备地址 */
#define USB_DEVICE_ADDR 0x02
#endif
#ifndef DEFAULT_ENDP0_SIZE
#define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */
#ifndef DEFAULT_EP0_SIZE
#define DEFAULT_EP0_SIZE 64 /* Default maximum packet size for Endpoint 0 */
#endif
#ifndef DEFAULT_ENDP1_SIZE
#define DEFAULT_ENDP1_SIZE 8 /* default maximum packet size for endpoint 1 */
#ifndef DEFAULT_EP1_SIZE
#define DEFAULT_EP1_SIZE 8 /* Default maximum packet size for Endpoint 1 */
#endif
#ifndef MAX_PACKET_SIZE
#define MAX_PACKET_SIZE 64 /* maximum packet size */
#define MAX_PACKET_SIZE 64 /* Maximum packet size */
#endif
#ifndef USB_BO_CBW_SIZE
#define USB_BO_CBW_SIZE 0x1F /* 命令块CBW的总长度 */
#define USB_BO_CSW_SIZE 0x0D /* 命令状态块CSW的总长度 */
#define USB_BO_CBW_SIZE 0x1F
#define USB_BO_CSW_SIZE 0x0D
#endif
#ifndef USB_BO_CBW_SIG0
#define USB_BO_CBW_SIG0 0x55 /* 命令块CBW识别标志'USBC' */
#define USB_BO_CBW_SIG0 0x55
#define USB_BO_CBW_SIG1 0x53
#define USB_BO_CBW_SIG2 0x42
#define USB_BO_CBW_SIG3 0x43
#define USB_BO_CSW_SIG0 0x55 /* 命令状态块CSW识别标志'USBS' */
#define USB_BO_CSW_SIG0 0x55
#define USB_BO_CSW_SIG1 0x53
#define USB_BO_CSW_SIG2 0x42
#define USB_BO_CSW_SIG3 0x53
#endif
typedef struct _USB_SETUP_REQ {
uint8_t bRequestType;
uint8_t bmRequestType;
uint8_t bRequest;
uint8_t wValueL;
uint8_t wValueH;
@ -194,7 +237,7 @@ typedef struct _USB_SETUP_REQ {
uint8_t wLengthH;
} USB_SETUP_REQ, *PUSB_SETUP_REQ;
typedef USB_SETUP_REQ __xdata *PXUSB_SETUP_REQ;
typedef USB_SETUP_REQ XDATA *PXUSB_SETUP_REQ;
typedef struct _USB_DEVICE_DESCR {
uint8_t bLength;
@ -217,7 +260,7 @@ typedef struct _USB_DEVICE_DESCR {
uint8_t bNumConfigurations;
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
typedef USB_DEV_DESCR __xdata *PXUSB_DEV_DESCR;
typedef USB_DEV_DESCR XDATA *PXUSB_DEV_DESCR;
typedef struct _USB_CONFIG_DESCR {
uint8_t bLength;
@ -231,7 +274,7 @@ typedef struct _USB_CONFIG_DESCR {
uint8_t MaxPower;
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
typedef USB_CFG_DESCR __xdata *PXUSB_CFG_DESCR;
typedef USB_CFG_DESCR XDATA *PXUSB_CFG_DESCR;
typedef struct _USB_INTERF_DESCR {
uint8_t bLength;
@ -245,7 +288,7 @@ typedef struct _USB_INTERF_DESCR {
uint8_t iInterface;
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
typedef USB_ITF_DESCR __xdata *PXUSB_ITF_DESCR;
typedef USB_ITF_DESCR XDATA *PXUSB_ITF_DESCR;
typedef struct _USB_ENDPOINT_DESCR {
uint8_t bLength;
@ -257,7 +300,7 @@ typedef struct _USB_ENDPOINT_DESCR {
uint8_t bInterval;
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
typedef USB_ENDP_DESCR __xdata *PXUSB_ENDP_DESCR;
typedef USB_ENDP_DESCR XDATA *PXUSB_ENDP_DESCR;
typedef struct _USB_CONFIG_DESCR_LONG {
USB_CFG_DESCR cfg_descr;
@ -265,7 +308,7 @@ typedef struct _USB_CONFIG_DESCR_LONG {
USB_ENDP_DESCR endp_descr[1];
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
typedef USB_CFG_DESCR_LONG __xdata *PXUSB_CFG_DESCR_LONG;
typedef USB_CFG_DESCR_LONG XDATA *PXUSB_CFG_DESCR_LONG;
typedef struct _USB_HUB_DESCR {
uint8_t bDescLength;
@ -279,7 +322,7 @@ typedef struct _USB_HUB_DESCR {
uint8_t PortPwrCtrlMask;
} USB_HUB_DESCR, *PUSB_HUB_DESCR;
typedef USB_HUB_DESCR __xdata *PXUSB_HUB_DESCR;
typedef USB_HUB_DESCR XDATA *PXUSB_HUB_DESCR;
typedef struct _USB_HID_DESCR {
uint8_t bLength;
@ -293,9 +336,9 @@ typedef struct _USB_HID_DESCR {
uint8_t wDescriptorLengthH;
} USB_HID_DESCR, *PUSB_HID_DESCR;
typedef USB_HID_DESCR __xdata *PXUSB_HID_DESCR;
typedef USB_HID_DESCR XDATA *PXUSB_HID_DESCR;
typedef struct _UDISK_BOC_CBW { /* command of BulkOnly USB-FlashDisk */
typedef struct _UDISK_BOC_CBW { /* Command of BulkOnly USB-FlashDisk */
uint8_t mCBW_Sig0;
uint8_t mCBW_Sig1;
uint8_t mCBW_Sig2;
@ -307,16 +350,16 @@ typedef struct _UDISK_BOC_CBW { /* command of BulkOnly USB-FlashDisk */
uint8_t mCBW_DataLen0;
uint8_t mCBW_DataLen1;
uint8_t mCBW_DataLen2;
uint8_t mCBW_DataLen3; /* uppest byte of data length, always is 0 */
uint8_t mCBW_Flag; /* transfer direction and etc. */
uint8_t mCBW_DataLen3; /* MSB byte of data length, always is 0 */
uint8_t mCBW_Flag; /* Transfer direction and etc. */
uint8_t mCBW_LUN;
uint8_t mCBW_CB_Len; /* length of command block */
uint8_t mCBW_CB_Buf[16]; /* command block buffer */
uint8_t mCBW_CB_Len; /* Length of command block */
uint8_t mCBW_CB_Buf[16]; /* Command block buffer */
} UDISK_BOC_CBW, *PUDISK_BOC_CBW;
typedef UDISK_BOC_CBW __xdata *PXUDISK_BOC_CBW;
typedef UDISK_BOC_CBW XDATA *PXUDISK_BOC_CBW;
typedef struct _UDISK_BOC_CSW { /* status of BulkOnly USB-FlashDisk */
typedef struct _UDISK_BOC_CSW { /* Status of BulkOnly USB-FlashDisk */
uint8_t mCSW_Sig0;
uint8_t mCSW_Sig1;
uint8_t mCSW_Sig2;
@ -325,13 +368,13 @@ typedef struct _UDISK_BOC_CSW { /* status of BulkOnly USB-FlashDisk */
uint8_t mCSW_Tag1;
uint8_t mCSW_Tag2;
uint8_t mCSW_Tag3;
uint8_t mCSW_Residue0; /* return: remainder bytes */
uint8_t mCSW_Residue0; /* Return: remainder bytes */
uint8_t mCSW_Residue1;
uint8_t mCSW_Residue2;
uint8_t mCSW_Residue3; /* uppest byte of remainder length, always is 0 */
uint8_t mCSW_Status; /* return: result status */
uint8_t mCSW_Residue3; /* MSB byte of remainder length, always is 0 */
uint8_t mCSW_Status; /* Return: result status */
} UDISK_BOC_CSW, *PUDISK_BOC_CSW;
typedef UDISK_BOC_CSW __xdata *PXUDISK_BOC_CSW;
typedef UDISK_BOC_CSW XDATA *PXUDISK_BOC_CSW;
#endif // __USB_DEF__

View File

@ -4,10 +4,10 @@
* Version : V1.0
* Date : 2017/01/20
* Description : CH554 DEBUG Interface
CH554 main frequency modification, delay function definition
                     Serial port 0 and serial port 1 initialization
                     Serial port 0 and serial port 1 transceiver subfunctions
                     Watchdog initialization
CH554 main frequency modification, delay function definition
Serial port 0 and serial port 1 initialization
Serial port 0 and serial port 1 transceiver subfunctions
Watchdog initialization
*******************************************************************************/
#include <stdint.h>
@ -17,42 +17,40 @@
/*******************************************************************************
* Function Name : CfgFsys( )
* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed
                 CLOCK_CFG configuration, the formula is as follows:
                 Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself
* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed
CLOCK_CFG configuration, the formula is as follows:
Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself
*******************************************************************************/
void CfgFsys( )
void CfgFsys()
{
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal
// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal
// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal
#if FREQ_SYS == 32000000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz
#elif FREQ_SYS == 24000000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz
#elif FREQ_SYS == 16000000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz
#elif FREQ_SYS == 12000000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz
#elif FREQ_SYS == 6000000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz
#elif FREQ_SYS == 3000000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz
#elif FREQ_SYS == 750000
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz
#elif FREQ_SYS == 187500
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz
#else
#warning FREQ_SYS invalid or not set
#warning FREQ_SYS invalid or not set
#endif
SAFE_MOD = 0x00;
SAFE_MOD = 0x00;
}
/*******************************************************************************
* Function Name : mDelayus(UNIT16 n)
* Description : us delay function
@ -60,55 +58,55 @@ void CfgFsys( )
* Output : None
* Return : None
*******************************************************************************/
void mDelayuS( uint16_t n ) // Delay in uS
void mDelayuS(uint16_t n) // Delay in uS
{
#ifdef FREQ_SYS
#if FREQ_SYS <= 6000000
n >>= 2;
#ifdef FREQ_SYS
#if FREQ_SYS <= 6000000
n >>= 2;
#endif
#if FREQ_SYS <= 3000000
n >>= 2;
#endif
#if FREQ_SYS <= 750000
n >>= 4;
#endif
#endif
#if FREQ_SYS <= 3000000
n >>= 2;
while (n) { // Total = 12~13 Fsys cycles, 1uS @Fsys=12MHz
++SAFE_MOD; // 2 Fsys cycles, for higher Fsys, add operation here
#ifdef FREQ_SYS
#if FREQ_SYS >= 14000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 16000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 18000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 20000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 22000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 24000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 26000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 28000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 30000000
++SAFE_MOD;
#endif
#if FREQ_SYS >= 32000000
++SAFE_MOD;
#endif
#endif
#if FREQ_SYS <= 750000
n >>= 4;
#endif
#endif
while ( n ) { // total = 12~13 Fsys cycles, 1uS @Fsys=12MHz
++ SAFE_MOD; // 2 Fsys cycles, for higher Fsys, add operation here
#ifdef FREQ_SYS
#if FREQ_SYS >= 14000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 16000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 18000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 20000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 22000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 24000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 26000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 28000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 30000000
++ SAFE_MOD;
#endif
#if FREQ_SYS >= 32000000
++ SAFE_MOD;
#endif
#endif
-- n;
}
--n;
}
}
/*******************************************************************************
@ -118,17 +116,17 @@ void mDelayuS( uint16_t n ) // Delay in uS
* Output : None
* Return : None
*******************************************************************************/
void mDelaymS( uint16_t n ) // Delay in mS
void mDelaymS(uint16_t n) // Delay in mS
{
while ( n ) {
#ifdef DELAY_MS_HW
while ( ( TKEY_CTRL & bTKC_IF ) == 0 );
while ( TKEY_CTRL & bTKC_IF );
while (n) {
#ifdef DELAY_MS_HW
while ( ( TKEY_CTRL & bTKC_IF ) == 0 );
while ( TKEY_CTRL & bTKC_IF );
#else
mDelayuS( 1000 );
mDelayuS(1000);
#endif
-- n;
}
--n;
}
}
#if SDCC < 370
@ -139,7 +137,8 @@ void putchar(char c)
SBUF = c;
}
char getchar() {
char getchar(void)
{
while(!RI); /* assumes UART is initialized */
RI = 0;
return SBUF;
@ -154,7 +153,8 @@ int putchar(int c)
return c;
}
int getchar() {
int getchar(void)
{
while(!RI); /* assumes UART is initialized */
RI = 0;
return SBUF;
@ -162,42 +162,106 @@ int getchar() {
#endif
// Set pin p1.4 and p1.5 to GPIO output mode.
void gpio_init(){
// p1.4
P1_MOD_OC &= ~0x10;
P1_DIR_PU |= 0x10;
// p1.5
P1_MOD_OC &= ~0x20;
P1_DIR_PU |= 0x20;
void gpio_init()
{
// p1.4
P1_MOD_OC &= ~0x10;
P1_DIR_PU |= 0x10;
// p1.5
P1_MOD_OC &= ~0x20;
P1_DIR_PU |= 0x20;
}
void gpio_set(uint8_t pin) {
switch (pin)
{
case 0x10: // p1.4
P1 |= 0x10;
break;
case 0x20: // p1.5
P1 |= 0x20;
break;
default: // do nothing, unsupported pin.
break;
}
void gpio_set(uint8_t pin)
{
switch (pin) {
case 0x10: // p1.4
P1 |= 0x10;
break;
case 0x20: // p1.5
P1 |= 0x20;
break;
default: // do nothing, unsupported pin.
break;
}
}
void gpio_unset(uint8_t pin) {
switch (pin)
{
case 0x10:
P1 &= ~0x10;
break;
case 0x20:
P1 &= ~0x20;
break;
default: // do nothing, unsupported pin.
break;
}
void gpio_unset(uint8_t pin)
{
switch (pin) {
case 0x10:
P1 &= ~0x10;
break;
case 0x20:
P1 &= ~0x20;
break;
default: // do nothing, unsupported pin.
break;
}
}
uint8_t gpio_get(uint8_t pin)
{
uint8_t ret = 0;
switch (pin) {
case 0x10: // p1.4
ret = P1 & 0x10;
break;
case 0x20: // p1.5
ret = P1 & 0x20;
break;
default: // do nothing, unsupported pin.
ret = 0xff;
break;
}
return ret;
}
// Set pin p1.4 to GPIO input mode. (FPGA_CTS)
void gpio_init_p1_4_in()
{
// p1.4
P1_MOD_OC &= ~0x10; // Output Mode: 0 = Push-pull output, 1 = Open-drain output
P1_DIR_PU &= ~0x10; // Port Direction Control and Pull-up Enable Register:
// Push-pull output mode:
// 0 = Input.
// 1 = Output
// Open-drain output mode:
// 0 = Pull-up resistor disabled
// 1 = Pull-up resistor enabled
}
// Read status of pin 1.4
uint8_t gpio_p1_4_get(void)
{
return (P1 & 0x10); // p1.4
}
// Set pin p1.5 to GPIO output mode. (CH552_CTS)
void gpio_init_p1_5_out()
{
// p1.5
P1_MOD_OC &= ~0x20; // Output Mode: 0 = Push-pull output, 1 = Open-drain output
P1_DIR_PU |= 0x20; // Port Direction Control and Pull-up Enable Register:
// Push-pull output mode:
// 0 = Input.
// 1 = Output
// Open-drain output mode:
// 0 = Pull-up resistor disabled
// 1 = Pull-up resistor enabled
}
// Set p1.5 high
void gpio_p1_5_set(void)
{
P1 |= 0x20; // p1.4
}
// Set p1.5 low
void gpio_p1_5_unset(void)
{
P1 &= ~0x20;
}

View File

@ -1,138 +1,221 @@

#ifndef __DEBUG_H__
#define __DEBUG_H__
/* Debug */
/* Provide printf subroutine and delay function */
#pragma once
#include <stdint.h>
#ifndef UART0_BAUD
#define UART0_BAUD 9600
#include "ch554.h"
// UART1 baud rates
// Setting Actual % error
//Std 9600 9615.38 0.16%
// 14400 14492.75 0.64%
//Std 19200 19230.77 0.16%
//Std 38400 38461.54 0.16%
//Std 57600 58823.53 2.12%
// 100000 100000 0.00%
//Std 115200 111111.1 -3.55%
// 128000 142857.14 11.61%
//Std 230400 250000 8.51%
// 250000 250000 0%
// 256000 333333.33 30.21%
//Std 460800 500000 8.51%
//Std 500000 500000 0%
//Std 576000
//Std 921600
//Std 1000000 1000000 0.00%
#ifndef UART0_BAUD
//#define UART0_BAUD 115200
#define UART0_BAUD 1000000
#endif
#ifndef UART1_BAUD
#define UART1_BAUD 9600
#define UART1_BAUD 500000
//#define UART1_BAUD 1000000
#endif
void CfgFsys( ); // CH554 clock selection and configuration
void CfgFsys(void); // CH554 clock selection and configuration
void mDelayuS(uint16_t n); // Delay in units of uS
void mDelaymS(uint16_t n); // Delay in mS
void mDelayuS (uint16_t n); // Delay in units of uS
void mDelaymS (uint16_t n); // Delay in mS
// Set pin p1.4 and p1.5 to GPIO output mode.
void gpio_init(void);
void gpio_set(uint8_t pin);
void gpio_unset(uint8_t pin);
uint8_t gpio_get(uint8_t pin);
void gpio_init_p1_4_in(void);
void gpio_init_p1_5_out(void);
uint8_t gpio_p1_4_get(void);
void gpio_p1_5_set(void);
void gpio_p1_5_unset(void);
/*******************************************************************************
* Function Name : CH554UART0Alter()
* Description : CH554 serial port 0 pin mapping, serial port mapping to P0.2 and P0.3
*******************************************************************************/
* Function Name : CH554UART0Alter()
* Description : Set the alternate pin mappings for UART0 (RX on P1.2, TX on P1.3)
*******************************************************************************/
inline void CH554UART0Alter()
{
PIN_FUNC |= bUART0_PIN_X; //串口映射到P1.2和P1.3
PIN_FUNC |= bUART0_PIN_X; // RX on P1.2, TX on P1.3
}
/*******************************************************************************
* Function Name : mInitSTDIO()
* Description : CH554 serial port 0 is initialized, T1 is used as the baud rate generator of UART0 by default, T2 can also be used
                   As a baud rate generator
*******************************************************************************/
inline void mInitSTDIO( )
* Function Name : mInitSTDIO()
* Description : CH554 UART0 is initialized
* T1 is used as the baud rate generator of UART0 by default
* T2 can also be used as baud rate generator
* RX on P3.0, TX on P3.1
*******************************************************************************/
inline void mInitSTDIO( )
{
uint32_t x;
uint8_t x2;
SM0 = 0;
SM1 = 1;
SM2 = 0; //Serial port 0 usage mode 1
//Use Timer1 as a baud rate generator
RCLK = 0; //UART0 receive clock
TCLK = 0; //UART0 transmit clock
PCON |= SMOD;
x = 10 * FREQ_SYS / UART0_BAUD / 16; //If you change the main frequency, be careful not to overflow the value of x
SM0 = 0; // 8-bit data asynchronous communication
SM1 = 1; // Variable baud rate, which is generated by timer T1 or T2
// With SM0=0 and SM1=1 we are now in UART0 Mode 1
SM2 = 0; // In Mode 1, SM2=0 gives that the Receive interrupt flag bit is set when receiving data and the reception is valid
// Use Timer1 as a baud rate generator
RCLK = 0; // UART0 receive clock
TCLK = 0; // UART0 transmit clock
PCON |= SMOD; // Set Fast mode for UART0 baud rate communication
x = 10 * FREQ_SYS / UART0_BAUD / 16; // If you change the main frequency, be careful not to overflow the value of x
x2 = x % 10;
x /= 10;
if ( x2 >= 5 ) x ++; //rounding
TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; //0X20, Timer1 as 8-bit auto-reload timer
T2MOD = T2MOD | bTMR_CLK | bT1_CLK; //Timer1 clock selection
TH1 = 0-x; //12MHz crystal oscillator, buad / 12 is the actual need to set the baud rate
TR1 = 1; //Start timer 1
TI = 1;
REN = 1; //Serial 0 receive enable
if (x2 >= 5) {
x++; // Rounding
}
TMOD = (TMOD & ~bT1_GATE & ~bT1_CT & ~MASK_T1_MOD) | bT1_M1; // Timer1 as 8-bit auto-reload timer
T2MOD = T2MOD | bTMR_CLK | bT1_CLK; // Timer1 clock selection
TH1 = 0-x; // 12MHz crystal oscillator, baud / 12 is the actual need to set the baud rate
TR1 = 1; // Start timer 1
TI = 1; // Enable transmit interrupt
REN = 1; // UART0 receive enable
ES = 1; // UART0 interrupt enable
}
/*******************************************************************************
* Function Name : CH554UART0RcvByte()
* Description : CH554UART0 receives a byte
* Return : SBUF
*******************************************************************************/
inline uint8_t CH554UART0RcvByte( )
* Function Name : CH554UART0RcvByte()
* Description : CH554UART0 receives a byte
* Return : SBUF
*******************************************************************************/
inline uint8_t CH554UART0RcvByte()
{
while(RI == 0); // wait for uart rx interrupt flag
while (RI == 0)
; // Wait for uart rx interrupt flag
RI = 0;
return SBUF;
}
/*******************************************************************************
* Function Name : CH554UART0SendByte(uint8_t SendDat)
* Description : CH554UART0 sends a byte
* Input : uint8_t SendDat; the data to be sent
*******************************************************************************/
* Function Name : CH554UART0SendByte(uint8_t SendDat)
* Description : CH554UART0 sends a byte
* Input : uint8_t SendDat; the data to be sent
*******************************************************************************/
inline void CH554UART0SendByte(uint8_t SendDat)
{
SBUF = SendDat;
while(TI ==0); // wait for transmit to finish (TI == 1)
TI = 0;
SBUF = SendDat;
while (TI == 0)
; // Wait for transmit to finish (TI == 1)
TI = 0;
}
/*******************************************************************************
* Function Name : CH554UART1Alter()
* Description : Set the alternate pin mappings for UART1 (TX on P3.2, RX on P3.4)
*******************************************************************************/
* Function Name : CH554UART1Alter()
* Description : Set the alternate pin mappings for UART1 (RX on P3.4, TX on P3.2)
*******************************************************************************/
inline void CH554UART1Alter()
{
PIN_FUNC |= bUART1_PIN_X;
PIN_FUNC |= bUART1_PIN_X; // RX on P3.4, TX on P3.2
}
/*******************************************************************************
* Function Name : UART1Setup()
* Description : CH554串口1初始化
*******************************************************************************/
inline void UART1Setup()
* Function Name : UART1Setup()
* Description : CH554 serial port 1 initialization
* RX on P1.6, TX on P1.7
*
*******************************************************************************/
inline void UART1Setup()
{
U1SM0 = 0; //UART1选择8位数据位
U1SMOD = 1; //快速模式
U1REN = 1; //使能接收
// should correct for rounding in SBAUD1 calculation
SBAUD1 = 256 - FREQ_SYS/16/UART1_BAUD;
U1SM0 = 0; // UART1 selects 8-bit data bit
U1SMOD = 1; // Fast mode
U1REN = 1; // Enable receiving
// Should correct for rounding in SBAUD1 calculation
SBAUD1 = 256 - FREQ_SYS/16/UART1_BAUD; // Calculation for Fast mode
IE_UART1 = 1; // Enable UART1 interrupt
IP_EX = bIP_UART1; // Serial port IRQ has high priority
}
/*******************************************************************************
* Function Name : CH554UART1RcvByte()
* Description : CH554UART1接收一个字节
* Return : SBUF
*******************************************************************************/
* Function Name : UART1Clean()
* Description : Read out spurious data
*******************************************************************************/
inline void UART1Clean()
{
uint8_t tmp;
while (U1RI) {
tmp = SBUF1;
U1RI = 0;
}
}
/*******************************************************************************
* Function Name : CH554UART1RcvByte()
* Description : CH554UART1 receives a byte
* Return : SBUF
*******************************************************************************/
inline uint8_t CH554UART1RcvByte( )
{
while(U1RI == 0); //查询接收,中断方式可不用
while (U1RI == 0) // Query reception, interrupt mode is not required
;
U1RI = 0;
return SBUF1;
}
/*******************************************************************************
* Function Name : CH554UART1SendByte(uint8_t SendDat)
* Description : CH554UART1发送一个字节
* Input : uint8_t SendDat
*******************************************************************************/
* Function Name : CH554UART1SendByte(uint8_t SendDat)
* Description : CH554UART1 sends a byte
* Input : uint8_t SendDat; data to be sent
*******************************************************************************/
inline void CH554UART1SendByte(uint8_t SendDat)
{
SBUF1 = SendDat; //查询发送中断方式可不用下面2条语句,但发送前需TI=0
while(U1TI ==0);
U1TI = 0;
SBUF1 = SendDat; // Query sending, the interrupt mode does not need the following two statements, but TI=0 is required before sending
while (U1TI == 0)
;
U1TI = 0;
}
/*******************************************************************************
* Function Name : CH554UART1SendBuffer(uint8_t SendDat)
* Description : CH554UART1 sends a complete buffer
* Input : uint8_t *Buf; Data to be sent
* Input : uint32_t Len; Length of data
*******************************************************************************/
inline void CH554UART1SendBuffer(uint8_t *Buf, uint32_t Len)
{
uint32_t Count = 0;
while (Count < Len) {
if (gpio_p1_4_get()) {
SBUF1 = Buf[Count++];
while (U1TI == 0)
;
U1TI = 0;
}
}
}
#if SDCC < 370
void putchar(char c);
char getchar();
char getchar(void);
#else
int putchar(int c);
int getchar(void);
@ -149,16 +232,15 @@ int getchar(void);
*******************************************************************************/
inline void CH554WDTModeSelect(uint8_t mode)
{
SAFE_MOD = 0x55;
SAFE_MOD = 0xaa; //Enter Safe Mode
if(mode){
GLOBAL_CFG |= bWDOG_EN; //Start watchdog reset
}
else GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer
SAFE_MOD = 0x00; //exit safe Mode
WDOG_COUNT = 0; //Watchdog assignment initial value
SAFE_MOD = 0x55;
SAFE_MOD = 0xaa; // Enter Safe Mode
if (mode) {
GLOBAL_CFG |= bWDOG_EN; // Start watchdog reset
} else {
GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer
}
SAFE_MOD = 0x00; // Exit safe Mode
WDOG_COUNT = 0; // Watchdog assignment initial value
}
/*******************************************************************************
@ -173,12 +255,7 @@ inline void CH554WDTModeSelect(uint8_t mode)
*******************************************************************************/
inline void CH554WDTFeed(uint8_t tim)
{
WDOG_COUNT = tim; // Watchdog counter assignment
WDOG_COUNT = tim; // Watchdog counter assignment
}
// Set pin p1.4 and p1.5 to GPIO output mode.
void gpio_init();
void gpio_set(uint8_t pin);
void gpio_unset(uint8_t pin);
#endif

View File

@ -0,0 +1,40 @@
#ifndef __MEM_PART_H__
#define __MEM_PART_H__
// https://github.com/contiki-os/contiki/wiki/8051-Memory-Spaces
#ifdef BUILD_CODE
#define IDATA __idata
#define XDATA __xdata
#define AT0000 __at(0x0000) // 0x000 0
#define AT0008 __at(0x0008) // 0x008, 8
#define AT0010 __at(0x0010) // 0x010, 16
#define AT0040 __at(0x0040) // 0x040, 64
#define AT0050 __at(0x0050) // 0x050, 80
#define AT0080 __at(0x0080) // 0x080, 128
#define AT0090 __at(0x0090) // 0x090, 144
#define AT00C0 __at(0x00C0) // 0x0C0, 192
#define AT00C8 __at(0x00C8) // 0x0C8, 200
#define AT0110 __at(0x0110) // 0x110, 272
#define AT0148 __at(0x0148) // 0x148, 328
#define AT01C8 __at(0x01C8) // 0x1C8, 456
#define FLASH __code
#else
#define IDATA
#define XDATA
#define AT0000
#define AT0008
#define AT0010
#define AT0040
#define AT0050
#define AT0080
#define AT0090
#define AT00C0
#define AT00C8
#define AT0110
#define AT0148
#define AT01C8
#define FLASH
#endif
#endif

View File

@ -0,0 +1,188 @@
#include <stdint.h>
#include "debug.h"
#include "print.h"
void printStr(uint8_t *str)
{
#ifdef DEBUG_PRINT
while (*str != 0) {
CH554UART0SendByte(*str);
++str;
}
#else
(void)str;
#endif
}
void printChar(uint8_t c)
{
#ifdef DEBUG_PRINT
CH554UART0SendByte(c);
#else
(void)c;
#endif
}
#ifdef USE_NUM_U8
int8_t uint8_to_str(uint8_t *buf, uint8_t bufsize, uint8_t n)
{
uint8_t *start;
#ifdef USE_NEGATIVE_NUMS
if (n < 0) { // Handle negative numbers.
if (!bufsize) {
return -1;
}
*buf++ = '-';
bufsize--;
}
#endif
start = buf; // Remember the start of the string. This will come into play at the end.
do {
// Handle the current digit.
uint8_t digit;
if (!bufsize) {
return -1;
}
digit = n % 10;
#ifdef USE_NEGATIVE_NUMS
if (digit < 0) {
digit *= -1;
}
#endif
*buf++ = digit + '0';
bufsize--;
n /= 10;
} while (n);
// Terminate the string.
if (!bufsize) {
return -1;
}
*buf = 0;
// We wrote the string backwards, i.e. with least significant digits first. Now reverse the string.
--buf;
while (start < buf) {
uint8_t a = *start;
*start = *buf;
*buf = a;
++start;
--buf;
}
return 0;
}
#endif
#ifdef USE_NUM_U32
int8_t uint32_to_str(uint8_t *buf, uint8_t bufsize, uint32_t n)
{
uint8_t *start;
#ifdef USE_NEGATIVE_NUMS
if (n < 0) { // Handle negative numbers.
if (!bufsize) {
return -1;
}
*buf++ = '-';
bufsize--;
}
#endif
start = buf; // Remember the start of the string. This will come into play at the end.
do {
// Handle the current digit.
uint8_t digit;
if (!bufsize) {
return -1;
}
digit = n % 10;
#ifdef USE_NEGATIVE_NUMS
if (digit < 0) {
digit *= -1;
}
#endif
*buf++ = digit + '0';
bufsize--;
n /= 10;
} while (n);
// Terminate the string.
if (!bufsize) {
return -1;
}
*buf = 0;
// We wrote the string backwards, i.e. with least significant digits first. Now reverse the string.
--buf;
while (start < buf) {
uint8_t a = *start;
*start = *buf;
*buf = a;
++start;
--buf;
}
return 0;
}
#endif
#ifdef USE_NUM_U8
void printNumU8(uint8_t num)
{
#ifdef DEBUG_PRINT
uint8_t num_str[4] = { 0 };
int8_t ret;
ret = uint8_to_str(num_str, 4, num);
if (!ret) {
printStr(num_str);
}
#endif
}
#endif
#ifdef USE_NUM_U32
void printNumU32(uint32_t num)
{
#ifdef DEBUG_PRINT
uint8_t num_str[11] = { 0 };
int8_t ret;
ret = uint32_to_str(num_str, 10, num);
if (!ret) {
printStr(num_str);
}
#else
(void)num;
#endif
}
#endif
void printNumHex(uint8_t num)
{
#ifdef DEBUG_PRINT
// High nibble
uint8_t val = num >> 4;
if (val <= 9) {
val = val + '0';
} else {
val = (val-10) + 'A';
}
printChar(val);
// Low nibble
val = num & 0x0F;
if (val <= 9) {
val = val + '0';
} else {
val = (val-10) + 'A';
}
printChar(val);
#else
(void)num;
#endif
}

View File

@ -0,0 +1,42 @@
#ifndef __PRINT_H__
#define __PRINT_H__
#include <stdint.h>
//#define DEBUG_PRINT
//#define DEBUG_SETUP
//#define UART_OUT_DEBUG
//#define USE_NUM_U8
#define USE_NUM_U32
//#define USE_NEGATIVE_NUMS
void printStr(uint8_t *str);
void printChar(uint8_t c);
#ifdef DEBUG_SETUP
#define printStrSetup(x) printStr(x)
#define printNumHexSetup(x) printNumHex(x)
#else
#define printStrSetup(x)
#define printNumHexSetup(x)
#endif
#ifdef USE_NUM_U8
int8_t uint8_to_str(uint8_t *buf, uint8_t bufsize, uint8_t n);
#endif
#ifdef USE_NUM_U32
int8_t uint32_to_str(uint8_t *buf, uint8_t bufsize, uint32_t n);
#endif
#ifdef USE_NUM_U8
void printNumU8(uint8_t num);
#endif
#ifdef USE_NUM_U32
void printNumU32(uint32_t num);
#endif
void printNumHex(uint8_t num);
#endif

View File

@ -0,0 +1,64 @@
#ifndef __USB_STRINGS_H__
#define __USB_STRINGS_H__
#include "mem.h"
unsigned char FLASH ProdDesc[]={ // "MTA1-USB-V1"
24, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'M', 0, 'T', 0, 'A', 0, '1', 0,
'-', 0, 'U', 0, 'S', 0, 'B', 0,
'-', 0, 'V', 0, '1', 0
};
unsigned char FLASH ManufDesc[]={ // "Tillitis"
18, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'T', 0, 'i', 0, 'l', 0, 'l', 0,
'i', 0, 't', 0, 'i', 0, 's', 0
};
unsigned char FLASH SerialDesc[]={ // "68de5d27-e223-4874-bc76-a54d6e84068f"
74, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'6', 0, '8', 0, 'd', 0, 'e', 0,
'5', 0, 'd', 0, '2', 0, '7', 0,
'-', 0, 'e', 0, '2', 0, '2', 0,
'3', 0, '-', 0, '4', 0, '8', 0,
'7', 0, '4', 0, '-', 0, 'b', 0,
'c', 0, '7', 0, '6', 0, '-', 0,
'a', 0, '5', 0, '4', 0, 'd', 0,
'6', 0, 'e', 0, '8', 0, '4', 0,
'0', 0, '6', 0, '8', 0, 'f', 0,
};
unsigned char FLASH CdcCtrlInterfaceDesc[] = {
18, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'C', 0, 'D', 0, 'C', 0, '-', 0,
'C', 0, 't', 0, 'r', 0, 'l', 0,
};
unsigned char FLASH CdcDataInterfaceDesc[] = {
18, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'C', 0, 'D', 0, 'C', 0, '-', 0,
'D', 0, 'a', 0, 't', 0, 'a', 0,
};
unsigned char FLASH FidoHidInterfaceDesc[] = {
18, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'F', 0, 'I', 0, 'D', 0, 'O', 0,
'-', 0, 'H', 0, 'I', 0, 'D', 0,
};
unsigned char FLASH TkeyCtrlInterfaceDesc[] = {
20, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
'T', 0, 'K', 0, 'E', 0, 'Y', 0,
'-', 0, 'C', 0, 't', 0, 'r', 0,
'l', 0,
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
#ifndef USB_STRINGS
#define USB_STRINGS
unsigned char __code Prod_Des[]={ // "MTA1-USB-V1"
0x18, 0x03, 0x4d, 0x00, 0x54, 0x00, 0x41, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x31, 0x00
};
unsigned char __code Manuf_Des[]={ // "Tillitis"
0x12, 0x03, 0x54, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x73, 0x00
};
unsigned char __code SerDes[]={ // "68de5d27-e223-4874-bc76-a54d6e84068f"
0x4a, 0x03, 0x36, 0x00, 0x38, 0x00, 0x64, 0x00, 0x65, 0x00, 0x35, 0x00, 0x64, 0x00, 0x32, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x32, 0x00, 0x32, 0x00, 0x33, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x38, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x63, 0x00, 0x37, 0x00, 0x36, 0x00, 0x2d, 0x00, 0x61, 0x00, 0x35, 0x00, 0x34, 0x00, 0x64, 0x00, 0x36, 0x00, 0x65, 0x00, 0x38, 0x00, 0x34, 0x00, 0x30, 0x00, 0x36, 0x00, 0x38, 0x00, 0x66, 0x00
};
#endif