mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-03-12 10:06:47 -04:00
Compare commits
61 Commits
54889f8dce
...
3cd2f6c2b5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3cd2f6c2b5 | ||
![]() |
b02c2d67d6 | ||
![]() |
1968b3614c | ||
![]() |
0cc991fea2 | ||
![]() |
d65e1eec4e | ||
![]() |
a68b646edf | ||
![]() |
e4df068bb4 | ||
![]() |
e5e2ab2787 | ||
![]() |
cbc7adf706 | ||
![]() |
12c23cc149 | ||
![]() |
b45489730a | ||
![]() |
6c439b3a4f | ||
![]() |
f686c59e03 | ||
![]() |
1e959bebb6 | ||
![]() |
4a27940bf1 | ||
![]() |
d07abc7ad2 | ||
![]() |
fe16cc9f72 | ||
![]() |
e9f72a8530 | ||
![]() |
ed10222999 | ||
![]() |
1179324f10 | ||
![]() |
43239759e6 | ||
![]() |
4532bec84d | ||
![]() |
a9484d9cf4 | ||
![]() |
91625c05bb | ||
![]() |
38b029f1c4 | ||
![]() |
7f718b298b | ||
![]() |
833bf63bc8 | ||
![]() |
eacfd6eddc | ||
![]() |
beb325b683 | ||
![]() |
2e1925555d | ||
![]() |
e1d7608897 | ||
![]() |
0183f25170 | ||
![]() |
89c77ca4de | ||
![]() |
cd959e9966 | ||
![]() |
e18eb03c4f | ||
![]() |
5dfe549969 | ||
![]() |
5e15b40a86 | ||
![]() |
d2c7fb0ba9 | ||
![]() |
179c13e9bf | ||
![]() |
050e0f2673 | ||
![]() |
aedd6102ea | ||
![]() |
f68414c4aa | ||
![]() |
75ad033e03 | ||
![]() |
05bb999759 | ||
![]() |
81ac7bffa0 | ||
![]() |
bb18d5b9e9 | ||
![]() |
8ed16fff6a | ||
![]() |
c292595ee3 | ||
![]() |
361890042a | ||
![]() |
5029eb1d39 | ||
![]() |
04ec938200 | ||
![]() |
bfc43093ec | ||
![]() |
07dc20e4e1 | ||
![]() |
0a634c76da | ||
![]() |
ab4ef5fdf9 | ||
![]() |
f3706dcfcc | ||
![]() |
a0c031eb25 | ||
![]() |
1b9bbc4eba | ||
![]() |
b443359e9c | ||
![]() |
90fca5d3dd | ||
![]() |
0af82ee566 |
33
.github/workflows/ci.yaml
vendored
33
.github/workflows/ci.yaml
vendored
@ -10,10 +10,10 @@ on:
|
|||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-firmware:
|
check-formatting:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/tillitis/tkey-builder:4
|
image: ghcr.io/tillitis/tkey-builder:5rc1
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -26,11 +26,26 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
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
|
working-directory: hw/application_fpga
|
||||||
run: |
|
run: |
|
||||||
make -C fw/tk1 checkfmt
|
make checkfmt
|
||||||
make -C fw/testfw 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
|
- name: run static analysis on firmware C code
|
||||||
working-directory: hw/application_fpga
|
working-directory: hw/application_fpga
|
||||||
@ -44,7 +59,7 @@ jobs:
|
|||||||
check-verilog:
|
check-verilog:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/tillitis/tkey-builder:4
|
image: ghcr.io/tillitis/tkey-builder:5rc1
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -64,7 +79,7 @@ jobs:
|
|||||||
build-usb-firmware:
|
build-usb-firmware:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/tillitis/tkey-builder:4
|
image: ghcr.io/tillitis/tkey-builder:5rc1
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -86,7 +101,7 @@ jobs:
|
|||||||
commit_sha: ${{ github.sha }}
|
commit_sha: ${{ github.sha }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/tillitis/tkey-builder:4
|
image: ghcr.io/tillitis/tkey-builder:5rc1
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -115,7 +130,7 @@ jobs:
|
|||||||
needs: build-bitstream
|
needs: build-bitstream
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/tillitis/tkey-builder:4
|
image: ghcr.io/tillitis/tkey-builder:5rc1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
@ -12,6 +12,7 @@ RUN apt-get -qq update -y \
|
|||||||
clang-format \
|
clang-format \
|
||||||
clang-tidy \
|
clang-tidy \
|
||||||
cmake \
|
cmake \
|
||||||
|
curl \
|
||||||
flex \
|
flex \
|
||||||
g++ \
|
g++ \
|
||||||
gawk \
|
gawk \
|
||||||
@ -57,109 +58,12 @@ RUN apt-get -qq update -y \
|
|||||||
zlib1g-dev \
|
zlib1g-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& 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
|
FROM base as toolsbuilder
|
||||||
|
|
||||||
RUN git clone --depth=1 https://github.com/YosysHQ/icestorm /src
|
COPY buildtools.sh /buildtools.sh
|
||||||
WORKDIR /src
|
COPY verible.sha512 /verible.sha512
|
||||||
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
|
|
||||||
|
|
||||||
# Custom iceprog for the RPi 2040-based programmer (will be upstreamed).
|
RUN /buildtools.sh
|
||||||
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
|
|
||||||
|
|
||||||
FROM base
|
FROM base
|
||||||
LABEL org.opencontainers.image.description="Toolchain for building TKey FPGA bitstream"
|
LABEL org.opencontainers.image.description="Toolchain for building TKey FPGA bitstream"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
BUILDIMAGE=tkey-builder-local
|
BUILDIMAGE=tkey-builder-local
|
||||||
|
|
||||||
# default image used when running a container
|
# default image used when running a container
|
||||||
IMAGE=ghcr.io/tillitis/tkey-builder:4
|
IMAGE=ghcr.io/tillitis/tkey-builder:5rc1
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@echo "Targets:"
|
@echo "Targets:"
|
||||||
@ -23,11 +23,11 @@ all:
|
|||||||
|
|
||||||
run:
|
run:
|
||||||
podman run --rm --mount type=bind,source="`pwd`/../",target=/build -w /build -it \
|
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:
|
||||||
docker run --rm --mount type=bind,source="`pwd`/../",target=/build -w /build -it \
|
docker run --rm --mount type=bind,source="`pwd`/../",target=/build -w /build -it \
|
||||||
$(IMAGE) /usr/bin/bash
|
$(IMAGE) /usr/bin/bash -l
|
||||||
|
|
||||||
run-make:
|
run-make:
|
||||||
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
|
podman run --rm --mount type=bind,source="`pwd`/../hw/application_fpga",target=/build -w /build -it \
|
||||||
|
134
contrib/buildtools.sh
Executable file
134
contrib/buildtools.sh
Executable 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
1
contrib/verible.sha512
Normal file
@ -0,0 +1 @@
|
|||||||
|
3e997b8cd494556fa107b96a6daa4e51133208a85b3c0250c0223d7194aedbc98b3f5213fedaee083edd96c317e50057aa9cdc0517197f4638be3834133e2c9f /src/verible.tar.gz
|
@ -2,6 +2,104 @@
|
|||||||
|
|
||||||
Descriptions of the tagged TKey releases.
|
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
|
## TK1-24.03
|
||||||
|
|
||||||
|
@ -127,7 +127,10 @@ FIRMWARE_OBJS = \
|
|||||||
$(P)/fw/tk1/lib.o \
|
$(P)/fw/tk1/lib.o \
|
||||||
$(P)/fw/tk1/assert.o \
|
$(P)/fw/tk1/assert.o \
|
||||||
$(P)/fw/tk1/led.o \
|
$(P)/fw/tk1/led.o \
|
||||||
$(P)/fw/tk1/blake2s/blake2s.o
|
$(P)/fw/tk1/blake2s/blake2s.o \
|
||||||
|
$(P)/fw/tk1/syscall.o \
|
||||||
|
$(P)/fw/tk1/spi.o \
|
||||||
|
$(P)/fw/tk1/flash.o
|
||||||
|
|
||||||
FIRMWARE_SOURCES = \
|
FIRMWARE_SOURCES = \
|
||||||
$(P)/fw/tk1/main.c \
|
$(P)/fw/tk1/main.c \
|
||||||
@ -135,14 +138,37 @@ FIRMWARE_SOURCES = \
|
|||||||
$(P)/fw/tk1/lib.c \
|
$(P)/fw/tk1/lib.c \
|
||||||
$(P)/fw/tk1/assert.c \
|
$(P)/fw/tk1/assert.c \
|
||||||
$(P)/fw/tk1/led.c \
|
$(P)/fw/tk1/led.c \
|
||||||
$(P)/fw/tk1/blake2s/blake2s.c
|
$(P)/fw/tk1/blake2s/blake2s.c \
|
||||||
|
$(P)/fw/tk1/syscall.c \
|
||||||
|
$(P)/fw/tk1/spi.c \
|
||||||
|
$(P)/fw/tk1/flash.c
|
||||||
|
|
||||||
TESTFW_OBJS = \
|
TESTFW_OBJS = \
|
||||||
$(P)/fw/testfw/main.o \
|
$(P)/fw/testfw/main.o \
|
||||||
$(P)/fw/testfw/start.o \
|
$(P)/fw/testfw/start.o \
|
||||||
$(P)/fw/tk1/proto.o \
|
$(P)/fw/tk1/proto.o \
|
||||||
|
$(P)/fw/tk1/assert.o \
|
||||||
$(P)/fw/tk1/lib.o \
|
$(P)/fw/tk1/lib.o \
|
||||||
$(P)/fw/tk1/blake2s/blake2s.o
|
$(P)/fw/tk1/spi.o \
|
||||||
|
$(P)/fw/tk1/flash.o
|
||||||
|
|
||||||
|
IRQPOC_OBJS = \
|
||||||
|
$(P)/fw/irqpoc/main.o \
|
||||||
|
$(P)/fw/irqpoc/start.o
|
||||||
|
|
||||||
|
IRQPOC_LED_TOGGLE_OBJS = \
|
||||||
|
$(P)/fw/irqpoc_led_toggle/main.o \
|
||||||
|
$(P)/fw/irqpoc_led_toggle/start.o
|
||||||
|
|
||||||
|
IRQPOC_WITH_APP_OBJS = \
|
||||||
|
$(P)/fw/irqpoc_with_app/main.o \
|
||||||
|
$(P)/fw/irqpoc_with_app/start.o
|
||||||
|
|
||||||
|
IRQPOC_C_EXAMPLE_OBJS = \
|
||||||
|
$(P)/fw/irqpoc_c_example/main.o \
|
||||||
|
$(P)/fw/irqpoc_c_example/start.o \
|
||||||
|
$(P)/fw/tk1/led.o \
|
||||||
|
$(P)/fw/tk1/assert.o
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
# All: Complete build of HW and FW.
|
# All: Complete build of HW and FW.
|
||||||
@ -180,6 +206,10 @@ LDFLAGS = -T $(P)/fw/tk1/firmware.lds
|
|||||||
|
|
||||||
$(FIRMWARE_OBJS): $(FIRMWARE_DEPS)
|
$(FIRMWARE_OBJS): $(FIRMWARE_DEPS)
|
||||||
$(TESTFW_OBJS): $(FIRMWARE_DEPS)
|
$(TESTFW_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
$(IRQPOC_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
$(IRQPOC_LED_TOGGLE_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
$(IRQPOC_WITH_APP_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
$(IRQPOC_C_EXAMPLE_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
|
||||||
firmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
|
firmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@
|
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@
|
||||||
@ -222,6 +252,18 @@ splint:
|
|||||||
testfw.elf: $(TESTFW_OBJS) $(P)/fw/tk1/firmware.lds
|
testfw.elf: $(TESTFW_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
$(CC) $(CFLAGS) $(TESTFW_OBJS) $(LDFLAGS) -o $@
|
$(CC) $(CFLAGS) $(TESTFW_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
irqpoc.elf: $(IRQPOC_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
|
$(CC) $(CFLAGS) $(IRQPOC_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
irqpoc_led_toggle.elf: $(IRQPOC_LED_TOGGLE_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
|
$(CC) $(CFLAGS) $(IRQPOC_LED_TOGGLE_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
irqpoc_with_app.elf: $(IRQPOC_WITH_APP_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
|
$(CC) $(CFLAGS) $(IRQPOC_WITH_APP_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
irqpoc_c_example.elf: $(IRQPOC_C_EXAMPLE_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
|
$(CC) $(CFLAGS) $(IRQPOC_C_EXAMPLE_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
# Generate a fake BRAM file that will be filled in later after place-n-route
|
# Generate a fake BRAM file that will be filled in later after place-n-route
|
||||||
bram_fw.hex:
|
bram_fw.hex:
|
||||||
$(ICESTORM_PATH)icebram -v -g 32 $(BRAM_FW_SIZE) > $@
|
$(ICESTORM_PATH)icebram -v -g 32 $(BRAM_FW_SIZE) > $@
|
||||||
@ -232,6 +274,13 @@ simfirmware.hex: simfirmware.bin simfirmware_size_mismatch
|
|||||||
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
testfw.hex: testfw.bin testfw_size_mismatch
|
testfw.hex: testfw.bin testfw_size_mismatch
|
||||||
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
|
irqpoc.hex: irqpoc.bin
|
||||||
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
|
irqpoc_with_app.hex: irqpoc_with_app.bin
|
||||||
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
|
irqpoc_c_example.hex: irqpoc_c_example.bin
|
||||||
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
|
|
||||||
|
|
||||||
.PHONY: check-binary-hashes
|
.PHONY: check-binary-hashes
|
||||||
check-binary-hashes:
|
check-binary-hashes:
|
||||||
@ -261,7 +310,8 @@ LINT_FLAGS = \
|
|||||||
-Wno-WIDTHEXPAND \
|
-Wno-WIDTHEXPAND \
|
||||||
-Wno-UNOPTFLAT \
|
-Wno-UNOPTFLAT \
|
||||||
--timescale 1ns/1ns \
|
--timescale 1ns/1ns \
|
||||||
-DNO_ICE40_DEFAULT_ASSIGNMENTS
|
-DNO_ICE40_DEFAULT_ASSIGNMENTS \
|
||||||
|
-Wno-GENUNNAMED
|
||||||
|
|
||||||
lint: $(FPGA_VERILOG_SRCS) \
|
lint: $(FPGA_VERILOG_SRCS) \
|
||||||
$(SIM_VERILOG_SRCS) \
|
$(SIM_VERILOG_SRCS) \
|
||||||
@ -303,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
|
# Temporary fix using grep, since the verible with --verify flag only returns
|
||||||
# error if the last file is malformatted.
|
# error if the last file is malformatted.
|
||||||
checkfmt: $(FPGA_VERILOG_SRCS) $(SIM_VERILOG_SRCS) $(VERILATOR_VERILOG_SRCS) $(VERILOG_SRCS)
|
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 | \
|
$(FORMAT) $(CHECK_FORMAT_FLAGS) $^ 2>&1 | \
|
||||||
grep "Needs formatting" && exit 1 || true
|
grep "Needs formatting" && exit 1 || true
|
||||||
.PHONY: checkfmt
|
.PHONY: checkfmt
|
||||||
@ -367,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)
|
application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE)
|
||||||
$(NEXTPNR_PATH)nextpnr-ice40 \
|
$(NEXTPNR_PATH)nextpnr-ice40 \
|
||||||
-l application_fpga_par.txt \
|
-l application_fpga_par.txt \
|
||||||
|
--seed 4127945014473118301 \
|
||||||
--freq $(TARGET_FREQ) \
|
--freq $(TARGET_FREQ) \
|
||||||
--ignore-loops \
|
--ignore-loops \
|
||||||
--up5k \
|
--up5k \
|
||||||
@ -401,11 +454,13 @@ application_fpga_testfw.bin: application_fpga.asc bram_fw.hex testfw.hex
|
|||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
# Build testbench simulation for the design
|
# Build testbench simulation for the design
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
SIMFIRMWARE = simfirmware.hex
|
||||||
|
|
||||||
tb_application_fpga: $(SIM_VERILOG_SRCS) \
|
tb_application_fpga: $(SIM_VERILOG_SRCS) \
|
||||||
$(VERILOG_SRCS) \
|
$(VERILOG_SRCS) \
|
||||||
$(PICORV32_SRCS) \
|
$(PICORV32_SRCS) \
|
||||||
$(ICE40_SIM_CELLS) \
|
$(ICE40_SIM_CELLS) \
|
||||||
simfirmware.hex
|
$(SIMFIRMWARE)
|
||||||
python3 ./tools/app_bin_to_spram_hex.py \
|
python3 ./tools/app_bin_to_spram_hex.py \
|
||||||
./tb/app.bin \
|
./tb/app.bin \
|
||||||
./tb/output_spram0.hex \
|
./tb/output_spram0.hex \
|
||||||
@ -429,7 +484,7 @@ tb_application_fpga: $(SIM_VERILOG_SRCS) \
|
|||||||
-DNO_ICE40_DEFAULT_ASSIGNMENTS \
|
-DNO_ICE40_DEFAULT_ASSIGNMENTS \
|
||||||
-DAPP_SIZE=$(shell ls -l tb/app.bin| awk '{print $$5}') \
|
-DAPP_SIZE=$(shell ls -l tb/app.bin| awk '{print $$5}') \
|
||||||
-DBRAM_FW_SIZE=$(BRAM_FW_SIZE) \
|
-DBRAM_FW_SIZE=$(BRAM_FW_SIZE) \
|
||||||
-DFIRMWARE_HEX=\"$(P)/simfirmware.hex\" \
|
-DFIRMWARE_HEX=\"$(P)/$(SIMFIRMWARE)\" \
|
||||||
-DUDS_HEX=\"$(P)/data/uds.hex\" \
|
-DUDS_HEX=\"$(P)/data/uds.hex\" \
|
||||||
-DUDI_HEX=\"$(P)/data/udi.hex\" \
|
-DUDI_HEX=\"$(P)/data/udi.hex\" \
|
||||||
$(filter %.v, $^)
|
$(filter %.v, $^)
|
||||||
@ -437,6 +492,23 @@ tb_application_fpga: $(SIM_VERILOG_SRCS) \
|
|||||||
./tb_verilated/Vtb_application_fpga_sim \
|
./tb_verilated/Vtb_application_fpga_sim \
|
||||||
&& { echo -e "\n -- Wave simulation saved to tb_application_fpga_sim.fst\n"; true; }
|
&& { echo -e "\n -- Wave simulation saved to tb_application_fpga_sim.fst\n"; true; }
|
||||||
|
|
||||||
|
.PHONY: emptyapp
|
||||||
|
emptyapp:
|
||||||
|
dd if=/dev/zero of=tb/app.bin bs=1024 count=128
|
||||||
|
|
||||||
|
.PHONY: tb_application_fpga_irqpoc
|
||||||
|
tb_application_fpga_irqpoc: SIMFIRMWARE=irqpoc.hex
|
||||||
|
tb_application_fpga_irqpoc: irqpoc.hex emptyapp tb_application_fpga
|
||||||
|
|
||||||
|
.PHONY: tb_application_fpga_irqpoc_with_app
|
||||||
|
tb_application_fpga_irqpoc_with_app: SIMFIRMWARE=irqpoc_with_app.hex
|
||||||
|
tb_application_fpga_irqpoc_with_app: irqpoc_with_app.hex emptyapp tb_application_fpga
|
||||||
|
|
||||||
|
.PHONY: tb_application_fpga_irqpoc_c_example
|
||||||
|
tb_application_fpga_irqpoc_c_example: SIMFIRMWARE=irqpoc_c_example.hex
|
||||||
|
tb_application_fpga_irqpoc_c_example: irqpoc_c_example.hex emptyapp tb_application_fpga
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
# FPGA device programming.
|
# FPGA device programming.
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
@ -483,6 +555,10 @@ clean_fw:
|
|||||||
rm -f $(FIRMWARE_OBJS)
|
rm -f $(FIRMWARE_OBJS)
|
||||||
rm -f testfw.{elf,elf.map,bin,hex}
|
rm -f testfw.{elf,elf.map,bin,hex}
|
||||||
rm -f $(TESTFW_OBJS)
|
rm -f $(TESTFW_OBJS)
|
||||||
|
rm -f $(IRQPOC_OBJS)
|
||||||
|
rm -f $(IRQPOC_LED_TOGGLE_OBJS)
|
||||||
|
rm -f $(IRQPOC_WITH_APP_OBJS)
|
||||||
|
rm -f $(IRQPOC_C_EXAMPLE_OBJS)
|
||||||
rm -f qemu_firmware.elf
|
rm -f qemu_firmware.elf
|
||||||
.PHONY: clean_fw
|
.PHONY: clean_fw
|
||||||
|
|
||||||
|
@ -11,9 +11,10 @@ The design top level is in `rtl/application_fpga.v`. It contains
|
|||||||
instances of all cores as well as the memory system.
|
instances of all cores as well as the memory system.
|
||||||
|
|
||||||
The memory system allows the CPU to access cores in different ways
|
The memory system allows the CPU to access cores in different ways
|
||||||
given the current execution mode. There are two execution modes -
|
given the current execution mode. There are three execution modes -
|
||||||
firmware and application. Basically, in application mode the access is
|
firmware, application and system call. Each mode give access to a
|
||||||
more restrictive.
|
different set of resources. Where app mode is the most restrictive and
|
||||||
|
firmware mode is the least restrictive.
|
||||||
|
|
||||||
The rest of the components are under `cores`. They typically have
|
The rest of the components are under `cores`. They typically have
|
||||||
their own `README.md` file documenting them and their API in detail.
|
their own `README.md` file documenting them and their API in detail.
|
||||||
@ -24,17 +25,18 @@ and bitmasks, see the file `fw/tk1_mem.h`.
|
|||||||
|
|
||||||
Rough memory map:
|
Rough memory map:
|
||||||
|
|
||||||
| *name* | *prefix* |
|
| *name* | *prefix* |
|
||||||
|---------|----------|
|
|------------|----------|
|
||||||
| ROM | 0x00 |
|
| ROM | 0x00 |
|
||||||
| RAM | 0x40 |
|
| RAM | 0x40 |
|
||||||
| TRNG | 0xc0 |
|
| TRNG | 0xc0 |
|
||||||
| Timer | 0xc1 |
|
| Timer | 0xc1 |
|
||||||
| UDS | 0xc2 |
|
| UDS | 0xc2 |
|
||||||
| UART | 0xc3 |
|
| UART | 0xc3 |
|
||||||
| Touch | 0xc4 |
|
| Touch | 0xc4 |
|
||||||
| FW\_RAM | 0xd0 |
|
| FW\_RAM | 0xd0 |
|
||||||
| TK1 | 0xff |
|
| IRQ31\_SET | 0xe1 |
|
||||||
|
| TK1 | 0xff |
|
||||||
|
|
||||||
## `clk_reset_gen`
|
## `clk_reset_gen`
|
||||||
|
|
||||||
@ -96,6 +98,71 @@ hours, days) there is also a 32 bit prescaler.
|
|||||||
|
|
||||||
The timer is available to use by firmware and applications.
|
The timer is available to use by firmware and applications.
|
||||||
|
|
||||||
|
## `irq31_set`
|
||||||
|
|
||||||
|
Interrupt 31 trigger area. A 32-bit write to the IRQ31\_SET memory
|
||||||
|
area will trigger interrupt 31.
|
||||||
|
|
||||||
|
## Interrupts
|
||||||
|
|
||||||
|
Triggering an interrupt will cause the CPU to execute the interrupt
|
||||||
|
handler att address 0x10.
|
||||||
|
|
||||||
|
The interrupt handler is shared by all PicoRV32 interrupts but only
|
||||||
|
interrupt 31 is enabled on the Tkey. Register `x4` can be inspected to
|
||||||
|
determine the interrupt source. Each interrupt source is assigned one
|
||||||
|
bit in x4. Triggered interrupts have their bit set to `1`.
|
||||||
|
|
||||||
|
| *Interrupt Name* | *Source* | *x4 Bit* |
|
||||||
|
|------------------|------------|----------|
|
||||||
|
| IRQ_SYSCALL | IRQ31\_SET | 31 |
|
||||||
|
|
||||||
|
The return address is located in register `x3`. Calling the PicoRV32
|
||||||
|
specific instruction `retirq` exits the interrupt handler and clears
|
||||||
|
the interrupt source.
|
||||||
|
|
||||||
|
No registers are stored/restored when entering/exiting the interrupt
|
||||||
|
handler. It is up to the software to store/restore as necessary.
|
||||||
|
|
||||||
|
Interrupts can be enabled/disabled using the PicoRV32 specific
|
||||||
|
`maskirq` instruction.
|
||||||
|
|
||||||
|
## Restricted resources
|
||||||
|
|
||||||
|
The following table shows resource availablility for each execution
|
||||||
|
mode:
|
||||||
|
|
||||||
|
| *Execution Mode* | *ROM* | *FW RAM* | *SPI* | *Sensitive assets* |
|
||||||
|
|------------------|--------|----------|-------|--------------------|
|
||||||
|
| Firmware mode | r/x | r/w | r/w | r/w* |
|
||||||
|
| IRQ_SYSCALL | r/x | r/w | r/w | r* |
|
||||||
|
| Application mode | r | i | i | r* |
|
||||||
|
|
||||||
|
Legend:
|
||||||
|
r = readable
|
||||||
|
w = writeable
|
||||||
|
x = executable
|
||||||
|
i = invisible
|
||||||
|
* = read-/writeability varies, see below
|
||||||
|
|
||||||
|
These sensitive assets are only readable and/or writeable in firmware
|
||||||
|
mode:
|
||||||
|
- APP_START
|
||||||
|
- APP_SIZE
|
||||||
|
- CDI_FIRST
|
||||||
|
- CDI_LAST
|
||||||
|
- RAM_ADDR_RAND
|
||||||
|
- RAM_DATA_RAND
|
||||||
|
- UDI_FIRST
|
||||||
|
- UDI_LAST
|
||||||
|
- UDS_FIRST
|
||||||
|
- UDS_LAST
|
||||||
|
|
||||||
|
Note that these assets have different properties, some are read-only
|
||||||
|
and some are write-only. The list above only shows if they are
|
||||||
|
restricted in app mode. See each individual API to find out more about
|
||||||
|
their properties.
|
||||||
|
|
||||||
## `tk1`
|
## `tk1`
|
||||||
|
|
||||||
See [tk1 README](core/tk1/README.md) for details.
|
See [tk1 README](core/tk1/README.md) for details.
|
||||||
@ -107,7 +174,6 @@ Contains:
|
|||||||
- RGB LED control.
|
- RGB LED control.
|
||||||
- General purpose input/output (GPIO) pin control.
|
- General purpose input/output (GPIO) pin control.
|
||||||
- Application introspection: start address and size of binary.
|
- Application introspection: start address and size of binary.
|
||||||
- BLAKE2s function access.
|
|
||||||
- Compound Device Identity (CDI).
|
- Compound Device Identity (CDI).
|
||||||
- Unique Device Identity (UDI).
|
- Unique Device Identity (UDI).
|
||||||
- RAM memory protection.
|
- RAM memory protection.
|
||||||
|
@ -1 +1 @@
|
|||||||
44086edb70377991b57d3f1c231f743fcf0c2c9d2303843ec133f76cc42449a8 application_fpga.bin
|
93e311e4bfa7e2f8c3c89f194b5fbe7b83eff81e6d32fd73c8859d5d76324b48 application_fpga.bin
|
||||||
|
@ -17,8 +17,7 @@ module fw_ram (
|
|||||||
input wire clk,
|
input wire clk,
|
||||||
input wire reset_n,
|
input wire reset_n,
|
||||||
|
|
||||||
input wire system_mode,
|
input wire en,
|
||||||
|
|
||||||
input wire cs,
|
input wire cs,
|
||||||
input wire [ 3 : 0] we,
|
input wire [ 3 : 0] we,
|
||||||
input wire [ 8 : 0] address,
|
input wire [ 8 : 0] address,
|
||||||
@ -31,21 +30,19 @@ module fw_ram (
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Registers and wires.
|
// Registers and wires.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
reg [31 : 0] tmp_read_data;
|
reg [31 : 0] tmp_read_data;
|
||||||
reg [31 : 0] mem_read_data0;
|
reg [31 : 0] mem_read_data0;
|
||||||
reg [31 : 0] mem_read_data1;
|
reg [31 : 0] mem_read_data1;
|
||||||
reg ready_reg;
|
reg ready_reg;
|
||||||
wire system_mode_cs;
|
reg bank0;
|
||||||
reg bank0;
|
reg bank1;
|
||||||
reg bank1;
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Concurrent assignment of ports.
|
// Concurrent assignment of ports.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
assign read_data = tmp_read_data;
|
assign read_data = tmp_read_data;
|
||||||
assign ready = ready_reg;
|
assign ready = ready_reg;
|
||||||
assign system_mode_cs = cs && ~system_mode;
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -56,12 +53,12 @@ module fw_ram (
|
|||||||
.RADDR({3'h0, address[7 : 0]}),
|
.RADDR({3'h0, address[7 : 0]}),
|
||||||
.RCLK(clk),
|
.RCLK(clk),
|
||||||
.RCLKE(1'h1),
|
.RCLKE(1'h1),
|
||||||
.RE(system_mode_cs & bank0),
|
.RE(en & cs & bank0),
|
||||||
.WADDR({3'h0, address[7 : 0]}),
|
.WADDR({3'h0, address[7 : 0]}),
|
||||||
.WCLK(clk),
|
.WCLK(clk),
|
||||||
.WCLKE(1'h1),
|
.WCLKE(1'h1),
|
||||||
.WDATA(write_data[15 : 0]),
|
.WDATA(write_data[15 : 0]),
|
||||||
.WE((|we & system_mode_cs & bank0)),
|
.WE((|we & en & cs & bank0)),
|
||||||
.MASK({{8{~we[1]}}, {8{~we[0]}}})
|
.MASK({{8{~we[1]}}, {8{~we[0]}}})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -70,12 +67,12 @@ module fw_ram (
|
|||||||
.RADDR({3'h0, address[7 : 0]}),
|
.RADDR({3'h0, address[7 : 0]}),
|
||||||
.RCLK(clk),
|
.RCLK(clk),
|
||||||
.RCLKE(1'h1),
|
.RCLKE(1'h1),
|
||||||
.RE(system_mode_cs & bank0),
|
.RE(en & cs & bank0),
|
||||||
.WADDR({3'h0, address[7 : 0]}),
|
.WADDR({3'h0, address[7 : 0]}),
|
||||||
.WCLK(clk),
|
.WCLK(clk),
|
||||||
.WCLKE(1'h1),
|
.WCLKE(1'h1),
|
||||||
.WDATA(write_data[31 : 16]),
|
.WDATA(write_data[31 : 16]),
|
||||||
.WE((|we & system_mode_cs & bank0)),
|
.WE((|we & en & cs & bank0)),
|
||||||
.MASK({{8{~we[3]}}, {8{~we[2]}}})
|
.MASK({{8{~we[3]}}, {8{~we[2]}}})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -85,12 +82,12 @@ module fw_ram (
|
|||||||
.RADDR({3'h0, address[7 : 0]}),
|
.RADDR({3'h0, address[7 : 0]}),
|
||||||
.RCLK(clk),
|
.RCLK(clk),
|
||||||
.RCLKE(1'h1),
|
.RCLKE(1'h1),
|
||||||
.RE(system_mode_cs & bank1),
|
.RE(en & cs & bank1),
|
||||||
.WADDR({3'h0, address[7 : 0]}),
|
.WADDR({3'h0, address[7 : 0]}),
|
||||||
.WCLK(clk),
|
.WCLK(clk),
|
||||||
.WCLKE(1'h1),
|
.WCLKE(1'h1),
|
||||||
.WDATA(write_data[15 : 0]),
|
.WDATA(write_data[15 : 0]),
|
||||||
.WE((|we & system_mode_cs & bank1)),
|
.WE((|we & en & cs & bank1)),
|
||||||
.MASK({{8{~we[1]}}, {8{~we[0]}}})
|
.MASK({{8{~we[1]}}, {8{~we[0]}}})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -99,12 +96,12 @@ module fw_ram (
|
|||||||
.RADDR({3'h0, address[7 : 0]}),
|
.RADDR({3'h0, address[7 : 0]}),
|
||||||
.RCLK(clk),
|
.RCLK(clk),
|
||||||
.RCLKE(1'h1),
|
.RCLKE(1'h1),
|
||||||
.RE(system_mode_cs & bank1),
|
.RE(en & cs & bank1),
|
||||||
.WADDR({3'h0, address[7 : 0]}),
|
.WADDR({3'h0, address[7 : 0]}),
|
||||||
.WCLK(clk),
|
.WCLK(clk),
|
||||||
.WCLKE(1'h1),
|
.WCLKE(1'h1),
|
||||||
.WDATA(write_data[31 : 16]),
|
.WDATA(write_data[31 : 16]),
|
||||||
.WE((|we & system_mode_cs & bank1)),
|
.WE((|we & en & cs & bank1)),
|
||||||
.MASK({{8{~we[3]}}, {8{~we[2]}}})
|
.MASK({{8{~we[3]}}, {8{~we[2]}}})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -129,7 +126,7 @@ module fw_ram (
|
|||||||
bank1 = 1'h0;
|
bank1 = 1'h0;
|
||||||
tmp_read_data = 32'h0;
|
tmp_read_data = 32'h0;
|
||||||
|
|
||||||
if (system_mode_cs) begin
|
if (en & cs) begin
|
||||||
if (address[8]) begin
|
if (address[8]) begin
|
||||||
bank1 = 1'h1;
|
bank1 = 1'h1;
|
||||||
tmp_read_data = mem_read_data1;
|
tmp_read_data = mem_read_data1;
|
||||||
|
@ -78,18 +78,6 @@ FW as part of the loading of the app. The registers can't be written
|
|||||||
when the `ADDR_SYSTEM_MODE_CTRL` has been set.
|
when the `ADDR_SYSTEM_MODE_CTRL` has been set.
|
||||||
|
|
||||||
|
|
||||||
### Access to Blake2s
|
|
||||||
|
|
||||||
```
|
|
||||||
ADDR_BLAKE2S: 0x10
|
|
||||||
```
|
|
||||||
|
|
||||||
This register provides the 32-bit function pointer address to the
|
|
||||||
Blake2s hash function in the FW. It is written by FW during boot. The
|
|
||||||
register can't be written to when the `ADDR_SYSTEM_MODE_CTRL` has been
|
|
||||||
set.
|
|
||||||
|
|
||||||
|
|
||||||
### Access to CDI
|
### Access to CDI
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -164,8 +152,9 @@ ADDR_CPU_MON_LAST: 0x62
|
|||||||
Monitors events and state changes in the SoC and handles security
|
Monitors events and state changes in the SoC and handles security
|
||||||
violations. Currently checks for:
|
violations. Currently checks for:
|
||||||
|
|
||||||
1. Trying to execute instructions in FW\_RAM. *Always enabled.*
|
1. Trying to access memory that is outside of the defined size of the
|
||||||
2. Trying to access RAM outside of the physical memory. *Always enabled*
|
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
|
3. Trying to execute instructions from a memory area in RAM defined by
|
||||||
the application.
|
the application.
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ module tk1 #(
|
|||||||
input wire reset_n,
|
input wire reset_n,
|
||||||
|
|
||||||
input wire cpu_trap,
|
input wire cpu_trap,
|
||||||
output wire system_mode,
|
output wire rw_locked,
|
||||||
|
|
||||||
input wire [31 : 0] cpu_addr,
|
input wire [31 : 0] cpu_addr,
|
||||||
input wire cpu_instr,
|
input wire cpu_instr,
|
||||||
@ -45,6 +45,10 @@ module tk1 #(
|
|||||||
output wire gpio3,
|
output wire gpio3,
|
||||||
output wire gpio4,
|
output wire gpio4,
|
||||||
|
|
||||||
|
input wire access_level_hi,
|
||||||
|
|
||||||
|
output wire fw_ram_en,
|
||||||
|
|
||||||
input wire cs,
|
input wire cs,
|
||||||
input wire we,
|
input wire we,
|
||||||
input wire [ 7 : 0] address,
|
input wire [ 7 : 0] address,
|
||||||
@ -79,8 +83,6 @@ module tk1 #(
|
|||||||
localparam ADDR_APP_START = 8'h0c;
|
localparam ADDR_APP_START = 8'h0c;
|
||||||
localparam ADDR_APP_SIZE = 8'h0d;
|
localparam ADDR_APP_SIZE = 8'h0d;
|
||||||
|
|
||||||
localparam ADDR_BLAKE2S = 8'h10;
|
|
||||||
|
|
||||||
localparam ADDR_CDI_FIRST = 8'h20;
|
localparam ADDR_CDI_FIRST = 8'h20;
|
||||||
localparam ADDR_CDI_LAST = 8'h27;
|
localparam ADDR_CDI_LAST = 8'h27;
|
||||||
|
|
||||||
@ -107,6 +109,7 @@ module tk1 #(
|
|||||||
localparam FW_RAM_FIRST = 32'hd0000000;
|
localparam FW_RAM_FIRST = 32'hd0000000;
|
||||||
localparam FW_RAM_LAST = 32'hd00007ff;
|
localparam FW_RAM_LAST = 32'hd00007ff;
|
||||||
|
|
||||||
|
localparam FW_ROM_LAST = 32'h000017ff;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Registers including update variables and write enable.
|
// Registers including update variables and write enable.
|
||||||
@ -115,6 +118,7 @@ module tk1 #(
|
|||||||
reg cdi_mem_we;
|
reg cdi_mem_we;
|
||||||
|
|
||||||
reg system_mode_reg;
|
reg system_mode_reg;
|
||||||
|
reg system_mode_new;
|
||||||
reg system_mode_we;
|
reg system_mode_we;
|
||||||
|
|
||||||
reg [ 2 : 0] led_reg;
|
reg [ 2 : 0] led_reg;
|
||||||
@ -133,9 +137,6 @@ module tk1 #(
|
|||||||
reg [31 : 0] app_size_reg;
|
reg [31 : 0] app_size_reg;
|
||||||
reg app_size_we;
|
reg app_size_we;
|
||||||
|
|
||||||
reg [31 : 0] blake2s_addr_reg;
|
|
||||||
reg blake2s_addr_we;
|
|
||||||
|
|
||||||
reg [23 : 0] cpu_trap_ctr_reg;
|
reg [23 : 0] cpu_trap_ctr_reg;
|
||||||
reg [23 : 0] cpu_trap_ctr_new;
|
reg [23 : 0] cpu_trap_ctr_new;
|
||||||
reg [ 2 : 0] cpu_trap_led_reg;
|
reg [ 2 : 0] cpu_trap_led_reg;
|
||||||
@ -180,6 +181,11 @@ module tk1 #(
|
|||||||
reg spi_tx_data_vld;
|
reg spi_tx_data_vld;
|
||||||
wire spi_ready;
|
wire spi_ready;
|
||||||
wire [ 7 : 0] spi_rx_data;
|
wire [ 7 : 0] spi_rx_data;
|
||||||
|
wire spi_access_en;
|
||||||
|
|
||||||
|
wire rom_exec_en;
|
||||||
|
|
||||||
|
wire system_mode;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Concurrent connectivity for ports etc.
|
// Concurrent connectivity for ports etc.
|
||||||
@ -187,8 +193,6 @@ module tk1 #(
|
|||||||
assign read_data = tmp_read_data;
|
assign read_data = tmp_read_data;
|
||||||
assign ready = tmp_ready;
|
assign ready = tmp_ready;
|
||||||
|
|
||||||
assign system_mode = system_mode_reg;
|
|
||||||
|
|
||||||
assign force_trap = force_trap_reg;
|
assign force_trap = force_trap_reg;
|
||||||
|
|
||||||
assign gpio3 = gpio3_reg;
|
assign gpio3 = gpio3_reg;
|
||||||
@ -199,6 +203,12 @@ module tk1 #(
|
|||||||
|
|
||||||
assign system_reset = system_reset_reg;
|
assign system_reset = system_reset_reg;
|
||||||
|
|
||||||
|
assign system_mode = system_mode_reg;
|
||||||
|
|
||||||
|
assign rom_exec_en = !system_mode | access_level_hi;
|
||||||
|
assign fw_ram_en = !system_mode | access_level_hi;
|
||||||
|
assign spi_access_en = !system_mode | access_level_hi;
|
||||||
|
assign rw_locked = system_mode;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Module instance.
|
// Module instance.
|
||||||
@ -258,7 +268,6 @@ module tk1 #(
|
|||||||
gpio4_reg <= 1'h0;
|
gpio4_reg <= 1'h0;
|
||||||
app_start_reg <= 32'h0;
|
app_start_reg <= 32'h0;
|
||||||
app_size_reg <= APP_SIZE;
|
app_size_reg <= APP_SIZE;
|
||||||
blake2s_addr_reg <= 32'h0;
|
|
||||||
cdi_mem[0] <= 32'h0;
|
cdi_mem[0] <= 32'h0;
|
||||||
cdi_mem[1] <= 32'h0;
|
cdi_mem[1] <= 32'h0;
|
||||||
cdi_mem[2] <= 32'h0;
|
cdi_mem[2] <= 32'h0;
|
||||||
@ -290,7 +299,7 @@ module tk1 #(
|
|||||||
gpio2_reg[1] <= gpio2_reg[0];
|
gpio2_reg[1] <= gpio2_reg[0];
|
||||||
|
|
||||||
if (system_mode_we) begin
|
if (system_mode_we) begin
|
||||||
system_mode_reg <= 1'h1;
|
system_mode_reg <= system_mode_new;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (led_we) begin
|
if (led_we) begin
|
||||||
@ -313,10 +322,6 @@ module tk1 #(
|
|||||||
app_size_reg <= write_data;
|
app_size_reg <= write_data;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (blake2s_addr_we) begin
|
|
||||||
blake2s_addr_reg <= write_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (cdi_mem_we) begin
|
if (cdi_mem_we) begin
|
||||||
cdi_mem[address[2 : 0]] <= write_data;
|
cdi_mem[address[2 : 0]] <= write_data;
|
||||||
end
|
end
|
||||||
@ -381,10 +386,14 @@ module tk1 #(
|
|||||||
// Monitor events and state changes in the SoC, and handle
|
// Monitor events and state changes in the SoC, and handle
|
||||||
// security violations. We currently check for:
|
// 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.
|
// Trying to execute instructions in FW-RAM.
|
||||||
//
|
//
|
||||||
|
// Executing instructions in ROM, while ROM is marked as not
|
||||||
|
// executable.
|
||||||
|
//
|
||||||
// Trying to execute code in mem area set to be data access only.
|
// Trying to execute code in mem area set to be data access only.
|
||||||
// This requires execution monitor to have been setup and
|
// This requires execution monitor to have been setup and
|
||||||
// enabled.
|
// enabled.
|
||||||
@ -393,15 +402,88 @@ module tk1 #(
|
|||||||
force_trap_set = 1'h0;
|
force_trap_set = 1'h0;
|
||||||
|
|
||||||
if (cpu_valid) begin
|
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
|
if (cpu_addr[31 : 30] == 2'h1 & |cpu_addr[29 : 17]) begin
|
||||||
force_trap_set = 1'h1;
|
force_trap_set = 1'h1;
|
||||||
end
|
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_instr) begin
|
||||||
if ((cpu_addr >= FW_RAM_FIRST) && (cpu_addr <= FW_RAM_LAST)) begin
|
if ((cpu_addr >= FW_RAM_FIRST) && (cpu_addr <= FW_RAM_LAST)) begin
|
||||||
force_trap_set = 1'h1;
|
force_trap_set = 1'h1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (!rom_exec_en) begin
|
||||||
|
if (cpu_addr <= FW_ROM_LAST) begin // Only valid as long as ROM starts at address 0x00.
|
||||||
|
force_trap_set = 1'h1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if (cpu_mon_en_reg) begin
|
if (cpu_mon_en_reg) begin
|
||||||
if ((cpu_addr >= cpu_mon_first_reg) && (cpu_addr <= cpu_mon_last_reg)) begin
|
if ((cpu_addr >= cpu_mon_first_reg) && (cpu_addr <= cpu_mon_last_reg)) begin
|
||||||
force_trap_set = 1'h1;
|
force_trap_set = 1'h1;
|
||||||
@ -411,18 +493,32 @@ module tk1 #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// system_mode_ctrl
|
||||||
|
//
|
||||||
|
// Automatically lower privilege when executing above ROM.
|
||||||
|
// ----------------------------------------------------------------
|
||||||
|
always @* begin : system_mode_ctrl
|
||||||
|
system_mode_new = 1'h0;
|
||||||
|
system_mode_we = 1'h0;
|
||||||
|
|
||||||
|
if (cpu_valid & cpu_instr) begin
|
||||||
|
if (cpu_addr > FW_ROM_LAST) begin
|
||||||
|
system_mode_new = 1'h1;
|
||||||
|
system_mode_we = 1'h1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// api
|
// api
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
always @* begin : api
|
always @* begin : api
|
||||||
system_mode_we = 1'h0;
|
|
||||||
led_we = 1'h0;
|
led_we = 1'h0;
|
||||||
gpio3_we = 1'h0;
|
gpio3_we = 1'h0;
|
||||||
gpio4_we = 1'h0;
|
gpio4_we = 1'h0;
|
||||||
app_start_we = 1'h0;
|
app_start_we = 1'h0;
|
||||||
app_size_we = 1'h0;
|
app_size_we = 1'h0;
|
||||||
blake2s_addr_we = 1'h0;
|
|
||||||
cdi_mem_we = 1'h0;
|
cdi_mem_we = 1'h0;
|
||||||
ram_addr_rand_we = 1'h0;
|
ram_addr_rand_we = 1'h0;
|
||||||
ram_data_rand_we = 1'h0;
|
ram_data_rand_we = 1'h0;
|
||||||
@ -437,16 +533,12 @@ module tk1 #(
|
|||||||
spi_start = 1'h0;
|
spi_start = 1'h0;
|
||||||
spi_tx_data_vld = 1'h0;
|
spi_tx_data_vld = 1'h0;
|
||||||
|
|
||||||
spi_enable = write_data[0];
|
spi_enable = write_data[0] & spi_access_en;
|
||||||
spi_tx_data = write_data[7 : 0];
|
spi_tx_data = write_data[7 : 0] & {8{spi_access_en}};
|
||||||
|
|
||||||
if (cs) begin
|
if (cs) begin
|
||||||
tmp_ready = 1'h1;
|
tmp_ready = 1'h1;
|
||||||
if (we) begin
|
if (we) begin
|
||||||
if (address == ADDR_SYSTEM_MODE_CTRL) begin
|
|
||||||
system_mode_we = 1'h1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (address == ADDR_LED) begin
|
if (address == ADDR_LED) begin
|
||||||
led_we = 1'h1;
|
led_we = 1'h1;
|
||||||
end
|
end
|
||||||
@ -457,13 +549,13 @@ module tk1 #(
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_APP_START) begin
|
if (address == ADDR_APP_START) begin
|
||||||
if (!system_mode_reg) begin
|
if (!rw_locked) begin
|
||||||
app_start_we = 1'h1;
|
app_start_we = 1'h1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_APP_SIZE) begin
|
if (address == ADDR_APP_SIZE) begin
|
||||||
if (!system_mode_reg) begin
|
if (!rw_locked) begin
|
||||||
app_size_we = 1'h1;
|
app_size_we = 1'h1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -472,26 +564,20 @@ module tk1 #(
|
|||||||
system_reset_new = 1'h1;
|
system_reset_new = 1'h1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_BLAKE2S) begin
|
|
||||||
if (!system_mode_reg) begin
|
|
||||||
blake2s_addr_we = 1'h1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if ((address >= ADDR_CDI_FIRST) && (address <= ADDR_CDI_LAST)) begin
|
if ((address >= ADDR_CDI_FIRST) && (address <= ADDR_CDI_LAST)) begin
|
||||||
if (!system_mode_reg) begin
|
if (!rw_locked) begin
|
||||||
cdi_mem_we = 1'h1;
|
cdi_mem_we = 1'h1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_RAM_ADDR_RAND) begin
|
if (address == ADDR_RAM_ADDR_RAND) begin
|
||||||
if (!system_mode_reg) begin
|
if (!rw_locked) begin
|
||||||
ram_addr_rand_we = 1'h1;
|
ram_addr_rand_we = 1'h1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_RAM_DATA_RAND) begin
|
if (address == ADDR_RAM_DATA_RAND) begin
|
||||||
if (!system_mode_reg) begin
|
if (!rw_locked) begin
|
||||||
ram_data_rand_we = 1'h1;
|
ram_data_rand_we = 1'h1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -513,15 +599,21 @@ module tk1 #(
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_SPI_EN) begin
|
if (address == ADDR_SPI_EN) begin
|
||||||
spi_enable_vld = 1'h1;
|
if (spi_access_en) begin
|
||||||
|
spi_enable_vld = 1'h1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_SPI_XFER) begin
|
if (address == ADDR_SPI_XFER) begin
|
||||||
spi_start = 1'h1;
|
if (spi_access_en) begin
|
||||||
|
spi_start = 1'h1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_SPI_DATA) begin
|
if (address == ADDR_SPI_DATA) begin
|
||||||
spi_tx_data_vld = 1'h1;
|
if (spi_access_en) begin
|
||||||
|
spi_tx_data_vld = 1'h1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -558,26 +650,26 @@ module tk1 #(
|
|||||||
tmp_read_data = app_size_reg;
|
tmp_read_data = app_size_reg;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_BLAKE2S) begin
|
|
||||||
tmp_read_data = blake2s_addr_reg;
|
|
||||||
end
|
|
||||||
|
|
||||||
if ((address >= ADDR_CDI_FIRST) && (address <= ADDR_CDI_LAST)) begin
|
if ((address >= ADDR_CDI_FIRST) && (address <= ADDR_CDI_LAST)) begin
|
||||||
tmp_read_data = cdi_mem[address[2 : 0]];
|
tmp_read_data = cdi_mem[address[2 : 0]];
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((address >= ADDR_UDI_FIRST) && (address <= ADDR_UDI_LAST)) begin
|
if ((address >= ADDR_UDI_FIRST) && (address <= ADDR_UDI_LAST)) begin
|
||||||
if (!system_mode_reg) begin
|
if (!rw_locked) begin
|
||||||
tmp_read_data = udi_rdata;
|
tmp_read_data = udi_rdata;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_SPI_XFER) begin
|
if (address == ADDR_SPI_XFER) begin
|
||||||
tmp_read_data[0] = spi_ready;
|
if (spi_access_en) begin
|
||||||
|
tmp_read_data[0] = spi_ready;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (address == ADDR_SPI_DATA) begin
|
if (address == ADDR_SPI_DATA) begin
|
||||||
tmp_read_data[7 : 0] = spi_rx_data;
|
if (spi_access_en) begin
|
||||||
|
tmp_read_data[7 : 0] = spi_rx_data;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -18,7 +18,7 @@ module tb_tk1 ();
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Internal constant and parameter definitions.
|
// Internal constant and parameter definitions.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
parameter DEBUG = 1;
|
parameter DEBUG = 0;
|
||||||
|
|
||||||
parameter CLK_HALF_PERIOD = 1;
|
parameter CLK_HALF_PERIOD = 1;
|
||||||
parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
|
parameter CLK_PERIOD = 2 * CLK_HALF_PERIOD;
|
||||||
@ -62,6 +62,7 @@ module tb_tk1 ();
|
|||||||
localparam ADDR_SPI_XFER = 8'h81;
|
localparam ADDR_SPI_XFER = 8'h81;
|
||||||
localparam ADDR_SPI_DATA = 8'h82;
|
localparam ADDR_SPI_DATA = 8'h82;
|
||||||
|
|
||||||
|
localparam APP_RAM_START = 32'h40000000;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Register and Wire declarations.
|
// Register and Wire declarations.
|
||||||
@ -76,7 +77,7 @@ module tb_tk1 ();
|
|||||||
reg tb_clk;
|
reg tb_clk;
|
||||||
reg tb_reset_n;
|
reg tb_reset_n;
|
||||||
reg tb_cpu_trap;
|
reg tb_cpu_trap;
|
||||||
wire tb_system_mode;
|
wire tb_rw_locked;
|
||||||
|
|
||||||
reg [31 : 0] tb_cpu_addr;
|
reg [31 : 0] tb_cpu_addr;
|
||||||
reg tb_cpu_instr;
|
reg tb_cpu_instr;
|
||||||
@ -95,6 +96,10 @@ module tb_tk1 ();
|
|||||||
wire tb_gpio3;
|
wire tb_gpio3;
|
||||||
wire tb_gpio4;
|
wire tb_gpio4;
|
||||||
|
|
||||||
|
reg tb_access_level_hi;
|
||||||
|
|
||||||
|
wire tb_fw_ram_en;
|
||||||
|
|
||||||
wire tb_spi_ss;
|
wire tb_spi_ss;
|
||||||
wire tb_spi_sck;
|
wire tb_spi_sck;
|
||||||
wire tb_spi_mosi;
|
wire tb_spi_mosi;
|
||||||
@ -122,7 +127,7 @@ module tb_tk1 ();
|
|||||||
.reset_n(tb_reset_n),
|
.reset_n(tb_reset_n),
|
||||||
|
|
||||||
.cpu_trap(tb_cpu_trap),
|
.cpu_trap(tb_cpu_trap),
|
||||||
.system_mode(tb_system_mode),
|
.rw_locked(tb_rw_locked),
|
||||||
|
|
||||||
.cpu_addr (tb_cpu_addr),
|
.cpu_addr (tb_cpu_addr),
|
||||||
.cpu_instr (tb_cpu_instr),
|
.cpu_instr (tb_cpu_instr),
|
||||||
@ -141,6 +146,10 @@ module tb_tk1 ();
|
|||||||
.gpio3(tb_gpio3),
|
.gpio3(tb_gpio3),
|
||||||
.gpio4(tb_gpio4),
|
.gpio4(tb_gpio4),
|
||||||
|
|
||||||
|
.access_level_hi(tb_access_level_hi),
|
||||||
|
|
||||||
|
.fw_ram_en(tb_fw_ram_en),
|
||||||
|
|
||||||
.spi_ss (tb_spi_ss),
|
.spi_ss (tb_spi_ss),
|
||||||
.spi_sck (tb_spi_sck),
|
.spi_sck (tb_spi_sck),
|
||||||
.spi_mosi(tb_spi_mosi),
|
.spi_mosi(tb_spi_mosi),
|
||||||
@ -192,7 +201,7 @@ module tb_tk1 ();
|
|||||||
$display("------------");
|
$display("------------");
|
||||||
if (tb_main_monitor) begin
|
if (tb_main_monitor) begin
|
||||||
$display("Inputs and outputs:");
|
$display("Inputs and outputs:");
|
||||||
$display("tb_cpu_trap: 0x%1x, system_mode: 0x%1x", tb_cpu_trap, tb_system_mode);
|
$display("tb_cpu_trap: 0x%1x, system_mode: 0x%1x", tb_cpu_trap, dut.system_mode);
|
||||||
$display("cpu_addr: 0x%08x, cpu_instr: 0x%1x, cpu_valid: 0x%1x, force_tap: 0x%1x",
|
$display("cpu_addr: 0x%08x, cpu_instr: 0x%1x, cpu_valid: 0x%1x, force_tap: 0x%1x",
|
||||||
tb_cpu_addr, tb_cpu_instr, tb_cpu_valid, tb_force_trap);
|
tb_cpu_addr, tb_cpu_instr, tb_cpu_valid, tb_force_trap);
|
||||||
$display("ram_addr_rand: 0x%08x, ram_data_rand: 0x%08x", tb_ram_addr_rand,
|
$display("ram_addr_rand: 0x%08x, ram_data_rand: 0x%08x", tb_ram_addr_rand,
|
||||||
@ -227,7 +236,6 @@ module tb_tk1 ();
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
task reset_dut;
|
task reset_dut;
|
||||||
begin
|
begin
|
||||||
$display("--- Toggle reset.");
|
|
||||||
tb_reset_n = 0;
|
tb_reset_n = 0;
|
||||||
#(2 * CLK_PERIOD);
|
#(2 * CLK_PERIOD);
|
||||||
tb_reset_n = 1;
|
tb_reset_n = 1;
|
||||||
@ -277,6 +285,8 @@ module tb_tk1 ();
|
|||||||
tb_gpio1 = 1'h0;
|
tb_gpio1 = 1'h0;
|
||||||
tb_gpio2 = 1'h0;
|
tb_gpio2 = 1'h0;
|
||||||
|
|
||||||
|
tb_access_level_hi = 1'h0;
|
||||||
|
|
||||||
tb_cs = 1'h0;
|
tb_cs = 1'h0;
|
||||||
tb_we = 1'h0;
|
tb_we = 1'h0;
|
||||||
tb_address = 8'h0;
|
tb_address = 8'h0;
|
||||||
@ -285,6 +295,25 @@ module tb_tk1 ();
|
|||||||
endtask // init_sim
|
endtask // init_sim
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// restore_mem_bus()
|
||||||
|
//
|
||||||
|
// Restore memory bus to its initial state
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
task restore_mem_bus();
|
||||||
|
begin : restore_mem_bus
|
||||||
|
tb_cpu_addr = 32'h0;
|
||||||
|
tb_cpu_instr = 1'h0;
|
||||||
|
tb_cpu_valid = 1'h0;
|
||||||
|
|
||||||
|
tb_cs = 1'h0;
|
||||||
|
tb_we = 1'h0;
|
||||||
|
tb_address = 8'h0;
|
||||||
|
tb_write_data = 32'h0;
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// write_word()
|
// write_word()
|
||||||
//
|
//
|
||||||
@ -301,7 +330,7 @@ module tb_tk1 ();
|
|||||||
tb_write_data = word;
|
tb_write_data = word;
|
||||||
tb_cs = 1;
|
tb_cs = 1;
|
||||||
tb_we = 1;
|
tb_we = 1;
|
||||||
#(2 * CLK_PERIOD);
|
#(CLK_PERIOD);
|
||||||
tb_cs = 0;
|
tb_cs = 0;
|
||||||
tb_we = 0;
|
tb_we = 0;
|
||||||
end
|
end
|
||||||
@ -320,12 +349,16 @@ module tb_tk1 ();
|
|||||||
reg [31 : 0] read_data;
|
reg [31 : 0] read_data;
|
||||||
|
|
||||||
tb_address = address;
|
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);
|
#(CLK_PERIOD);
|
||||||
read_data = tb_read_data;
|
read_data = tb_read_data;
|
||||||
|
|
||||||
#(CLK_PERIOD);
|
#(CLK_PERIOD);
|
||||||
|
tb_cpu_valid = 1'h0;
|
||||||
tb_cs = 1'h0;
|
tb_cs = 1'h0;
|
||||||
end
|
end
|
||||||
endtask // read_word
|
endtask // read_word
|
||||||
@ -354,21 +387,138 @@ module tb_tk1 ();
|
|||||||
#(CLK_PERIOD);
|
#(CLK_PERIOD);
|
||||||
tb_cs = 1'h0;
|
tb_cs = 1'h0;
|
||||||
|
|
||||||
if (DEBUG) begin
|
if (read_data == expected) begin
|
||||||
if (read_data == expected) begin
|
if (DEBUG) begin
|
||||||
$display("--- Reading 0x%08x from 0x%02x.", read_data, address);
|
$display("--- Reading 0x%08x from 0x%02x.", read_data, address);
|
||||||
end
|
end
|
||||||
else begin
|
end
|
||||||
$display("--- Error: Got 0x%08x when reading from 0x%02x, expected 0x%08x", read_data,
|
else begin
|
||||||
address, expected);
|
$display("--- Error: Got 0x%08x when reading from 0x%02x, expected 0x%08x", read_data,
|
||||||
error_ctr = error_ctr + 1;
|
address, expected);
|
||||||
end
|
error_ctr = error_ctr + 1;
|
||||||
$display("");
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endtask // read_check_word
|
endtask // read_check_word
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// check_equal()
|
||||||
|
//
|
||||||
|
// Check that two values are equal
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
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", value, expected);
|
||||||
|
error_ctr = error_ctr + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask // check_equal
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// fetch_instruction()
|
||||||
|
//
|
||||||
|
// Simulate fetch of an instruction at specified address.
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
task fetch_instruction(input [31 : 0] address);
|
||||||
|
begin : fetch_instruction
|
||||||
|
tb_cpu_addr = address;
|
||||||
|
tb_cpu_instr = 1'h1;
|
||||||
|
tb_cpu_valid = 1'h1;
|
||||||
|
#(CLK_PERIOD);
|
||||||
|
tb_cpu_addr = 32'h0;
|
||||||
|
tb_cpu_instr = 1'h0;
|
||||||
|
tb_cpu_valid = 1'h0;
|
||||||
|
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()
|
// test1()
|
||||||
// Read out name and version.
|
// Read out name and version.
|
||||||
@ -400,10 +550,27 @@ module tb_tk1 ();
|
|||||||
|
|
||||||
$display("");
|
$display("");
|
||||||
$display("--- test2: Read out UDI started.");
|
$display("--- test2: Read out UDI started.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
|
reset_dut();
|
||||||
|
|
||||||
read_check_word(ADDR_UDI_FIRST, 32'h00010203);
|
read_check_word(ADDR_UDI_FIRST, 32'h00010203);
|
||||||
read_check_word(ADDR_UDI_LAST, 32'h04050607);
|
read_check_word(ADDR_UDI_LAST, 32'h04050607);
|
||||||
|
|
||||||
|
$display("--- test2: Switch to app mode.");
|
||||||
|
fetch_instruction(APP_RAM_START);
|
||||||
|
|
||||||
|
read_check_word(ADDR_UDI_FIRST, 32'h0);
|
||||||
|
read_check_word(ADDR_UDI_LAST, 32'h0);
|
||||||
|
|
||||||
|
$display("--- test2: Enter syscall.");
|
||||||
|
tb_access_level_hi = 1;
|
||||||
|
|
||||||
|
read_check_word(ADDR_UDI_FIRST, 32'h0);
|
||||||
|
read_check_word(ADDR_UDI_LAST, 32'h0);
|
||||||
|
|
||||||
|
$display("--- test2: Leave syscall.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
|
|
||||||
$display("--- test2: completed.");
|
$display("--- test2: completed.");
|
||||||
$display("");
|
$display("");
|
||||||
end
|
end
|
||||||
@ -418,6 +585,10 @@ module tb_tk1 ();
|
|||||||
begin
|
begin
|
||||||
tc_ctr = tc_ctr + 1;
|
tc_ctr = tc_ctr + 1;
|
||||||
|
|
||||||
|
$display("--- test5: Reset DUT to switch to fw mode.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
|
reset_dut();
|
||||||
|
|
||||||
$display("");
|
$display("");
|
||||||
$display("--- test3: Write and read CDI started.");
|
$display("--- test3: Write and read CDI started.");
|
||||||
$display("--- test3: Write CDI.");
|
$display("--- test3: Write CDI.");
|
||||||
@ -441,9 +612,9 @@ module tb_tk1 ();
|
|||||||
read_check_word(ADDR_CDI_LAST + 0, 32'h70717273);
|
read_check_word(ADDR_CDI_LAST + 0, 32'h70717273);
|
||||||
|
|
||||||
$display("--- test3: Switch to app mode.");
|
$display("--- test3: Switch to app mode.");
|
||||||
write_word(ADDR_SYSTEM_MODE_CTRL, 32'hdeadbeef);
|
fetch_instruction(APP_RAM_START);
|
||||||
|
|
||||||
$display("--- test3: Try to write CDI again.");
|
$display("--- test3: Try to write CDI from app mode.");
|
||||||
write_word(ADDR_CDI_FIRST + 0, 32'hfffefdfc);
|
write_word(ADDR_CDI_FIRST + 0, 32'hfffefdfc);
|
||||||
write_word(ADDR_CDI_FIRST + 1, 32'hefeeedec);
|
write_word(ADDR_CDI_FIRST + 1, 32'hefeeedec);
|
||||||
write_word(ADDR_CDI_FIRST + 2, 32'hdfdedddc);
|
write_word(ADDR_CDI_FIRST + 2, 32'hdfdedddc);
|
||||||
@ -453,7 +624,7 @@ module tb_tk1 ();
|
|||||||
write_word(ADDR_CDI_FIRST + 6, 32'h8f8e8d8c);
|
write_word(ADDR_CDI_FIRST + 6, 32'h8f8e8d8c);
|
||||||
write_word(ADDR_CDI_FIRST + 7, 32'h7f7e7d7c);
|
write_word(ADDR_CDI_FIRST + 7, 32'h7f7e7d7c);
|
||||||
|
|
||||||
$display("--- test3: Read CDI again.");
|
$display("--- test3: Read CDI from app mode.");
|
||||||
read_check_word(ADDR_CDI_FIRST + 0, 32'hf0f1f2f3);
|
read_check_word(ADDR_CDI_FIRST + 0, 32'hf0f1f2f3);
|
||||||
read_check_word(ADDR_CDI_FIRST + 1, 32'he0e1e2e3);
|
read_check_word(ADDR_CDI_FIRST + 1, 32'he0e1e2e3);
|
||||||
read_check_word(ADDR_CDI_FIRST + 2, 32'hd0d1d2d3);
|
read_check_word(ADDR_CDI_FIRST + 2, 32'hd0d1d2d3);
|
||||||
@ -463,46 +634,38 @@ module tb_tk1 ();
|
|||||||
read_check_word(ADDR_CDI_FIRST + 6, 32'h80818283);
|
read_check_word(ADDR_CDI_FIRST + 6, 32'h80818283);
|
||||||
read_check_word(ADDR_CDI_LAST + 0, 32'h70717273);
|
read_check_word(ADDR_CDI_LAST + 0, 32'h70717273);
|
||||||
|
|
||||||
|
$display("--- test3: Enter syscall.");
|
||||||
|
tb_access_level_hi = 1;
|
||||||
|
|
||||||
|
$display("--- test3: Try to write CDI from syscall.");
|
||||||
|
write_word(ADDR_CDI_FIRST + 0, 32'hfffefdfc);
|
||||||
|
write_word(ADDR_CDI_FIRST + 1, 32'hefeeedec);
|
||||||
|
write_word(ADDR_CDI_FIRST + 2, 32'hdfdedddc);
|
||||||
|
write_word(ADDR_CDI_FIRST + 3, 32'hcfcecdcc);
|
||||||
|
write_word(ADDR_CDI_FIRST + 4, 32'hafaeadac);
|
||||||
|
write_word(ADDR_CDI_FIRST + 5, 32'h9f9e9d9c);
|
||||||
|
write_word(ADDR_CDI_FIRST + 6, 32'h8f8e8d8c);
|
||||||
|
write_word(ADDR_CDI_FIRST + 7, 32'h7f7e7d7c);
|
||||||
|
|
||||||
|
$display("--- test3: Read CDI from syscall.");
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 0, 32'hf0f1f2f3);
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 1, 32'he0e1e2e3);
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 2, 32'hd0d1d2d3);
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 3, 32'hc0c1c2c3);
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 4, 32'ha0a1a2a3);
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 5, 32'h90919293);
|
||||||
|
read_check_word(ADDR_CDI_FIRST + 6, 32'h80818283);
|
||||||
|
read_check_word(ADDR_CDI_LAST + 0, 32'h70717273);
|
||||||
|
|
||||||
|
$display("--- test3: Leave syscall.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
|
|
||||||
$display("--- test3: completed.");
|
$display("--- test3: completed.");
|
||||||
$display("");
|
$display("");
|
||||||
end
|
end
|
||||||
endtask // test3
|
endtask // test3
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
// test4()
|
|
||||||
// Write and read blake2s entry point.
|
|
||||||
//----------------------------------------------------------------
|
|
||||||
task test4;
|
|
||||||
begin
|
|
||||||
tc_ctr = tc_ctr + 1;
|
|
||||||
|
|
||||||
$display("");
|
|
||||||
$display("--- test4: Write and read blake2s entry point in fw mode started.");
|
|
||||||
$display("--- test4: Reset DUT to switch to fw mode.");
|
|
||||||
reset_dut();
|
|
||||||
|
|
||||||
$display("--- test4: Write Blake2s entry point.");
|
|
||||||
write_word(ADDR_BLAKE2S, 32'hcafebabe);
|
|
||||||
|
|
||||||
$display("--- test4: Read Blake2s entry point.");
|
|
||||||
read_check_word(ADDR_BLAKE2S, 32'hcafebabe);
|
|
||||||
|
|
||||||
$display("--- test4: Switch to app mode.");
|
|
||||||
write_word(ADDR_SYSTEM_MODE_CTRL, 32'hf00ff00f);
|
|
||||||
|
|
||||||
$display("--- test4: Write Blake2s entry point again.");
|
|
||||||
write_word(ADDR_BLAKE2S, 32'hdeadbeef);
|
|
||||||
|
|
||||||
$display("--- test4: Read Blake2s entry point again");
|
|
||||||
read_check_word(ADDR_BLAKE2S, 32'hcafebabe);
|
|
||||||
|
|
||||||
$display("--- test4: completed.");
|
|
||||||
$display("");
|
|
||||||
end
|
|
||||||
endtask // test4
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// test5()
|
// test5()
|
||||||
// Write and read APP start address end size.
|
// Write and read APP start address end size.
|
||||||
@ -525,7 +688,7 @@ module tb_tk1 ();
|
|||||||
read_check_word(ADDR_APP_SIZE, 32'h47114711);
|
read_check_word(ADDR_APP_SIZE, 32'h47114711);
|
||||||
|
|
||||||
$display("--- test5: Switch to app mode.");
|
$display("--- test5: Switch to app mode.");
|
||||||
write_word(ADDR_SYSTEM_MODE_CTRL, 32'hf000000);
|
fetch_instruction(APP_RAM_START);
|
||||||
|
|
||||||
$display("--- test5: Write app start address and size again.");
|
$display("--- test5: Write app start address and size again.");
|
||||||
write_word(ADDR_APP_START, 32'hdeadbeef);
|
write_word(ADDR_APP_START, 32'hdeadbeef);
|
||||||
@ -543,7 +706,7 @@ module tb_tk1 ();
|
|||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// test6()
|
// test6()
|
||||||
// Write RAM address and data randomizatio in fw mode.
|
// Write and read RAM-address and data randomization.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
task test6;
|
task test6;
|
||||||
begin
|
begin
|
||||||
@ -552,6 +715,7 @@ module tb_tk1 ();
|
|||||||
$display("");
|
$display("");
|
||||||
$display("--- test6: Write RAM addr and data randomization in fw mode.");
|
$display("--- test6: Write RAM addr and data randomization in fw mode.");
|
||||||
$display("--- test6: Reset DUT to switch to fw mode.");
|
$display("--- test6: Reset DUT to switch to fw mode.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
reset_dut();
|
reset_dut();
|
||||||
|
|
||||||
$display("--- test6: Write to ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND .");
|
$display("--- test6: Write to ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND .");
|
||||||
@ -562,9 +726,14 @@ module tb_tk1 ();
|
|||||||
"--- test6: Check value in dut ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND registers.");
|
"--- test6: Check value in dut ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND registers.");
|
||||||
$display("--- test6: ram_addr_rand_reg: 0x%04x, ram_data_rand_reg: 0x%08x",
|
$display("--- test6: ram_addr_rand_reg: 0x%04x, ram_data_rand_reg: 0x%08x",
|
||||||
dut.ram_addr_rand, dut.ram_data_rand);
|
dut.ram_addr_rand, dut.ram_data_rand);
|
||||||
|
check_equal(dut.ram_addr_rand, 15'h1337);
|
||||||
|
check_equal(dut.ram_data_rand, 32'h47114711);
|
||||||
|
read_check_word(ADDR_RAM_ADDR_RAND, 32'h0);
|
||||||
|
read_check_word(ADDR_RAM_DATA_RAND, 32'h0);
|
||||||
|
|
||||||
|
|
||||||
$display("--- test6: Switch to app mode.");
|
$display("--- test6: Switch to app mode.");
|
||||||
write_word(ADDR_SYSTEM_MODE_CTRL, 32'hf000000);
|
fetch_instruction(APP_RAM_START);
|
||||||
|
|
||||||
$display("--- test6: Write to ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND again.");
|
$display("--- test6: Write to ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND again.");
|
||||||
write_word(ADDR_RAM_ADDR_RAND, 32'hdeadbeef);
|
write_word(ADDR_RAM_ADDR_RAND, 32'hdeadbeef);
|
||||||
@ -574,6 +743,30 @@ module tb_tk1 ();
|
|||||||
"--- test6: Check value in dut ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND registers.");
|
"--- test6: Check value in dut ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND registers.");
|
||||||
$display("--- test6: ram_addr_rand_reg: 0x%04x, ram_data_rand_reg: 0x%08x",
|
$display("--- test6: ram_addr_rand_reg: 0x%04x, ram_data_rand_reg: 0x%08x",
|
||||||
dut.ram_addr_rand, dut.ram_data_rand);
|
dut.ram_addr_rand, dut.ram_data_rand);
|
||||||
|
check_equal(dut.ram_addr_rand, 15'h1337);
|
||||||
|
check_equal(dut.ram_data_rand, 32'h47114711);
|
||||||
|
read_check_word(ADDR_RAM_ADDR_RAND, 32'h0);
|
||||||
|
read_check_word(ADDR_RAM_DATA_RAND, 32'h0);
|
||||||
|
|
||||||
|
|
||||||
|
$display("--- test6: Enter syscall.");
|
||||||
|
tb_access_level_hi = 1;
|
||||||
|
|
||||||
|
$display("--- test6: Write to ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND again.");
|
||||||
|
write_word(ADDR_RAM_ADDR_RAND, 32'hdeadbeef);
|
||||||
|
write_word(ADDR_RAM_DATA_RAND, 32'hf00ff00f);
|
||||||
|
|
||||||
|
$display(
|
||||||
|
"--- test6: Check value in dut ADDR_RAM_ADDR_RAND and ADDR_RAM_DATA_RAND registers.");
|
||||||
|
$display("--- test6: ram_addr_rand_reg: 0x%04x, ram_data_rand_reg: 0x%08x",
|
||||||
|
dut.ram_addr_rand, dut.ram_data_rand);
|
||||||
|
check_equal(dut.ram_addr_rand, 15'h1337);
|
||||||
|
check_equal(dut.ram_data_rand, 32'h47114711);
|
||||||
|
read_check_word(ADDR_RAM_ADDR_RAND, 32'h0);
|
||||||
|
read_check_word(ADDR_RAM_DATA_RAND, 32'h0);
|
||||||
|
|
||||||
|
$display("--- test6: Leave syscall.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
|
|
||||||
$display("--- test6: completed.");
|
$display("--- test6: completed.");
|
||||||
$display("");
|
$display("");
|
||||||
@ -655,17 +848,20 @@ module tb_tk1 ();
|
|||||||
write_word(ADDR_CPU_MON_LAST, 32'hdeadcafe);
|
write_word(ADDR_CPU_MON_LAST, 32'hdeadcafe);
|
||||||
$display("--- test9: cpu_mon_first_reg: 0x%08x, cpu_mon_last_reg: 0x%08x",
|
$display("--- test9: cpu_mon_first_reg: 0x%08x, cpu_mon_last_reg: 0x%08x",
|
||||||
dut.cpu_mon_first_reg, dut.cpu_mon_last_reg);
|
dut.cpu_mon_first_reg, dut.cpu_mon_last_reg);
|
||||||
|
check_equal(dut.cpu_mon_first_reg, 32'h10000000);
|
||||||
|
check_equal(dut.cpu_mon_last_reg, 32'h20000000);
|
||||||
|
|
||||||
$display("--- test9: force_trap before illegal access: 0x%1x", tb_force_trap);
|
$display("--- test9: force_trap before illegal access: 0x%1x", tb_force_trap);
|
||||||
$display("--- test9: Creating an illegal access.");
|
$display("--- test9: Creating an illegal access.");
|
||||||
|
|
||||||
tb_cpu_addr = 32'h13371337;
|
fetch_instruction(32'h13371337);
|
||||||
tb_cpu_instr = 1'h1;
|
|
||||||
tb_cpu_valid = 1'h1;
|
|
||||||
#(2 * CLK_PERIOD);
|
|
||||||
$display("--- test9: cpu_addr: 0x%08x, cpu_instr: 0x%1x, cpu_valid: 0x%1x", tb_cpu_addr,
|
$display("--- test9: cpu_addr: 0x%08x, cpu_instr: 0x%1x, cpu_valid: 0x%1x", tb_cpu_addr,
|
||||||
tb_cpu_instr, tb_cpu_valid);
|
tb_cpu_instr, tb_cpu_valid);
|
||||||
|
check_equal(dut.cpu_mon_first_reg, 32'h10000000);
|
||||||
|
check_equal(dut.cpu_mon_last_reg, 32'h20000000);
|
||||||
|
|
||||||
$display("--- test9: force_trap: 0x%1x", tb_force_trap);
|
$display("--- test9: force_trap: 0x%1x", tb_force_trap);
|
||||||
|
check_equal(tb_force_trap, 1);
|
||||||
|
|
||||||
$display("--- test9: completed.");
|
$display("--- test9: completed.");
|
||||||
$display("");
|
$display("");
|
||||||
@ -673,6 +869,66 @@ module tb_tk1 ();
|
|||||||
endtask // test9
|
endtask // test9
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// check_inverting_spi_loopback_transfer_succeeds()
|
||||||
|
// Do an SPI tranfer. Check that the received value is the inverse
|
||||||
|
// of the value sent.
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
task check_inverting_spi_loopback_transfer_succeeds(input [32 : 0] data);
|
||||||
|
begin : check_inverting_spi_loopback_transfer
|
||||||
|
$display("--- test10: Sending a byte.");
|
||||||
|
write_word(ADDR_SPI_EN, 32'h1);
|
||||||
|
write_word(ADDR_SPI_DATA, data);
|
||||||
|
write_word(ADDR_SPI_XFER, 32'h1);
|
||||||
|
|
||||||
|
// Ready ready flag in SPI until it is set.
|
||||||
|
read_word(ADDR_SPI_XFER);
|
||||||
|
while (!tb_read_data) begin
|
||||||
|
read_word(ADDR_SPI_XFER);
|
||||||
|
end
|
||||||
|
$display("--- test10: Byte should have been sent.");
|
||||||
|
|
||||||
|
#(2 * CLK_PERIOD);
|
||||||
|
read_check_word(ADDR_SPI_DATA, ~data[7 : 0] & 8'hff);
|
||||||
|
write_word(ADDR_SPI_EN, 32'h0);
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// check_spi_does_not_transfer()
|
||||||
|
// Do an SPI transfer. Check that the SS, SCK and MISO signal are
|
||||||
|
// not active.
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
task check_spi_does_not_transfer;
|
||||||
|
begin : check_spi_does_not_transfer
|
||||||
|
reg [31 : 0] wait_ctr;
|
||||||
|
reg error;
|
||||||
|
localparam CLK_PER_SPI_BIT = 3;
|
||||||
|
localparam WAIT_MARGIN = 10;
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
wait_ctr = CLK_PER_SPI_BIT * 8 * WAIT_MARGIN;
|
||||||
|
|
||||||
|
$display("--- test10: Sending a byte.");
|
||||||
|
write_word(ADDR_SPI_EN, 32'h1);
|
||||||
|
write_word(ADDR_SPI_DATA, 32'haa);
|
||||||
|
write_word(ADDR_SPI_XFER, 32'h1);
|
||||||
|
|
||||||
|
$display("--- test10: Waiting to see if SPI signals change state.");
|
||||||
|
while (!error && (wait_ctr != 0)) begin
|
||||||
|
if (~tb_spi_ss || tb_spi_sck || tb_spi_mosi) begin
|
||||||
|
$display("--- Error: SPI signals changed state");
|
||||||
|
error_ctr = error_ctr + 1;
|
||||||
|
error = 1;
|
||||||
|
end
|
||||||
|
#(CLK_PERIOD);
|
||||||
|
wait_ctr = wait_ctr - 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// test10()
|
// test10()
|
||||||
// SPI master loopback test.
|
// SPI master loopback test.
|
||||||
@ -683,28 +939,28 @@ module tb_tk1 ();
|
|||||||
tb_monitor = 0;
|
tb_monitor = 0;
|
||||||
tb_spi_monitor = 0;
|
tb_spi_monitor = 0;
|
||||||
|
|
||||||
|
restore_mem_bus();
|
||||||
|
reset_dut();
|
||||||
|
|
||||||
$display("");
|
$display("");
|
||||||
$display("--- test10: Loopback in SPI Master started.");
|
$display("--- test10: Loopback in SPI Master started.");
|
||||||
|
|
||||||
#(CLK_PERIOD);
|
#(CLK_PERIOD);
|
||||||
|
|
||||||
// Sending 0xa7 trough the inverting loopback.
|
check_inverting_spi_loopback_transfer_succeeds(32'ha7);
|
||||||
$display("--- test10: Sending a byte.");
|
|
||||||
write_word(ADDR_SPI_EN, 32'h1);
|
|
||||||
write_word(ADDR_SPI_DATA, 32'ha7);
|
|
||||||
write_word(ADDR_SPI_XFER, 32'h1);
|
|
||||||
|
|
||||||
// Ready ready flag in SPI until it is set.
|
$display("--- test10: Switch to app mode.");
|
||||||
read_word(ADDR_SPI_XFER);
|
fetch_instruction(APP_RAM_START);
|
||||||
while (!tb_read_data) begin
|
|
||||||
read_word(ADDR_SPI_XFER);
|
|
||||||
end
|
|
||||||
$display("--- test10: Byte should have been sent.");
|
|
||||||
|
|
||||||
// 0x58 is the inverse of 0xa7.
|
check_spi_does_not_transfer();
|
||||||
#(2 * CLK_PERIOD);
|
|
||||||
read_check_word(ADDR_SPI_DATA, 32'h58);
|
$display("--- test10: Enter syscall.");
|
||||||
write_word(ADDR_SPI_EN, 32'h0);
|
tb_access_level_hi = 1;
|
||||||
|
|
||||||
|
check_inverting_spi_loopback_transfer_succeeds(32'hc8);
|
||||||
|
|
||||||
|
$display("--- test10: Leave syscall.");
|
||||||
|
tb_access_level_hi = 0;
|
||||||
|
|
||||||
tb_monitor = 0;
|
tb_monitor = 0;
|
||||||
tb_spi_monitor = 0;
|
tb_spi_monitor = 0;
|
||||||
@ -714,6 +970,106 @@ module tb_tk1 ();
|
|||||||
end
|
end
|
||||||
endtask // test10
|
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()
|
// exit_with_error_code()
|
||||||
//
|
//
|
||||||
@ -746,7 +1102,6 @@ module tb_tk1 ();
|
|||||||
test1();
|
test1();
|
||||||
test2();
|
test2();
|
||||||
test3();
|
test3();
|
||||||
test4();
|
|
||||||
test5();
|
test5();
|
||||||
test6();
|
test6();
|
||||||
test7();
|
test7();
|
||||||
@ -754,6 +1109,7 @@ module tb_tk1 ();
|
|||||||
test9();
|
test9();
|
||||||
test9();
|
test9();
|
||||||
test10();
|
test10();
|
||||||
|
test11();
|
||||||
|
|
||||||
display_test_result();
|
display_test_result();
|
||||||
$display("");
|
$display("");
|
||||||
|
@ -55,6 +55,9 @@ module uart (
|
|||||||
input wire rxd,
|
input wire rxd,
|
||||||
output wire txd,
|
output wire txd,
|
||||||
|
|
||||||
|
input wire ch552_cts,
|
||||||
|
output wire fpga_cts,
|
||||||
|
|
||||||
input wire cs,
|
input wire cs,
|
||||||
input wire we,
|
input wire we,
|
||||||
input wire [ 7 : 0] address,
|
input wire [ 7 : 0] address,
|
||||||
@ -79,10 +82,10 @@ module uart (
|
|||||||
// The default bit rate is based on target clock frequency
|
// The default bit rate is based on target clock frequency
|
||||||
// divided by the bit rate times in order to hit the
|
// divided by the bit rate times in order to hit the
|
||||||
// center of the bits. I.e.
|
// center of the bits. I.e.
|
||||||
// Clock: 21 MHz, 62500 bps
|
// Clock: 21 MHz, 500 kbps
|
||||||
// Divisor = 21E6 / 62500 = 336
|
// Divisor = 21E6 / 500E3 = 42
|
||||||
// This also satisfies 1E6 % bps == 0 for the CH552 MCU used for USB-serial
|
// 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_DATA_BITS = 4'h8;
|
||||||
localparam DEFAULT_STOP_BITS = 2'h1;
|
localparam DEFAULT_STOP_BITS = 2'h1;
|
||||||
|
|
||||||
@ -110,6 +113,7 @@ module uart (
|
|||||||
reg [31 : 0] tmp_read_data;
|
reg [31 : 0] tmp_read_data;
|
||||||
reg tmp_ready;
|
reg tmp_ready;
|
||||||
|
|
||||||
|
reg [ 1 : 0] ch552_cts_reg;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Concurrent connectivity for ports etc.
|
// Concurrent connectivity for ports etc.
|
||||||
@ -158,9 +162,24 @@ module uart (
|
|||||||
|
|
||||||
.out_syn (fifo_out_syn),
|
.out_syn (fifo_out_syn),
|
||||||
.out_data(fifo_out_data),
|
.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
|
// api
|
||||||
//
|
//
|
||||||
@ -208,7 +227,7 @@ module uart (
|
|||||||
end
|
end
|
||||||
|
|
||||||
ADDR_TX_STATUS: begin
|
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
|
end
|
||||||
|
|
||||||
default: begin
|
default: begin
|
||||||
|
@ -81,10 +81,9 @@ module uart_core (
|
|||||||
parameter ERX_SYN = 4;
|
parameter ERX_SYN = 4;
|
||||||
|
|
||||||
parameter ETX_IDLE = 0;
|
parameter ETX_IDLE = 0;
|
||||||
parameter ETX_ACK = 1;
|
parameter ETX_START = 1;
|
||||||
parameter ETX_START = 2;
|
parameter ETX_BITS = 2;
|
||||||
parameter ETX_BITS = 3;
|
parameter ETX_STOP = 3;
|
||||||
parameter ETX_STOP = 4;
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -171,19 +170,19 @@ module uart_core (
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
always @(posedge clk) begin : reg_update
|
always @(posedge clk) begin : reg_update
|
||||||
if (!reset_n) begin
|
if (!reset_n) begin
|
||||||
rxd0_reg <= 1'b0;
|
rxd0_reg <= 0;
|
||||||
rxd_reg <= 1'b0;
|
rxd_reg <= 0;
|
||||||
rxd_byte_reg <= 8'h0;
|
rxd_byte_reg <= 8'h0;
|
||||||
rxd_bit_ctr_reg <= 4'h0;
|
rxd_bit_ctr_reg <= 4'h0;
|
||||||
rxd_bitrate_ctr_reg <= 16'h0;
|
rxd_bitrate_ctr_reg <= 16'h0;
|
||||||
rxd_syn_reg <= 0;
|
rxd_syn_reg <= 0;
|
||||||
erx_ctrl_reg <= ERX_IDLE;
|
erx_ctrl_reg <= ERX_IDLE;
|
||||||
|
|
||||||
txd_reg <= 1'b1;
|
txd_reg <= 1;
|
||||||
txd_byte_reg <= 8'h0;
|
txd_byte_reg <= 8'h0;
|
||||||
txd_bit_ctr_reg <= 4'h0;
|
txd_bit_ctr_reg <= 4'h0;
|
||||||
txd_bitrate_ctr_reg <= 16'h0;
|
txd_bitrate_ctr_reg <= 16'h0;
|
||||||
txd_ready_reg <= 1'b1;
|
txd_ready_reg <= 1;
|
||||||
etx_ctrl_reg <= ETX_IDLE;
|
etx_ctrl_reg <= ETX_IDLE;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -246,16 +245,16 @@ module uart_core (
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
always @* begin : rxd_bit_ctr
|
always @* begin : rxd_bit_ctr
|
||||||
rxd_bit_ctr_new = 4'h0;
|
rxd_bit_ctr_new = 4'h0;
|
||||||
rxd_bit_ctr_we = 1'b0;
|
rxd_bit_ctr_we = 0;
|
||||||
|
|
||||||
if (rxd_bit_ctr_rst) begin
|
if (rxd_bit_ctr_rst) begin
|
||||||
rxd_bit_ctr_new = 4'h0;
|
rxd_bit_ctr_new = 4'h0;
|
||||||
rxd_bit_ctr_we = 1'b1;
|
rxd_bit_ctr_we = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if (rxd_bit_ctr_inc) begin
|
else if (rxd_bit_ctr_inc) begin
|
||||||
rxd_bit_ctr_new = rxd_bit_ctr_reg + 1'h1;
|
rxd_bit_ctr_new = rxd_bit_ctr_reg + 1'h1;
|
||||||
rxd_bit_ctr_we = 1'b1;
|
rxd_bit_ctr_we = 1;
|
||||||
end
|
end
|
||||||
end // rxd_bit_ctr
|
end // rxd_bit_ctr
|
||||||
|
|
||||||
@ -267,22 +266,21 @@ module uart_core (
|
|||||||
// serial interface.
|
// serial interface.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
always @* begin : rxd_bitrate_ctr
|
always @* begin : rxd_bitrate_ctr
|
||||||
rxd_bitrate_ctr_new = 16'h0;
|
rxd_bitrate_ctr_new = 16'h1;
|
||||||
rxd_bitrate_ctr_we = 1'h0;
|
rxd_bitrate_ctr_we = 0;
|
||||||
|
|
||||||
if (rxd_bitrate_ctr_rst) begin
|
if (rxd_bitrate_ctr_rst) begin
|
||||||
rxd_bitrate_ctr_new = 16'h0;
|
rxd_bitrate_ctr_new = 16'h1;
|
||||||
rxd_bitrate_ctr_we = 1'b1;
|
rxd_bitrate_ctr_we = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if (rxd_bitrate_ctr_inc) begin
|
else if (rxd_bitrate_ctr_inc) begin
|
||||||
rxd_bitrate_ctr_new = rxd_bitrate_ctr_reg + 1'h1;
|
rxd_bitrate_ctr_new = rxd_bitrate_ctr_reg + 1'h1;
|
||||||
rxd_bitrate_ctr_we = 1'b1;
|
rxd_bitrate_ctr_we = 1;
|
||||||
end
|
end
|
||||||
end // rxd_bitrate_ctr
|
end // rxd_bitrate_ctr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// txd_bit_ctr
|
// txd_bit_ctr
|
||||||
//
|
//
|
||||||
@ -291,16 +289,16 @@ module uart_core (
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
always @* begin : txd_bit_ctr
|
always @* begin : txd_bit_ctr
|
||||||
txd_bit_ctr_new = 4'h0;
|
txd_bit_ctr_new = 4'h0;
|
||||||
txd_bit_ctr_we = 1'h0;
|
txd_bit_ctr_we = 0;
|
||||||
|
|
||||||
if (txd_bit_ctr_rst) begin
|
if (txd_bit_ctr_rst) begin
|
||||||
txd_bit_ctr_new = 4'h0;
|
txd_bit_ctr_new = 4'h0;
|
||||||
txd_bit_ctr_we = 1'h1;
|
txd_bit_ctr_we = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
else if (txd_bit_ctr_inc) begin
|
else if (txd_bit_ctr_inc) begin
|
||||||
txd_bit_ctr_new = txd_bit_ctr_reg + 1'h1;
|
txd_bit_ctr_new = txd_bit_ctr_reg + 1'h1;
|
||||||
txd_bit_ctr_we = 1'b1;
|
txd_bit_ctr_we = 1;
|
||||||
end
|
end
|
||||||
end // txd_bit_ctr
|
end // txd_bit_ctr
|
||||||
|
|
||||||
@ -312,11 +310,11 @@ module uart_core (
|
|||||||
// serial interface.
|
// serial interface.
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
always @* begin : txd_bitrate_ctr
|
always @* begin : txd_bitrate_ctr
|
||||||
txd_bitrate_ctr_new = 16'h0;
|
txd_bitrate_ctr_new = 16'h1;
|
||||||
txd_bitrate_ctr_we = 0;
|
txd_bitrate_ctr_we = 0;
|
||||||
|
|
||||||
if (txd_bitrate_ctr_rst) begin
|
if (txd_bitrate_ctr_rst) begin
|
||||||
txd_bitrate_ctr_new = 16'h0;
|
txd_bitrate_ctr_new = 16'h1;
|
||||||
txd_bitrate_ctr_we = 1;
|
txd_bitrate_ctr_we = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -350,25 +348,32 @@ module uart_core (
|
|||||||
ERX_IDLE: begin
|
ERX_IDLE: begin
|
||||||
if (!rxd_reg) begin
|
if (!rxd_reg) begin
|
||||||
// Possible start bit detected.
|
// Possible start bit detected.
|
||||||
rxd_bitrate_ctr_rst = 1;
|
rxd_bitrate_ctr_inc = 1;
|
||||||
erx_ctrl_new = ERX_START;
|
erx_ctrl_new = ERX_START;
|
||||||
erx_ctrl_we = 1;
|
erx_ctrl_we = 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
ERX_START: begin
|
ERX_START: begin
|
||||||
rxd_bitrate_ctr_inc = 1;
|
|
||||||
if (rxd_reg) begin
|
if (rxd_reg) begin
|
||||||
// Just a glitch.
|
// Just a glitch.
|
||||||
|
rxd_bitrate_ctr_rst = 1;
|
||||||
erx_ctrl_new = ERX_IDLE;
|
erx_ctrl_new = ERX_IDLE;
|
||||||
erx_ctrl_we = 1;
|
erx_ctrl_we = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
else begin
|
else begin
|
||||||
if (rxd_bitrate_ctr_reg == half_bit_rate) begin
|
if (rxd_bitrate_ctr_reg < half_bit_rate) begin
|
||||||
// start bit assumed. We start sampling data.
|
rxd_bitrate_ctr_inc = 1;
|
||||||
rxd_bit_ctr_rst = 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_bitrate_ctr_rst = 1;
|
||||||
|
rxd_bit_ctr_rst = 1;
|
||||||
erx_ctrl_new = ERX_BITS;
|
erx_ctrl_new = ERX_BITS;
|
||||||
erx_ctrl_we = 1;
|
erx_ctrl_we = 1;
|
||||||
end
|
end
|
||||||
@ -382,11 +387,14 @@ module uart_core (
|
|||||||
end
|
end
|
||||||
|
|
||||||
else begin
|
else begin
|
||||||
rxd_byte_we = 1;
|
if (rxd_bit_ctr_reg < data_bits) begin
|
||||||
rxd_bit_ctr_inc = 1;
|
rxd_bitrate_ctr_rst = 1;
|
||||||
rxd_bitrate_ctr_rst = 1;
|
rxd_bit_ctr_inc = 1;
|
||||||
if (rxd_bit_ctr_reg == (data_bits - 1)) begin
|
rxd_byte_we = 1; // We are in the middle of a data bit, make a sample
|
||||||
erx_ctrl_new = ERX_STOP;
|
end
|
||||||
|
|
||||||
|
else begin
|
||||||
|
erx_ctrl_new = ERX_STOP; // We are now in the middle of the stop bit
|
||||||
erx_ctrl_we = 1;
|
erx_ctrl_we = 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -394,12 +402,17 @@ module uart_core (
|
|||||||
|
|
||||||
|
|
||||||
ERX_STOP: begin
|
ERX_STOP: begin
|
||||||
rxd_bitrate_ctr_inc = 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
|
if (rxd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
|
||||||
rxd_syn_new = 1;
|
rxd_bitrate_ctr_inc = 1;
|
||||||
rxd_syn_we = 1;
|
end
|
||||||
erx_ctrl_new = ERX_SYN;
|
|
||||||
erx_ctrl_we = 1;
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -442,39 +455,35 @@ module uart_core (
|
|||||||
|
|
||||||
case (etx_ctrl_reg)
|
case (etx_ctrl_reg)
|
||||||
ETX_IDLE: begin
|
ETX_IDLE: begin
|
||||||
txd_new = 1;
|
txd_new = 1;
|
||||||
txd_we = 1;
|
txd_we = 1;
|
||||||
|
txd_bit_ctr_rst = 1;
|
||||||
if (txd_syn) begin
|
if (txd_syn) begin
|
||||||
|
txd_new = 0;
|
||||||
|
txd_we = 1;
|
||||||
txd_byte_new = txd_data;
|
txd_byte_new = txd_data;
|
||||||
txd_byte_we = 1;
|
txd_byte_we = 1;
|
||||||
txd_ready_new = 0;
|
txd_ready_new = 0;
|
||||||
txd_ready_we = 1;
|
txd_ready_we = 1;
|
||||||
txd_bitrate_ctr_rst = 1;
|
txd_bitrate_ctr_rst = 1;
|
||||||
etx_ctrl_new = ETX_ACK;
|
etx_ctrl_new = ETX_START;
|
||||||
etx_ctrl_we = 1;
|
etx_ctrl_we = 1;
|
||||||
end
|
end
|
||||||
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
|
ETX_START: begin
|
||||||
if (txd_bitrate_ctr_reg == bit_rate) begin
|
if (txd_bitrate_ctr_reg < bit_rate) begin
|
||||||
txd_bit_ctr_rst = 1;
|
txd_bitrate_ctr_inc = 1;
|
||||||
etx_ctrl_new = ETX_BITS;
|
|
||||||
etx_ctrl_we = 1;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else begin
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -486,29 +495,36 @@ module uart_core (
|
|||||||
|
|
||||||
else begin
|
else begin
|
||||||
txd_bitrate_ctr_rst = 1;
|
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_new = 1;
|
||||||
txd_we = 1;
|
txd_we = 1;
|
||||||
etx_ctrl_new = ETX_STOP;
|
etx_ctrl_new = ETX_STOP;
|
||||||
etx_ctrl_we = 1;
|
etx_ctrl_we = 1;
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
ETX_STOP: begin
|
ETX_STOP: begin
|
||||||
txd_bitrate_ctr_inc = 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
|
if (txd_bitrate_ctr_reg < (bit_rate * stop_bits)) begin
|
||||||
txd_ready_new = 1;
|
txd_bitrate_ctr_inc = 1;
|
||||||
txd_ready_we = 1;
|
end
|
||||||
etx_ctrl_new = ETX_IDLE;
|
|
||||||
etx_ctrl_we = 1;
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,7 +48,9 @@ module uart_fifo (
|
|||||||
|
|
||||||
output wire out_syn,
|
output wire out_syn,
|
||||||
output wire [7 : 0] out_data,
|
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_reg;
|
||||||
reg in_ack_new;
|
reg in_ack_new;
|
||||||
|
|
||||||
|
reg fpga_cts_reg;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Wires
|
// Wires
|
||||||
@ -90,6 +93,7 @@ module uart_fifo (
|
|||||||
assign out_syn = ~fifo_empty;
|
assign out_syn = ~fifo_empty;
|
||||||
assign out_data = fifo_mem[out_ptr_reg];
|
assign out_data = fifo_mem[out_ptr_reg];
|
||||||
assign fifo_bytes = byte_ctr_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;
|
out_ptr_reg <= 9'h0;
|
||||||
byte_ctr_reg <= 9'h0;
|
byte_ctr_reg <= 9'h0;
|
||||||
in_ack_reg <= 1'h0;
|
in_ack_reg <= 1'h0;
|
||||||
|
fpga_cts_reg <= 1'h1;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
in_ack_reg <= in_ack_new;
|
in_ack_reg <= in_ack_new;
|
||||||
@ -120,6 +125,14 @@ module uart_fifo (
|
|||||||
if (byte_ctr_we) begin
|
if (byte_ctr_we) begin
|
||||||
byte_ctr_reg <= byte_ctr_new;
|
byte_ctr_reg <= byte_ctr_new;
|
||||||
end
|
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
|
||||||
end // reg_update
|
end // reg_update
|
||||||
|
|
||||||
|
@ -17,8 +17,7 @@ module uds (
|
|||||||
input wire clk,
|
input wire clk,
|
||||||
input wire reset_n,
|
input wire reset_n,
|
||||||
|
|
||||||
input wire system_mode,
|
input wire en,
|
||||||
|
|
||||||
input wire cs,
|
input wire cs,
|
||||||
input wire [ 2 : 0] address,
|
input wire [ 2 : 0] address,
|
||||||
output wire [31 : 0] read_data,
|
output wire [31 : 0] read_data,
|
||||||
@ -89,7 +88,7 @@ module uds (
|
|||||||
if (cs) begin
|
if (cs) begin
|
||||||
tmp_ready = 1'h1;
|
tmp_ready = 1'h1;
|
||||||
|
|
||||||
if (!system_mode) begin
|
if (en) begin
|
||||||
if (uds_rd_reg[address[2 : 0]] == 1'h0) begin
|
if (uds_rd_reg[address[2 : 0]] == 1'h0) begin
|
||||||
uds_rd_we = 1'h1;
|
uds_rd_we = 1'h1;
|
||||||
end
|
end
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
# UART.
|
# UART.
|
||||||
set_io interface_rx 26
|
set_io interface_rx 26
|
||||||
set_io interface_tx 25
|
set_io interface_tx 25
|
||||||
# set_io interface_cts 27
|
set_io interface_ch552_cts 27
|
||||||
# set_io interface_rts 28
|
set_io interface_fpga_cts 28
|
||||||
|
|
||||||
|
|
||||||
# SPI master to flash memory.
|
# SPI master to flash memory.
|
||||||
|
@ -1 +1 @@
|
|||||||
edb39fca7dafb8ea0b89fdeecd960d7656e14ce461e49af97160a8bd6e67d9987e816adad37ba0fcfa63d107c3160988e4c3423ce4a71c39544bc0045888fec1 firmware.bin
|
5e655ba4f25e7f5bc033ce0d9707c9a0b8990258c4b87470c2bcef90d50df79813705c1ef9d22c8670a37aff68f0e5146e5d0c21406916aabf7704579eb7f15c firmware.bin
|
||||||
|
@ -37,15 +37,38 @@ memory access control.
|
|||||||
|
|
||||||
## Communication
|
## Communication
|
||||||
|
|
||||||
The firmware communicates to the host via the
|
The firmware communicates with the client using the
|
||||||
`UART_{RX,TX}_{STATUS,DATA}` registers, using the framing protocol
|
`UART_{RX,TX}_{STATUS,DATA}` registers. On top of that is uses three
|
||||||
described in the [Framing
|
protocols: The USB Mode protocol, the TKey framing protocol, and the
|
||||||
Protocol](https://dev.tillitis.se/protocol/).
|
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
|
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
|
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
|
## 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
|
Firmware loads the application at the start of RAM (`0x4000_0000`). It
|
||||||
uses the special FW\_RAM for its own stack.
|
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
|
When reset is released, the CPU starts executing the firmware. It
|
||||||
begins by clearing all CPU registers, and then sets up a stack for
|
begins by clearing all CPU registers, clears all FW\_RAM, sets up a
|
||||||
itself and then jumps to main().
|
stack for itself there, and then jumps to `main()`.
|
||||||
|
|
||||||
Beginning at `main()` it sets up the "system calls", then fills the
|
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
|
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
|
stack. After this it performs no more function calls and uses no
|
||||||
more automatic variables.
|
more automatic variables.
|
||||||
|
|
||||||
8. Firmware starts the application by first switching to from
|
8. Firmware starts the application by first switching from firmware
|
||||||
firmware mode to application mode by writing to the `SYSTEM_MODE_CTRL`
|
mode to application mode by writing to the `SYSTEM_MODE_CTRL`
|
||||||
register. In this mode the MMIO region is restricted, e.g. some
|
register. In this mode the MMIO region is restricted, e.g. some
|
||||||
registers are removed (`UDS`), and some are switched from
|
registers are removed (`UDS`), and some are switched from
|
||||||
read/write to read-only (see [the memory
|
read/write to read-only (see [the memory
|
||||||
|
9
hw/application_fpga/fw/irqpoc/Makefile
Normal file
9
hw/application_fpga/fw/irqpoc/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Uses ../.clang-format
|
||||||
|
FMTFILES=main.c
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||||
|
clang-format --verbose -i $(FMTFILES)
|
||||||
|
.PHONY: checkfmt
|
||||||
|
checkfmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES)
|
102
hw/application_fpga/fw/irqpoc/custom_ops.S
Normal file
102
hw/application_fpga/fw/irqpoc/custom_ops.S
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
|
||||||
|
#define regnum_q0 0
|
||||||
|
#define regnum_q1 1
|
||||||
|
#define regnum_q2 2
|
||||||
|
#define regnum_q3 3
|
||||||
|
|
||||||
|
#define regnum_x0 0
|
||||||
|
#define regnum_x1 1
|
||||||
|
#define regnum_x2 2
|
||||||
|
#define regnum_x3 3
|
||||||
|
#define regnum_x4 4
|
||||||
|
#define regnum_x5 5
|
||||||
|
#define regnum_x6 6
|
||||||
|
#define regnum_x7 7
|
||||||
|
#define regnum_x8 8
|
||||||
|
#define regnum_x9 9
|
||||||
|
#define regnum_x10 10
|
||||||
|
#define regnum_x11 11
|
||||||
|
#define regnum_x12 12
|
||||||
|
#define regnum_x13 13
|
||||||
|
#define regnum_x14 14
|
||||||
|
#define regnum_x15 15
|
||||||
|
#define regnum_x16 16
|
||||||
|
#define regnum_x17 17
|
||||||
|
#define regnum_x18 18
|
||||||
|
#define regnum_x19 19
|
||||||
|
#define regnum_x20 20
|
||||||
|
#define regnum_x21 21
|
||||||
|
#define regnum_x22 22
|
||||||
|
#define regnum_x23 23
|
||||||
|
#define regnum_x24 24
|
||||||
|
#define regnum_x25 25
|
||||||
|
#define regnum_x26 26
|
||||||
|
#define regnum_x27 27
|
||||||
|
#define regnum_x28 28
|
||||||
|
#define regnum_x29 29
|
||||||
|
#define regnum_x30 30
|
||||||
|
#define regnum_x31 31
|
||||||
|
|
||||||
|
#define regnum_zero 0
|
||||||
|
#define regnum_ra 1
|
||||||
|
#define regnum_sp 2
|
||||||
|
#define regnum_gp 3
|
||||||
|
#define regnum_tp 4
|
||||||
|
#define regnum_t0 5
|
||||||
|
#define regnum_t1 6
|
||||||
|
#define regnum_t2 7
|
||||||
|
#define regnum_s0 8
|
||||||
|
#define regnum_s1 9
|
||||||
|
#define regnum_a0 10
|
||||||
|
#define regnum_a1 11
|
||||||
|
#define regnum_a2 12
|
||||||
|
#define regnum_a3 13
|
||||||
|
#define regnum_a4 14
|
||||||
|
#define regnum_a5 15
|
||||||
|
#define regnum_a6 16
|
||||||
|
#define regnum_a7 17
|
||||||
|
#define regnum_s2 18
|
||||||
|
#define regnum_s3 19
|
||||||
|
#define regnum_s4 20
|
||||||
|
#define regnum_s5 21
|
||||||
|
#define regnum_s6 22
|
||||||
|
#define regnum_s7 23
|
||||||
|
#define regnum_s8 24
|
||||||
|
#define regnum_s9 25
|
||||||
|
#define regnum_s10 26
|
||||||
|
#define regnum_s11 27
|
||||||
|
#define regnum_t3 28
|
||||||
|
#define regnum_t4 29
|
||||||
|
#define regnum_t5 30
|
||||||
|
#define regnum_t6 31
|
||||||
|
|
||||||
|
// x8 is s0 and also fp
|
||||||
|
#define regnum_fp 8
|
||||||
|
|
||||||
|
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||||
|
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||||
|
|
||||||
|
#define picorv32_getq_insn(_rd, _qs) \
|
||||||
|
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_setq_insn(_qd, _rs) \
|
||||||
|
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_retirq_insn() \
|
||||||
|
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_maskirq_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_waitirq_insn(_rd) \
|
||||||
|
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_timer_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
10
hw/application_fpga/fw/irqpoc/main.c
Normal file
10
hw/application_fpga/fw/irqpoc/main.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
40
hw/application_fpga/fw/irqpoc/start.S
Normal file
40
hw/application_fpga/fw/irqpoc/start.S
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Example firmware that demonstrates how to raise interrupts
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "custom_ops.S" // PicoRV32 custom instructions
|
||||||
|
|
||||||
|
.section ".text.init"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
j init
|
||||||
|
|
||||||
|
.=0x10 // IRQ handler at fixed address 0x10
|
||||||
|
irq_handler:
|
||||||
|
// PicoRV32 stores the IRQ bitmask in x4.
|
||||||
|
// If bit 31 is 1: IRQ31 was triggered.
|
||||||
|
|
||||||
|
nop // NOPs are not necessary. Only added to make it easier to find
|
||||||
|
nop // when simulating.
|
||||||
|
nop
|
||||||
|
picorv32_retirq_insn() // Return from interrupt
|
||||||
|
|
||||||
|
.=0x20 // Setting location of init to 0x20. Makes it easier to find when
|
||||||
|
// simulating.
|
||||||
|
init:
|
||||||
|
li t0, 0x7fffffff // IRQ31 mask
|
||||||
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
||||||
|
|
||||||
|
li t0, 0xe1000000 // IRQ31 trigger address
|
||||||
|
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address.
|
||||||
|
// Writing any data triggers an interrupt.
|
||||||
|
loop:
|
||||||
|
j loop
|
||||||
|
|
||||||
|
.align 4 // Padding to please makehex.py which requires even 4-byte file
|
||||||
|
// sizes.
|
||||||
|
|
9
hw/application_fpga/fw/irqpoc_c_example/Makefile
Normal file
9
hw/application_fpga/fw/irqpoc_c_example/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Uses ../.clang-format
|
||||||
|
FMTFILES=main.c
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||||
|
clang-format --verbose -i $(FMTFILES)
|
||||||
|
.PHONY: checkfmt
|
||||||
|
checkfmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES)
|
102
hw/application_fpga/fw/irqpoc_c_example/custom_ops.S
Normal file
102
hw/application_fpga/fw/irqpoc_c_example/custom_ops.S
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
|
||||||
|
#define regnum_q0 0
|
||||||
|
#define regnum_q1 1
|
||||||
|
#define regnum_q2 2
|
||||||
|
#define regnum_q3 3
|
||||||
|
|
||||||
|
#define regnum_x0 0
|
||||||
|
#define regnum_x1 1
|
||||||
|
#define regnum_x2 2
|
||||||
|
#define regnum_x3 3
|
||||||
|
#define regnum_x4 4
|
||||||
|
#define regnum_x5 5
|
||||||
|
#define regnum_x6 6
|
||||||
|
#define regnum_x7 7
|
||||||
|
#define regnum_x8 8
|
||||||
|
#define regnum_x9 9
|
||||||
|
#define regnum_x10 10
|
||||||
|
#define regnum_x11 11
|
||||||
|
#define regnum_x12 12
|
||||||
|
#define regnum_x13 13
|
||||||
|
#define regnum_x14 14
|
||||||
|
#define regnum_x15 15
|
||||||
|
#define regnum_x16 16
|
||||||
|
#define regnum_x17 17
|
||||||
|
#define regnum_x18 18
|
||||||
|
#define regnum_x19 19
|
||||||
|
#define regnum_x20 20
|
||||||
|
#define regnum_x21 21
|
||||||
|
#define regnum_x22 22
|
||||||
|
#define regnum_x23 23
|
||||||
|
#define regnum_x24 24
|
||||||
|
#define regnum_x25 25
|
||||||
|
#define regnum_x26 26
|
||||||
|
#define regnum_x27 27
|
||||||
|
#define regnum_x28 28
|
||||||
|
#define regnum_x29 29
|
||||||
|
#define regnum_x30 30
|
||||||
|
#define regnum_x31 31
|
||||||
|
|
||||||
|
#define regnum_zero 0
|
||||||
|
#define regnum_ra 1
|
||||||
|
#define regnum_sp 2
|
||||||
|
#define regnum_gp 3
|
||||||
|
#define regnum_tp 4
|
||||||
|
#define regnum_t0 5
|
||||||
|
#define regnum_t1 6
|
||||||
|
#define regnum_t2 7
|
||||||
|
#define regnum_s0 8
|
||||||
|
#define regnum_s1 9
|
||||||
|
#define regnum_a0 10
|
||||||
|
#define regnum_a1 11
|
||||||
|
#define regnum_a2 12
|
||||||
|
#define regnum_a3 13
|
||||||
|
#define regnum_a4 14
|
||||||
|
#define regnum_a5 15
|
||||||
|
#define regnum_a6 16
|
||||||
|
#define regnum_a7 17
|
||||||
|
#define regnum_s2 18
|
||||||
|
#define regnum_s3 19
|
||||||
|
#define regnum_s4 20
|
||||||
|
#define regnum_s5 21
|
||||||
|
#define regnum_s6 22
|
||||||
|
#define regnum_s7 23
|
||||||
|
#define regnum_s8 24
|
||||||
|
#define regnum_s9 25
|
||||||
|
#define regnum_s10 26
|
||||||
|
#define regnum_s11 27
|
||||||
|
#define regnum_t3 28
|
||||||
|
#define regnum_t4 29
|
||||||
|
#define regnum_t5 30
|
||||||
|
#define regnum_t6 31
|
||||||
|
|
||||||
|
// x8 is s0 and also fp
|
||||||
|
#define regnum_fp 8
|
||||||
|
|
||||||
|
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||||
|
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||||
|
|
||||||
|
#define picorv32_getq_insn(_rd, _qs) \
|
||||||
|
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_setq_insn(_qd, _rs) \
|
||||||
|
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_retirq_insn() \
|
||||||
|
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_maskirq_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_waitirq_insn(_rd) \
|
||||||
|
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_timer_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
32
hw/application_fpga/fw/irqpoc_c_example/main.c
Normal file
32
hw/application_fpga/fw/irqpoc_c_example/main.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
#include "../tk1/led.h"
|
||||||
|
#include "../tk1/assert.h"
|
||||||
|
|
||||||
|
// Proof-of-concept firmware for handling syscalls.
|
||||||
|
// This is NOT a best-practice example of secure syscall implementation.
|
||||||
|
|
||||||
|
#define SYSCALL_SET_LED 10
|
||||||
|
|
||||||
|
int32_t syscall_handler(uint32_t syscall_nr, uint32_t arg1) {
|
||||||
|
switch (syscall_nr) {
|
||||||
|
case SYSCALL_SET_LED:
|
||||||
|
set_led(arg1);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
assert(1 == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(1 == 2);
|
||||||
|
return -1; // This should never run
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
241
hw/application_fpga/fw/irqpoc_c_example/start.S
Normal file
241
hw/application_fpga/fw/irqpoc_c_example/start.S
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This firmware copies an app from ROM to app RAM.
|
||||||
|
// The app continuosly calls the SET_LED syscall in firmware (main.c).
|
||||||
|
//
|
||||||
|
#include "../tk1_mem.h"
|
||||||
|
#include "custom_ops.S" // PicoRV32 custom instructions
|
||||||
|
|
||||||
|
#define illegal_insn() .word 0
|
||||||
|
|
||||||
|
#define FW_SP_STORAGE (TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE - 4)
|
||||||
|
#define FW_STACK_TOP (TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE - 2*4)
|
||||||
|
|
||||||
|
#define LED_RED (1 << TK1_MMIO_TK1_LED_R_BIT)
|
||||||
|
#define LED_GREEN (1 << TK1_MMIO_TK1_LED_G_BIT)
|
||||||
|
#define LED_BLUE (1 << TK1_MMIO_TK1_LED_B_BIT)
|
||||||
|
|
||||||
|
.section ".text.init"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
j init
|
||||||
|
|
||||||
|
//
|
||||||
|
// IRQ handler
|
||||||
|
//
|
||||||
|
.=0x10 // IRQ handler at fixed address 0x10
|
||||||
|
irq_handler:
|
||||||
|
// PicoRV32 stores the IRQ bitmask in x4.
|
||||||
|
// If bit 31 is 1: IRQ31 was triggered.
|
||||||
|
li t4, (1 << 31)
|
||||||
|
beq x4, t4, irq_source_ok
|
||||||
|
unexpected_irq_source:
|
||||||
|
illegal_insn()
|
||||||
|
j unexpected_irq_source
|
||||||
|
irq_source_ok:
|
||||||
|
|
||||||
|
// Save app stack pointer. App is responsible for saving the rest of
|
||||||
|
// the registers.
|
||||||
|
la t0, FW_SP_STORAGE
|
||||||
|
sw sp, 0(t0)
|
||||||
|
|
||||||
|
// Setup firmware stack pointer
|
||||||
|
la sp, FW_STACK_TOP
|
||||||
|
|
||||||
|
// Run syscall handler
|
||||||
|
call syscall_handler
|
||||||
|
|
||||||
|
// Restore app stack pointer
|
||||||
|
la t0, FW_SP_STORAGE
|
||||||
|
lw sp, 0(t0)
|
||||||
|
|
||||||
|
// Verify that interrupt return address (x3) is in app RAM
|
||||||
|
li t0, TK1_RAM_BASE // 0x40000000
|
||||||
|
blt x3, t0, x3_invalid
|
||||||
|
li t0, TK1_RAM_BASE + TK1_RAM_SIZE // 0x40020000
|
||||||
|
bge x3, t0, x3_invalid
|
||||||
|
j x3_valid
|
||||||
|
x3_invalid:
|
||||||
|
illegal_insn()
|
||||||
|
j x3_invalid
|
||||||
|
x3_valid:
|
||||||
|
|
||||||
|
// Remove data left over from the syscall handling
|
||||||
|
mv x0, zero
|
||||||
|
mv x1, zero
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler
|
||||||
|
// x3 (interrupt return address) assumed preserved
|
||||||
|
mv x4, zero
|
||||||
|
mv x5, zero
|
||||||
|
mv x6, zero
|
||||||
|
mv x7, zero
|
||||||
|
mv x8, zero
|
||||||
|
mv x9, zero
|
||||||
|
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||||
|
mv x11, zero
|
||||||
|
mv x12, zero
|
||||||
|
mv x13, zero
|
||||||
|
mv x14, zero
|
||||||
|
mv x15, zero
|
||||||
|
mv x16, zero
|
||||||
|
mv x17, zero
|
||||||
|
mv x18, zero
|
||||||
|
mv x19, zero
|
||||||
|
mv x20, zero
|
||||||
|
mv x21, zero
|
||||||
|
mv x22, zero
|
||||||
|
mv x23, zero
|
||||||
|
mv x24, zero
|
||||||
|
mv x25, zero
|
||||||
|
mv x26, zero
|
||||||
|
mv x27, zero
|
||||||
|
mv x28, zero
|
||||||
|
mv x29, zero
|
||||||
|
mv x30, zero
|
||||||
|
mv x31, zero
|
||||||
|
|
||||||
|
picorv32_retirq_insn() // Return from interrupt
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init
|
||||||
|
//
|
||||||
|
.=0x100
|
||||||
|
init:
|
||||||
|
li t0, TK1_MMIO_TK1_LED
|
||||||
|
li t1, LED_RED
|
||||||
|
sw t1, 0(t0)
|
||||||
|
|
||||||
|
// Enable IRQs
|
||||||
|
li t0, 0x7fffffff // IRQ31 mask
|
||||||
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
||||||
|
|
||||||
|
// Copy app to App RAM
|
||||||
|
la t0, app_start
|
||||||
|
la t1, app_end
|
||||||
|
li t2, 0x40000000 // 0x40000000: App RAM
|
||||||
|
copy_app:
|
||||||
|
lw t3, 0(t0)
|
||||||
|
sw t3, 0(t2)
|
||||||
|
addi t0, t0, 4
|
||||||
|
addi t2, t2, 4
|
||||||
|
bleu t0, t1, copy_app
|
||||||
|
|
||||||
|
// Jump to app
|
||||||
|
li t2, 0x40000000 // 0x40000000: App RAM
|
||||||
|
jalr zero, 0(t2)
|
||||||
|
|
||||||
|
//
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
#define SYSCALL_SET_LED 10
|
||||||
|
|
||||||
|
.=0x1000
|
||||||
|
app_start:
|
||||||
|
// Set stack pointer to end of app RAM
|
||||||
|
li sp, 0x4001fffc
|
||||||
|
|
||||||
|
app_loop:
|
||||||
|
li a0, SYSCALL_SET_LED
|
||||||
|
li a1, LED_GREEN
|
||||||
|
call app_syscall
|
||||||
|
call app_delay
|
||||||
|
|
||||||
|
li a0, SYSCALL_SET_LED
|
||||||
|
li a1, LED_BLUE
|
||||||
|
call app_syscall
|
||||||
|
call app_delay
|
||||||
|
|
||||||
|
j app_loop
|
||||||
|
|
||||||
|
app_syscall:
|
||||||
|
// Save registers to stack
|
||||||
|
addi sp, sp, -32*4
|
||||||
|
sw x0, 0*4(sp)
|
||||||
|
sw x1, 1*4(sp)
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||||
|
sw x3, 3*4(sp)
|
||||||
|
sw x4, 4*4(sp)
|
||||||
|
sw x5, 5*4(sp)
|
||||||
|
sw x6, 6*4(sp)
|
||||||
|
sw x7, 7*4(sp)
|
||||||
|
sw x8, 8*4(sp)
|
||||||
|
sw x9, 9*4(sp)
|
||||||
|
// x10 (a0) will contain syscall return value. And should not be saved.
|
||||||
|
sw x11, 11*4(sp)
|
||||||
|
sw x12, 12*4(sp)
|
||||||
|
sw x13, 13*4(sp)
|
||||||
|
sw x14, 14*4(sp)
|
||||||
|
sw x15, 15*4(sp)
|
||||||
|
sw x16, 16*4(sp)
|
||||||
|
sw x17, 17*4(sp)
|
||||||
|
sw x18, 18*4(sp)
|
||||||
|
sw x19, 19*4(sp)
|
||||||
|
sw x20, 20*4(sp)
|
||||||
|
sw x21, 21*4(sp)
|
||||||
|
sw x22, 22*4(sp)
|
||||||
|
sw x23, 23*4(sp)
|
||||||
|
sw x24, 24*4(sp)
|
||||||
|
sw x25, 25*4(sp)
|
||||||
|
sw x26, 26*4(sp)
|
||||||
|
sw x27, 27*4(sp)
|
||||||
|
sw x28, 28*4(sp)
|
||||||
|
sw x29, 29*4(sp)
|
||||||
|
sw x30, 30*4(sp)
|
||||||
|
sw x31, 31*4(sp)
|
||||||
|
|
||||||
|
// Trigger syscall interrupt
|
||||||
|
li t0, (1 << 31)
|
||||||
|
and t0, a0, t0
|
||||||
|
li t1, 0xe1000000 // Syscall interrupt trigger address
|
||||||
|
sw zero, 0(t1) // Trigger interrupt
|
||||||
|
|
||||||
|
// Restore registers from stack
|
||||||
|
lw x0, 0*4(sp)
|
||||||
|
lw x1, 1*4(sp)
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||||
|
lw x3, 3*4(sp)
|
||||||
|
lw x4, 4*4(sp)
|
||||||
|
lw x5, 5*4(sp)
|
||||||
|
lw x6, 6*4(sp)
|
||||||
|
lw x7, 7*4(sp)
|
||||||
|
lw x8, 8*4(sp)
|
||||||
|
lw x9, 9*4(sp)
|
||||||
|
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||||
|
lw x11, 11*4(sp)
|
||||||
|
lw x12, 12*4(sp)
|
||||||
|
lw x13, 13*4(sp)
|
||||||
|
lw x14, 14*4(sp)
|
||||||
|
lw x15, 15*4(sp)
|
||||||
|
lw x16, 16*4(sp)
|
||||||
|
lw x17, 17*4(sp)
|
||||||
|
lw x18, 18*4(sp)
|
||||||
|
lw x19, 19*4(sp)
|
||||||
|
lw x20, 20*4(sp)
|
||||||
|
lw x21, 21*4(sp)
|
||||||
|
lw x22, 22*4(sp)
|
||||||
|
lw x23, 23*4(sp)
|
||||||
|
lw x24, 24*4(sp)
|
||||||
|
lw x25, 25*4(sp)
|
||||||
|
lw x26, 26*4(sp)
|
||||||
|
lw x27, 27*4(sp)
|
||||||
|
lw x28, 28*4(sp)
|
||||||
|
lw x29, 29*4(sp)
|
||||||
|
lw x30, 30*4(sp)
|
||||||
|
lw x31, 31*4(sp)
|
||||||
|
addi sp, sp, 32*4
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
app_delay:
|
||||||
|
li t5, 0x100000
|
||||||
|
app_delay_dec:
|
||||||
|
addi t5, t5, -1
|
||||||
|
bne t5, zero, app_delay_dec
|
||||||
|
ret
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
app_end:
|
||||||
|
|
9
hw/application_fpga/fw/irqpoc_led_toggle/Makefile
Normal file
9
hw/application_fpga/fw/irqpoc_led_toggle/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Uses ../.clang-format
|
||||||
|
FMTFILES=main.c
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||||
|
clang-format --verbose -i $(FMTFILES)
|
||||||
|
.PHONY: checkfmt
|
||||||
|
checkfmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES)
|
102
hw/application_fpga/fw/irqpoc_led_toggle/custom_ops.S
Normal file
102
hw/application_fpga/fw/irqpoc_led_toggle/custom_ops.S
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
|
||||||
|
#define regnum_q0 0
|
||||||
|
#define regnum_q1 1
|
||||||
|
#define regnum_q2 2
|
||||||
|
#define regnum_q3 3
|
||||||
|
|
||||||
|
#define regnum_x0 0
|
||||||
|
#define regnum_x1 1
|
||||||
|
#define regnum_x2 2
|
||||||
|
#define regnum_x3 3
|
||||||
|
#define regnum_x4 4
|
||||||
|
#define regnum_x5 5
|
||||||
|
#define regnum_x6 6
|
||||||
|
#define regnum_x7 7
|
||||||
|
#define regnum_x8 8
|
||||||
|
#define regnum_x9 9
|
||||||
|
#define regnum_x10 10
|
||||||
|
#define regnum_x11 11
|
||||||
|
#define regnum_x12 12
|
||||||
|
#define regnum_x13 13
|
||||||
|
#define regnum_x14 14
|
||||||
|
#define regnum_x15 15
|
||||||
|
#define regnum_x16 16
|
||||||
|
#define regnum_x17 17
|
||||||
|
#define regnum_x18 18
|
||||||
|
#define regnum_x19 19
|
||||||
|
#define regnum_x20 20
|
||||||
|
#define regnum_x21 21
|
||||||
|
#define regnum_x22 22
|
||||||
|
#define regnum_x23 23
|
||||||
|
#define regnum_x24 24
|
||||||
|
#define regnum_x25 25
|
||||||
|
#define regnum_x26 26
|
||||||
|
#define regnum_x27 27
|
||||||
|
#define regnum_x28 28
|
||||||
|
#define regnum_x29 29
|
||||||
|
#define regnum_x30 30
|
||||||
|
#define regnum_x31 31
|
||||||
|
|
||||||
|
#define regnum_zero 0
|
||||||
|
#define regnum_ra 1
|
||||||
|
#define regnum_sp 2
|
||||||
|
#define regnum_gp 3
|
||||||
|
#define regnum_tp 4
|
||||||
|
#define regnum_t0 5
|
||||||
|
#define regnum_t1 6
|
||||||
|
#define regnum_t2 7
|
||||||
|
#define regnum_s0 8
|
||||||
|
#define regnum_s1 9
|
||||||
|
#define regnum_a0 10
|
||||||
|
#define regnum_a1 11
|
||||||
|
#define regnum_a2 12
|
||||||
|
#define regnum_a3 13
|
||||||
|
#define regnum_a4 14
|
||||||
|
#define regnum_a5 15
|
||||||
|
#define regnum_a6 16
|
||||||
|
#define regnum_a7 17
|
||||||
|
#define regnum_s2 18
|
||||||
|
#define regnum_s3 19
|
||||||
|
#define regnum_s4 20
|
||||||
|
#define regnum_s5 21
|
||||||
|
#define regnum_s6 22
|
||||||
|
#define regnum_s7 23
|
||||||
|
#define regnum_s8 24
|
||||||
|
#define regnum_s9 25
|
||||||
|
#define regnum_s10 26
|
||||||
|
#define regnum_s11 27
|
||||||
|
#define regnum_t3 28
|
||||||
|
#define regnum_t4 29
|
||||||
|
#define regnum_t5 30
|
||||||
|
#define regnum_t6 31
|
||||||
|
|
||||||
|
// x8 is s0 and also fp
|
||||||
|
#define regnum_fp 8
|
||||||
|
|
||||||
|
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||||
|
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||||
|
|
||||||
|
#define picorv32_getq_insn(_rd, _qs) \
|
||||||
|
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_setq_insn(_qd, _rs) \
|
||||||
|
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_retirq_insn() \
|
||||||
|
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_maskirq_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_waitirq_insn(_rd) \
|
||||||
|
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_timer_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
10
hw/application_fpga/fw/irqpoc_led_toggle/main.c
Normal file
10
hw/application_fpga/fw/irqpoc_led_toggle/main.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
82
hw/application_fpga/fw/irqpoc_led_toggle/start.S
Normal file
82
hw/application_fpga/fw/irqpoc_led_toggle/start.S
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Example firmware demonstrating setting the LED from the interrupt handler.
|
||||||
|
// The LED color will alterate between blue and green.
|
||||||
|
// The color will be RED if an interrupt is triggered by an unexpected source.
|
||||||
|
//
|
||||||
|
// | Color | Execution context |
|
||||||
|
// |-------|-------------------|
|
||||||
|
// | Blue | Firmware loop |
|
||||||
|
// | Green | IRQ31 |
|
||||||
|
// | Red | Unexpected IRQ |
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "custom_ops.S" // PicoRV32 custom instructions
|
||||||
|
|
||||||
|
.section ".text.init"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
j init
|
||||||
|
|
||||||
|
|
||||||
|
.=0x10 // IRQ handler at fixed address 0x10
|
||||||
|
irq_handler:
|
||||||
|
// PicoRV32 stores the IRQ bitmask in x4.
|
||||||
|
// If bit 31 is 1: IRQ31 was triggered.
|
||||||
|
li t4, (1 << 31)
|
||||||
|
bne x4, t4, unexpected_irq
|
||||||
|
call led_green
|
||||||
|
call delay
|
||||||
|
j irq_source_check_done
|
||||||
|
unexpected_irq:
|
||||||
|
call led_red
|
||||||
|
call delay
|
||||||
|
irq_source_check_done:
|
||||||
|
picorv32_retirq_insn() // Return from interrupt
|
||||||
|
|
||||||
|
|
||||||
|
init:
|
||||||
|
li t0, 0x7fffffff // IRQ31 mask
|
||||||
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
||||||
|
|
||||||
|
irq_trigger_loop:
|
||||||
|
call led_blue
|
||||||
|
call delay
|
||||||
|
|
||||||
|
li t0, 0xe1000000 // IRQ31 trigger address
|
||||||
|
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address.
|
||||||
|
// Writing any data triggers an interrupt.
|
||||||
|
|
||||||
|
j irq_trigger_loop
|
||||||
|
|
||||||
|
led_red:
|
||||||
|
li t2, 0xff000024
|
||||||
|
li t3, (1 << 2)
|
||||||
|
sw t3, 0(t2)
|
||||||
|
ret
|
||||||
|
|
||||||
|
led_green:
|
||||||
|
li t2, 0xff000024
|
||||||
|
li t3, (1 << 1)
|
||||||
|
sw t3, 0(t2)
|
||||||
|
ret
|
||||||
|
|
||||||
|
led_blue:
|
||||||
|
li t2, 0xff000024
|
||||||
|
li t3, (1 << 0)
|
||||||
|
sw t3, 0(t2)
|
||||||
|
ret
|
||||||
|
|
||||||
|
delay:
|
||||||
|
li t5, 0x100000
|
||||||
|
delay_dec:
|
||||||
|
addi t5, t5, -1
|
||||||
|
bne t5, zero, delay_dec
|
||||||
|
ret
|
||||||
|
|
||||||
|
.align 4 // Padding to please makehex.py which requires even 4-byte file
|
||||||
|
// sizes.
|
||||||
|
|
9
hw/application_fpga/fw/irqpoc_with_app/Makefile
Normal file
9
hw/application_fpga/fw/irqpoc_with_app/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Uses ../.clang-format
|
||||||
|
FMTFILES=main.c
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||||
|
clang-format --verbose -i $(FMTFILES)
|
||||||
|
.PHONY: checkfmt
|
||||||
|
checkfmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES)
|
102
hw/application_fpga/fw/irqpoc_with_app/custom_ops.S
Normal file
102
hw/application_fpga/fw/irqpoc_with_app/custom_ops.S
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
|
||||||
|
#define regnum_q0 0
|
||||||
|
#define regnum_q1 1
|
||||||
|
#define regnum_q2 2
|
||||||
|
#define regnum_q3 3
|
||||||
|
|
||||||
|
#define regnum_x0 0
|
||||||
|
#define regnum_x1 1
|
||||||
|
#define regnum_x2 2
|
||||||
|
#define regnum_x3 3
|
||||||
|
#define regnum_x4 4
|
||||||
|
#define regnum_x5 5
|
||||||
|
#define regnum_x6 6
|
||||||
|
#define regnum_x7 7
|
||||||
|
#define regnum_x8 8
|
||||||
|
#define regnum_x9 9
|
||||||
|
#define regnum_x10 10
|
||||||
|
#define regnum_x11 11
|
||||||
|
#define regnum_x12 12
|
||||||
|
#define regnum_x13 13
|
||||||
|
#define regnum_x14 14
|
||||||
|
#define regnum_x15 15
|
||||||
|
#define regnum_x16 16
|
||||||
|
#define regnum_x17 17
|
||||||
|
#define regnum_x18 18
|
||||||
|
#define regnum_x19 19
|
||||||
|
#define regnum_x20 20
|
||||||
|
#define regnum_x21 21
|
||||||
|
#define regnum_x22 22
|
||||||
|
#define regnum_x23 23
|
||||||
|
#define regnum_x24 24
|
||||||
|
#define regnum_x25 25
|
||||||
|
#define regnum_x26 26
|
||||||
|
#define regnum_x27 27
|
||||||
|
#define regnum_x28 28
|
||||||
|
#define regnum_x29 29
|
||||||
|
#define regnum_x30 30
|
||||||
|
#define regnum_x31 31
|
||||||
|
|
||||||
|
#define regnum_zero 0
|
||||||
|
#define regnum_ra 1
|
||||||
|
#define regnum_sp 2
|
||||||
|
#define regnum_gp 3
|
||||||
|
#define regnum_tp 4
|
||||||
|
#define regnum_t0 5
|
||||||
|
#define regnum_t1 6
|
||||||
|
#define regnum_t2 7
|
||||||
|
#define regnum_s0 8
|
||||||
|
#define regnum_s1 9
|
||||||
|
#define regnum_a0 10
|
||||||
|
#define regnum_a1 11
|
||||||
|
#define regnum_a2 12
|
||||||
|
#define regnum_a3 13
|
||||||
|
#define regnum_a4 14
|
||||||
|
#define regnum_a5 15
|
||||||
|
#define regnum_a6 16
|
||||||
|
#define regnum_a7 17
|
||||||
|
#define regnum_s2 18
|
||||||
|
#define regnum_s3 19
|
||||||
|
#define regnum_s4 20
|
||||||
|
#define regnum_s5 21
|
||||||
|
#define regnum_s6 22
|
||||||
|
#define regnum_s7 23
|
||||||
|
#define regnum_s8 24
|
||||||
|
#define regnum_s9 25
|
||||||
|
#define regnum_s10 26
|
||||||
|
#define regnum_s11 27
|
||||||
|
#define regnum_t3 28
|
||||||
|
#define regnum_t4 29
|
||||||
|
#define regnum_t5 30
|
||||||
|
#define regnum_t6 31
|
||||||
|
|
||||||
|
// x8 is s0 and also fp
|
||||||
|
#define regnum_fp 8
|
||||||
|
|
||||||
|
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||||
|
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||||
|
|
||||||
|
#define picorv32_getq_insn(_rd, _qs) \
|
||||||
|
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_setq_insn(_qd, _rs) \
|
||||||
|
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_retirq_insn() \
|
||||||
|
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_maskirq_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_waitirq_insn(_rd) \
|
||||||
|
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_timer_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
10
hw/application_fpga/fw/irqpoc_with_app/main.c
Normal file
10
hw/application_fpga/fw/irqpoc_with_app/main.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
110
hw/application_fpga/fw/irqpoc_with_app/start.S
Normal file
110
hw/application_fpga/fw/irqpoc_with_app/start.S
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This firmware copies an app from ROM to app RAM. The app triggers IRQ_SYSCALL
|
||||||
|
// Checks are done to make sure that firmware RAM can/cannot be read depending
|
||||||
|
// on wether we're executing from firmware, syscall or app.
|
||||||
|
// Finally the app tries to jump firmware. This should result in a trap since
|
||||||
|
// the app is executing in app mode.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "custom_ops.S" // PicoRV32 custom instructions
|
||||||
|
|
||||||
|
#define illegal_insn() .word 0
|
||||||
|
|
||||||
|
.section ".text.init"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
j init
|
||||||
|
|
||||||
|
//
|
||||||
|
// IRQ handler
|
||||||
|
//
|
||||||
|
.=0x10 // IRQ handler at fixed address 0x10
|
||||||
|
irq_handler:
|
||||||
|
// PicoRV32 stores the IRQ bitmask in x4.
|
||||||
|
// If bit 31 is 1: IRQ31 was triggered.
|
||||||
|
li t4, (1 << 31)
|
||||||
|
bne x4, t4, unexpected_irq
|
||||||
|
// Firmware RAM should be readable from IRQ_SYSCALL
|
||||||
|
call check_can_read_test_val_from_fw_ram
|
||||||
|
j irq_source_check_done
|
||||||
|
unexpected_irq:
|
||||||
|
illegal_insn()
|
||||||
|
irq_source_check_done:
|
||||||
|
picorv32_retirq_insn() // Return from interrupt
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init
|
||||||
|
//
|
||||||
|
.=0x100
|
||||||
|
init:
|
||||||
|
// Save test value in firmware RAM
|
||||||
|
li t0, 0xd0000000
|
||||||
|
li t1, 0x5555aaaa
|
||||||
|
sw t1, 0(t0)
|
||||||
|
|
||||||
|
// Firmware RAM should be readable from firmware mode
|
||||||
|
call check_can_read_test_val_from_fw_ram
|
||||||
|
|
||||||
|
// Enable IRQs
|
||||||
|
li t0, 0x7fffffff // IRQ31
|
||||||
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
||||||
|
|
||||||
|
// Copy app to App RAM
|
||||||
|
la t0, app_start
|
||||||
|
la t1, app_end
|
||||||
|
li t2, 0x40000000 // 0x40000000: App RAM
|
||||||
|
copy_app:
|
||||||
|
lw t3, 0(t0)
|
||||||
|
sw t3, 0(t2)
|
||||||
|
addi t0, t0, 4
|
||||||
|
addi t2, t2, 4
|
||||||
|
bleu t0, t1, copy_app
|
||||||
|
|
||||||
|
// Jump to app
|
||||||
|
li t2, 0x40000000 // 0x40000000: App RAM
|
||||||
|
jalr zero, 0(t2)
|
||||||
|
|
||||||
|
//
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
.align 4
|
||||||
|
app_start:
|
||||||
|
// Firmware RAM should not be readable from app mode
|
||||||
|
call check_cannot_read_test_val_from_fw_ram
|
||||||
|
|
||||||
|
// Raise IRQ_SYSCALL
|
||||||
|
li t0, 0xe1000000 // IRQ_SYSCALL (IRQ31) trigger address
|
||||||
|
sw zero, 0(t0) // Raise IRQ by writing to interrupt trigger address.
|
||||||
|
// Writing any data triggers an interrupt.
|
||||||
|
|
||||||
|
jalr zero, 0(zero) // Jumping to firmware. Expecting trap
|
||||||
|
app_loop:
|
||||||
|
j app_loop
|
||||||
|
|
||||||
|
|
||||||
|
check_cannot_read_test_val_from_fw_ram:
|
||||||
|
li t0, 0xd0000000
|
||||||
|
lw t1, 0(t0)
|
||||||
|
li t2, 0
|
||||||
|
bne t1, t2, cannot_read_test_val_from_fw_ram_fail
|
||||||
|
ret
|
||||||
|
cannot_read_test_val_from_fw_ram_fail:
|
||||||
|
illegal_insn()
|
||||||
|
|
||||||
|
check_can_read_test_val_from_fw_ram:
|
||||||
|
// Check that saved test value can not be read while in app mode
|
||||||
|
li t0, 0xd0000000
|
||||||
|
lw t1, 0(t0)
|
||||||
|
li t2, 0x5555aaaa
|
||||||
|
bne t1, t2, can_read_test_val_from_fw_ram_fail
|
||||||
|
ret
|
||||||
|
can_read_test_val_from_fw_ram_fail:
|
||||||
|
illegal_insn()
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
app_end:
|
||||||
|
|
71
hw/application_fpga/fw/testapp/Makefile
Normal file
71
hw/application_fpga/fw/testapp/Makefile
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
P := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
|
OBJCOPY ?= llvm-objcopy
|
||||||
|
CC = clang
|
||||||
|
CFLAGS = \
|
||||||
|
-target riscv32-unknown-none-elf \
|
||||||
|
-march=rv32iczmmul \
|
||||||
|
-mabi=ilp32 \
|
||||||
|
-mcmodel=medany \
|
||||||
|
-static \
|
||||||
|
-std=gnu99 \
|
||||||
|
-O2 \
|
||||||
|
-ffast-math \
|
||||||
|
-fno-common \
|
||||||
|
-fno-builtin-printf \
|
||||||
|
-fno-builtin-putchar \
|
||||||
|
-fno-builtin-memcpy \
|
||||||
|
-nostdlib \
|
||||||
|
-mno-relax \
|
||||||
|
-Wall \
|
||||||
|
-Wpedantic \
|
||||||
|
-Wno-language-extension-token \
|
||||||
|
-Werror \
|
||||||
|
-flto \
|
||||||
|
-g
|
||||||
|
|
||||||
|
AS = clang
|
||||||
|
|
||||||
|
ASFLAGS = \
|
||||||
|
-target riscv32-unknown-none-elf \
|
||||||
|
-march=rv32iczmmul \
|
||||||
|
-mabi=ilp32 \
|
||||||
|
-mno-relax
|
||||||
|
|
||||||
|
LDFLAGS=-T $(P)/app.lds
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: testapp.bin
|
||||||
|
|
||||||
|
# Turn elf into bin for device
|
||||||
|
%.bin: %.elf
|
||||||
|
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $^ $@
|
||||||
|
chmod a-x $@
|
||||||
|
|
||||||
|
TESTAPP_FMTFILES = \
|
||||||
|
$(P)/main.c \
|
||||||
|
$(P)/syscall.h
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
testapp.elf: $(TESTAPP_OBJS)
|
||||||
|
$(CC) $(CFLAGS) $(TESTAPP_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 $(TESTAPP_FMTFILES)
|
||||||
|
clang-format --verbose -i $(TESTAPP_FMTFILES)
|
||||||
|
|
||||||
|
.PHONY: checkfmt
|
||||||
|
checkfmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 --Werror $(TESTAPP_FMTFILES)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f testapp.bin testapp.elf $(TESTAPP_OBJS)
|
64
hw/application_fpga/fw/testapp/app.lds
Normal file
64
hw/application_fpga/fw/testapp/app.lds
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text.init :
|
||||||
|
{
|
||||||
|
*(.text.init)
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.text) /* .text sections (code) */
|
||||||
|
*(.text*) /* .text* sections (code) */
|
||||||
|
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||||
|
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||||
|
*(.srodata) /* .rodata sections (constants, strings, etc.) */
|
||||||
|
*(.srodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||||
|
. = ALIGN(4);
|
||||||
|
_etext = .;
|
||||||
|
_sidata = _etext;
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
.data : AT (_etext)
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sdata = .;
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.data) /* .data sections */
|
||||||
|
*(.data*) /* .data* sections */
|
||||||
|
*(.sdata) /* .sdata sections */
|
||||||
|
*(.sdata*) /* .sdata* sections */
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = .;
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
/* Uninitialized data section */
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sbss = .;
|
||||||
|
*(.bss)
|
||||||
|
*(.bss*)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss*)
|
||||||
|
*(COMMON)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = .;
|
||||||
|
} >RAM
|
||||||
|
|
||||||
|
/* libcrt0/crt0.S inits stack to start just below end of RAM */
|
||||||
|
}
|
53
hw/application_fpga/fw/testapp/crt0.S
Normal file
53
hw/application_fpga/fw/testapp/crt0.S
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2022 Tillitis AB <tillitis.se>
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
.section ".text.init"
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
li x1, 0
|
||||||
|
li x2, 0
|
||||||
|
li x3, 0
|
||||||
|
li x4, 0
|
||||||
|
li x5, 0
|
||||||
|
li x6, 0
|
||||||
|
li x7, 0
|
||||||
|
li x8, 0
|
||||||
|
li x9, 0
|
||||||
|
li x10,0
|
||||||
|
li x11,0
|
||||||
|
li x12,0
|
||||||
|
li x13,0
|
||||||
|
li x14,0
|
||||||
|
li x15,0
|
||||||
|
li x16,0
|
||||||
|
li x17,0
|
||||||
|
li x18,0
|
||||||
|
li x19,0
|
||||||
|
li x20,0
|
||||||
|
li x21,0
|
||||||
|
li x22,0
|
||||||
|
li x23,0
|
||||||
|
li x24,0
|
||||||
|
li x25,0
|
||||||
|
li x26,0
|
||||||
|
li x27,0
|
||||||
|
li x28,0
|
||||||
|
li x29,0
|
||||||
|
li x30,0
|
||||||
|
li x31,0
|
||||||
|
|
||||||
|
/* init stack below 0x40020000 (TK1_RAM_BASE+TK1_RAM_SIZE) */
|
||||||
|
li sp, 0x4001fff0
|
||||||
|
|
||||||
|
/* zero-init bss section */
|
||||||
|
la a0, _sbss
|
||||||
|
la a1, _ebss
|
||||||
|
bge a0, a1, end_init_bss
|
||||||
|
|
||||||
|
loop_init_bss:
|
||||||
|
sw zero, 0(a0)
|
||||||
|
addi a0, a0, 4
|
||||||
|
blt a0, a1, loop_init_bss
|
||||||
|
|
||||||
|
end_init_bss:
|
||||||
|
call main
|
280
hw/application_fpga/fw/testapp/main.c
Normal file
280
hw/application_fpga/fw/testapp/main.c
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../tk1/led.h"
|
||||||
|
#include "../tk1/lib.h"
|
||||||
|
#include "../tk1/proto.h"
|
||||||
|
#include "../tk1/syscall_nrs.h"
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
#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;
|
||||||
|
volatile uint32_t *uds = (volatile uint32_t *)TK1_MMIO_UDS_FIRST;
|
||||||
|
volatile uint32_t *cdi = (volatile uint32_t *)TK1_MMIO_TK1_CDI_FIRST;
|
||||||
|
volatile uint32_t *udi = (volatile uint32_t *)TK1_MMIO_TK1_UDI_FIRST;
|
||||||
|
volatile uint32_t *system_mode_ctrl = (volatile uint32_t *)TK1_MMIO_TK1_SYSTEM_MODE_CTRL;
|
||||||
|
volatile uint8_t *fw_ram = (volatile uint8_t *)TK1_MMIO_FW_RAM_BASE;
|
||||||
|
volatile uint32_t *timer = (volatile uint32_t *)TK1_MMIO_TIMER_TIMER;
|
||||||
|
volatile uint32_t *timer_prescaler = (volatile uint32_t *)TK1_MMIO_TIMER_PRESCALER;
|
||||||
|
volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER_STATUS;
|
||||||
|
volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
|
||||||
|
volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS;
|
||||||
|
volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#define UDS_WORDS 8
|
||||||
|
#define UDI_WORDS 2
|
||||||
|
#define CDI_WORDS 8
|
||||||
|
|
||||||
|
static void write_with_header(const uint8_t *buf, size_t nbytes, enum mode mode)
|
||||||
|
{
|
||||||
|
// 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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(const uint8_t *buf, size_t nbytes)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
uint8_t buf[2];
|
||||||
|
|
||||||
|
hex(buf, c);
|
||||||
|
write(buf, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void puthexn(uint8_t *p, int n)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
puthex(p[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverseword(uint32_t *wordp)
|
||||||
|
{
|
||||||
|
*wordp = ((*wordp & 0xff000000) >> 24) | ((*wordp & 0x00ff0000) >> 8) |
|
||||||
|
((*wordp & 0x0000ff00) << 8) | ((*wordp & 0x000000ff) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t wait_timer_tick(uint32_t last_timer)
|
||||||
|
{
|
||||||
|
uint32_t newtimer;
|
||||||
|
for (;;) {
|
||||||
|
newtimer = *timer;
|
||||||
|
if (newtimer != last_timer) {
|
||||||
|
return newtimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void failmsg(char *s)
|
||||||
|
{
|
||||||
|
puts("FAIL: ");
|
||||||
|
puts(s);
|
||||||
|
puts("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
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(&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);
|
||||||
|
write((const uint8_t *)&name, 4);
|
||||||
|
puts(" ");
|
||||||
|
wordcpy_s(&name, 1, (void *)tk1name1, 1);
|
||||||
|
reverseword(&name);
|
||||||
|
write((const uint8_t *)&name, 4);
|
||||||
|
puts("\r\n");
|
||||||
|
|
||||||
|
uint32_t zeros[8];
|
||||||
|
memset(zeros, 0, 8 * 4);
|
||||||
|
|
||||||
|
int anyfailed = 0;
|
||||||
|
|
||||||
|
uint32_t uds_local[UDS_WORDS];
|
||||||
|
uint32_t udi_local[UDI_WORDS];
|
||||||
|
|
||||||
|
uint32_t sw = *system_mode_ctrl;
|
||||||
|
if (sw != 0xffffffff) {
|
||||||
|
failmsg("system_mode_ctrl is not 0xffffffff");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should NOT be able to read from UDS in app-mode.
|
||||||
|
wordcpy_s(uds_local, UDS_WORDS, (void *)uds, UDS_WORDS);
|
||||||
|
if (!memeq(uds_local, zeros, UDS_WORDS * 4)) {
|
||||||
|
failmsg("Read from UDS in app-mode");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should NOT be able to read from UDI in app-mode.
|
||||||
|
wordcpy_s(udi_local, UDI_WORDS, (void *)udi, UDI_WORDS);
|
||||||
|
if (!memeq(udi_local, zeros, UDI_WORDS * 4)) {
|
||||||
|
failmsg("Read from UDI in app-mode");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cdi_local[CDI_WORDS];
|
||||||
|
uint32_t cdi_local2[CDI_WORDS];
|
||||||
|
wordcpy_s(cdi_local, CDI_WORDS, (void *)cdi, CDI_WORDS);
|
||||||
|
|
||||||
|
// Write to CDI should NOT have any effect in app mode.
|
||||||
|
wordcpy_s((void *)cdi, CDI_WORDS, zeros, CDI_WORDS);
|
||||||
|
wordcpy_s(cdi_local2, CDI_WORDS, (void *)cdi, CDI_WORDS);
|
||||||
|
if (!memeq(cdi_local, cdi_local2, CDI_WORDS * 4)) {
|
||||||
|
failmsg("Write to CDI in app-mode");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
syscall_enable();
|
||||||
|
|
||||||
|
// Syscall should be able to access flash
|
||||||
|
puts("\r\nReading SPI flash capacity using syscall...\r\n");
|
||||||
|
int flash_capacity = syscall(TK1_SYSCALL_GET_FLASH_CAPACITY, 0);
|
||||||
|
if (flash_capacity != 0x14) {
|
||||||
|
failmsg("Expected SPI flash capacity: 0x14 (1 MByte)");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test FW_RAM.
|
||||||
|
*fw_ram = 0x21;
|
||||||
|
if (*fw_ram == 0x21) {
|
||||||
|
failmsg("Write and read FW RAM in app-mode");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("\r\nTesting timer... 3");
|
||||||
|
// Matching clock at 21 MHz, giving us timer in seconds
|
||||||
|
*timer_prescaler = 21 * 1000000;
|
||||||
|
|
||||||
|
// Test timer expiration after 1s
|
||||||
|
*timer = 1;
|
||||||
|
// Start the timer
|
||||||
|
*timer_ctrl = (1 << TK1_MMIO_TIMER_CTRL_START_BIT);
|
||||||
|
while (*timer_status & (1 << TK1_MMIO_TIMER_STATUS_RUNNING_BIT)) {
|
||||||
|
}
|
||||||
|
// Now timer has expired and is ready to run again
|
||||||
|
puts(" 2");
|
||||||
|
|
||||||
|
// Test to interrupt a timer - and reads from timer register
|
||||||
|
// Starting 10s timer and interrupting it in 3s...
|
||||||
|
*timer = 10;
|
||||||
|
*timer_ctrl = (1 << TK1_MMIO_TIMER_CTRL_START_BIT);
|
||||||
|
uint32_t last_timer = 10;
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
last_timer = wait_timer_tick(last_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the timer
|
||||||
|
*timer_ctrl = (1 << TK1_MMIO_TIMER_CTRL_STOP_BIT);
|
||||||
|
puts(" 1. done.\r\n");
|
||||||
|
|
||||||
|
if (*timer_status & (1 << TK1_MMIO_TIMER_STATUS_RUNNING_BIT)) {
|
||||||
|
failmsg("Timer didn't stop");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*timer != 10) {
|
||||||
|
failmsg("Timer didn't reset to 10");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check and display test results.
|
||||||
|
puts("\r\n--> ");
|
||||||
|
if (anyfailed) {
|
||||||
|
puts("Some test FAILED!\r\n");
|
||||||
|
} else {
|
||||||
|
puts("All tests passed.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 &
|
||||||
|
(1 << TK1_MMIO_TRNG_STATUS_READY_BIT)) == 0) {
|
||||||
|
}
|
||||||
|
uint32_t rnd = *trng_entropy;
|
||||||
|
puthexn((uint8_t *)&rnd, 4);
|
||||||
|
puts(" ");
|
||||||
|
}
|
||||||
|
puts("\r\n");
|
||||||
|
}
|
||||||
|
puts("\r\n");
|
||||||
|
|
||||||
|
puts("Now echoing what you type...Type + to reset device\r\n");
|
||||||
|
for (;;) {
|
||||||
|
in = readbyte(&mode, &mode_bytes_left);
|
||||||
|
if (in == '+') {
|
||||||
|
syscall(TK1_SYSCALL_RESET, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
writebyte(MODE_CDC);
|
||||||
|
writebyte(1);
|
||||||
|
writebyte(in);
|
||||||
|
}
|
||||||
|
}
|
94
hw/application_fpga/fw/testapp/syscall.S
Normal file
94
hw/application_fpga/fw/testapp/syscall.S
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
#include "../tk1/picorv32/custom_ops.S"
|
||||||
|
|
||||||
|
.section ".text"
|
||||||
|
.globl syscall_enable
|
||||||
|
.globl syscall
|
||||||
|
|
||||||
|
syscall_enable:
|
||||||
|
// Enable IRQs
|
||||||
|
li t0, 0x7fffffff // IRQ31 mask
|
||||||
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
syscall:
|
||||||
|
// Save registers to stack
|
||||||
|
addi sp, sp, -32*4
|
||||||
|
sw x0, 0*4(sp)
|
||||||
|
sw x1, 1*4(sp)
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||||
|
sw x3, 3*4(sp)
|
||||||
|
sw x4, 4*4(sp)
|
||||||
|
sw x5, 5*4(sp)
|
||||||
|
sw x6, 6*4(sp)
|
||||||
|
sw x7, 7*4(sp)
|
||||||
|
sw x8, 8*4(sp)
|
||||||
|
sw x9, 9*4(sp)
|
||||||
|
// x10 (a0) will contain syscall return value. And should not be saved.
|
||||||
|
sw x11, 11*4(sp)
|
||||||
|
sw x12, 12*4(sp)
|
||||||
|
sw x13, 13*4(sp)
|
||||||
|
sw x14, 14*4(sp)
|
||||||
|
sw x15, 15*4(sp)
|
||||||
|
sw x16, 16*4(sp)
|
||||||
|
sw x17, 17*4(sp)
|
||||||
|
sw x18, 18*4(sp)
|
||||||
|
sw x19, 19*4(sp)
|
||||||
|
sw x20, 20*4(sp)
|
||||||
|
sw x21, 21*4(sp)
|
||||||
|
sw x22, 22*4(sp)
|
||||||
|
sw x23, 23*4(sp)
|
||||||
|
sw x24, 24*4(sp)
|
||||||
|
sw x25, 25*4(sp)
|
||||||
|
sw x26, 26*4(sp)
|
||||||
|
sw x27, 27*4(sp)
|
||||||
|
sw x28, 28*4(sp)
|
||||||
|
sw x29, 29*4(sp)
|
||||||
|
sw x30, 30*4(sp)
|
||||||
|
sw x31, 31*4(sp)
|
||||||
|
|
||||||
|
// Trigger syscall interrupt
|
||||||
|
li t0, (1 << 31)
|
||||||
|
and t0, a0, t0
|
||||||
|
li t1, 0xe1000000 // Syscall interrupt trigger address
|
||||||
|
sw zero, 0(t1) // Trigger interrupt
|
||||||
|
|
||||||
|
// Restore registers from stack
|
||||||
|
lw x0, 0*4(sp)
|
||||||
|
lw x1, 1*4(sp)
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||||
|
lw x3, 3*4(sp)
|
||||||
|
lw x4, 4*4(sp)
|
||||||
|
lw x5, 5*4(sp)
|
||||||
|
lw x6, 6*4(sp)
|
||||||
|
lw x7, 7*4(sp)
|
||||||
|
lw x8, 8*4(sp)
|
||||||
|
lw x9, 9*4(sp)
|
||||||
|
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||||
|
lw x11, 11*4(sp)
|
||||||
|
lw x12, 12*4(sp)
|
||||||
|
lw x13, 13*4(sp)
|
||||||
|
lw x14, 14*4(sp)
|
||||||
|
lw x15, 15*4(sp)
|
||||||
|
lw x16, 16*4(sp)
|
||||||
|
lw x17, 17*4(sp)
|
||||||
|
lw x18, 18*4(sp)
|
||||||
|
lw x19, 19*4(sp)
|
||||||
|
lw x20, 20*4(sp)
|
||||||
|
lw x21, 21*4(sp)
|
||||||
|
lw x22, 22*4(sp)
|
||||||
|
lw x23, 23*4(sp)
|
||||||
|
lw x24, 24*4(sp)
|
||||||
|
lw x25, 25*4(sp)
|
||||||
|
lw x26, 26*4(sp)
|
||||||
|
lw x27, 27*4(sp)
|
||||||
|
lw x28, 28*4(sp)
|
||||||
|
lw x29, 29*4(sp)
|
||||||
|
lw x30, 30*4(sp)
|
||||||
|
lw x31, 31*4(sp)
|
||||||
|
addi sp, sp, 32*4
|
||||||
|
|
||||||
|
ret
|
12
hw/application_fpga/fw/testapp/syscall.h
Normal file
12
hw/application_fpga/fw/testapp/syscall.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 Tillitis AB <tillitis.se>
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
|
||||||
|
#ifndef TKEY_APP_SYSCALL_H
|
||||||
|
#define TKEY_APP_SYSCALL_H
|
||||||
|
|
||||||
|
void syscall_enable(void);
|
||||||
|
int syscall(uint32_t number, uint32_t arg1);
|
||||||
|
|
||||||
|
#endif
|
@ -3,12 +3,14 @@
|
|||||||
* SPDX-License-Identifier: GPL-2.0-only
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../tk1/blake2s/blake2s.h"
|
#include "../tk1/flash.h"
|
||||||
#include "../tk1/lib.h"
|
#include "../tk1/lib.h"
|
||||||
#include "../tk1/proto.h"
|
#include "../tk1/proto.h"
|
||||||
#include "../tk1/types.h"
|
#include "../tk1/types.h"
|
||||||
#include "../tk1_mem.h"
|
#include "../tk1_mem.h"
|
||||||
|
|
||||||
|
#define USBMODE_PACKET_SIZE 64
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
volatile uint32_t *tk1name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
|
volatile uint32_t *tk1name0 = (volatile uint32_t *)TK1_MMIO_TK1_NAME0;
|
||||||
volatile uint32_t *tk1name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
|
volatile uint32_t *tk1name1 = (volatile uint32_t *)TK1_MMIO_TK1_NAME1;
|
||||||
@ -23,7 +25,6 @@ volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER_STATUS
|
|||||||
volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
|
volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
|
||||||
volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS;
|
volatile uint32_t *trng_status = (volatile uint32_t *)TK1_MMIO_TRNG_STATUS;
|
||||||
volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY;
|
volatile uint32_t *trng_entropy = (volatile uint32_t *)TK1_MMIO_TRNG_ENTROPY;
|
||||||
volatile uint32_t *fw_blake2s_addr = (volatile uint32_t *)TK1_MMIO_TK1_BLAKE2S;
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#define UDS_WORDS 8
|
#define UDS_WORDS 8
|
||||||
@ -42,26 +43,68 @@ void *memcpy(void *dest, const void *src, size_t n)
|
|||||||
return dest;
|
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++) {
|
// Append USB Mode Protocol header:
|
||||||
writebyte(*c);
|
// 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++) {
|
uint8_t len;
|
||||||
writebyte(p[i]);
|
|
||||||
|
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)
|
void puthex(uint8_t c)
|
||||||
{
|
{
|
||||||
unsigned int upper = (c >> 4) & 0xf;
|
uint8_t buf[2];
|
||||||
unsigned int lower = c & 0xf;
|
|
||||||
writebyte(upper < 10 ? '0' + upper : 'a' - 10 + upper);
|
hex(buf, c);
|
||||||
writebyte(lower < 10 ? '0' + lower : 'a' - 10 + lower);
|
write(buf, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void puthexn(uint8_t *p, int n)
|
void puthexn(uint8_t *p, int n)
|
||||||
@ -78,7 +121,7 @@ void hexdump(void *buf, int len)
|
|||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
puthex(byte_buf[i]);
|
puthex(byte_buf[i]);
|
||||||
if (i % 2 == 1) {
|
if (i % 2 == 1) {
|
||||||
writebyte(' ');
|
puts(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != 1 && i % 16 == 1) {
|
if (i != 1 && i % 16 == 1) {
|
||||||
@ -151,12 +194,10 @@ void failmsg(char *s)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Function pointer to blake2s()
|
uint8_t in = 0;
|
||||||
volatile int (*fw_blake2s)(void *, unsigned long, const void *,
|
uint8_t mode = 0;
|
||||||
unsigned long, const void *, unsigned long,
|
uint8_t mode_bytes_left = 0;
|
||||||
blake2s_ctx *);
|
|
||||||
|
|
||||||
uint8_t in;
|
|
||||||
// Hard coded test UDS in ../../data/uds.hex
|
// Hard coded test UDS in ../../data/uds.hex
|
||||||
// clang-format off
|
// clang-format off
|
||||||
uint32_t uds_test[8] = {
|
uint32_t uds_test[8] = {
|
||||||
@ -172,18 +213,18 @@ int main(void)
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// Wait for terminal program and a character to be typed
|
// Wait for terminal program and a character to be typed
|
||||||
in = readbyte();
|
in = readbyte(&mode, &mode_bytes_left);
|
||||||
|
|
||||||
puts("\r\nI'm testfw on:");
|
puts("\r\nI'm testfw on:");
|
||||||
// Output the TK1 core's NAME0 and NAME1
|
// Output the TK1 core's NAME0 and NAME1
|
||||||
uint32_t name;
|
uint32_t name;
|
||||||
wordcpy_s(&name, 1, (void *)tk1name0, 1);
|
wordcpy_s(&name, 1, (void *)tk1name0, 1);
|
||||||
reverseword(&name);
|
reverseword(&name);
|
||||||
putsn((char *)&name, 4);
|
write((const uint8_t *)&name, 4);
|
||||||
puts(" ");
|
puts(" ");
|
||||||
wordcpy_s(&name, 1, (void *)tk1name1, 1);
|
wordcpy_s(&name, 1, (void *)tk1name1, 1);
|
||||||
reverseword(&name);
|
reverseword(&name);
|
||||||
putsn((char *)&name, 4);
|
write((const uint8_t *)&name, 4);
|
||||||
puts("\r\n");
|
puts("\r\n");
|
||||||
|
|
||||||
uint32_t zeros[8];
|
uint32_t zeros[8];
|
||||||
@ -246,6 +287,16 @@ int main(void)
|
|||||||
anyfailed = 1;
|
anyfailed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t jedec_id[3];
|
||||||
|
puts("\r\nReading SPI flash capacity...\r\n");
|
||||||
|
flash_release_powerdown();
|
||||||
|
flash_read_jedec_id(jedec_id);
|
||||||
|
|
||||||
|
if (jedec_id[2] != 0x14) {
|
||||||
|
failmsg("Expected SPI flash capacity: 0x14 (1 MByte)");
|
||||||
|
anyfailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Test FW_RAM.
|
// Test FW_RAM.
|
||||||
puts("\r\nTesting FW_RAM (takes 15s on hw)...\r\n");
|
puts("\r\nTesting FW_RAM (takes 15s on hw)...\r\n");
|
||||||
for (unsigned int i = 0; i < TK1_MMIO_FW_RAM_SIZE; i++) {
|
for (unsigned int i = 0; i < TK1_MMIO_FW_RAM_SIZE; i++) {
|
||||||
@ -263,56 +314,9 @@ int main(void)
|
|||||||
anyfailed = 1;
|
anyfailed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store function pointer to blake2s() so it's reachable from app
|
|
||||||
*fw_blake2s_addr = (uint32_t)blake2s;
|
|
||||||
|
|
||||||
// Turn on application mode.
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
*system_mode_ctrl = 1;
|
|
||||||
|
|
||||||
sw = *system_mode_ctrl;
|
|
||||||
if (sw != 0xffffffff) {
|
|
||||||
failmsg("system_mode_ctrl is not 0xffffffff in app mode");
|
|
||||||
anyfailed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should NOT be able to read from UDS in app-mode.
|
|
||||||
wordcpy_s(uds_local, UDS_WORDS, (void *)uds, UDS_WORDS);
|
|
||||||
if (!memeq(uds_local, zeros, UDS_WORDS * 4)) {
|
|
||||||
failmsg("Read from UDS in app-mode");
|
|
||||||
anyfailed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should NOT be able to read from UDI in app-mode.
|
|
||||||
wordcpy_s(udi_local, UDI_WORDS, (void *)udi, UDI_WORDS);
|
|
||||||
if (!memeq(udi_local, zeros, UDI_WORDS * 4)) {
|
|
||||||
failmsg("Read from UDI in app-mode");
|
|
||||||
anyfailed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t cdi_local[CDI_WORDS];
|
|
||||||
uint32_t cdi_local2[CDI_WORDS];
|
|
||||||
wordcpy_s(cdi_local, CDI_WORDS, (void *)cdi, CDI_WORDS);
|
|
||||||
|
|
||||||
// Write to CDI should NOT have any effect in app mode.
|
|
||||||
wordcpy_s((void *)cdi, CDI_WORDS, zeros, CDI_WORDS);
|
|
||||||
wordcpy_s(cdi_local2, CDI_WORDS, (void *)cdi, CDI_WORDS);
|
|
||||||
if (!memeq(cdi_local, cdi_local2, CDI_WORDS * 4)) {
|
|
||||||
failmsg("Write to CDI in app-mode");
|
|
||||||
anyfailed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test FW_RAM.
|
|
||||||
*fw_ram = 0x21;
|
|
||||||
if (*fw_ram == 0x21) {
|
|
||||||
failmsg("Write and read FW RAM in app-mode");
|
|
||||||
anyfailed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
puts("\r\nTesting timer... 3");
|
puts("\r\nTesting timer... 3");
|
||||||
// Matching clock at 18 MHz, giving us timer in seconds
|
// Matching clock at 21 MHz, giving us timer in seconds
|
||||||
*timer_prescaler = 18 * 1000000;
|
*timer_prescaler = 21 * 1000000;
|
||||||
|
|
||||||
// Test timer expiration after 1s
|
// Test timer expiration after 1s
|
||||||
*timer = 1;
|
*timer = 1;
|
||||||
@ -346,32 +350,6 @@ int main(void)
|
|||||||
anyfailed = 1;
|
anyfailed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Testing the blake2s MMIO in app mode
|
|
||||||
|
|
||||||
fw_blake2s = (volatile int (*)(void *, unsigned long, const void *,
|
|
||||||
unsigned long, const void *,
|
|
||||||
unsigned long, blake2s_ctx *)) *
|
|
||||||
fw_blake2s_addr;
|
|
||||||
|
|
||||||
char msg[17] = "dldlkjsdkljdslsdj";
|
|
||||||
uint32_t digest0[8];
|
|
||||||
uint32_t digest1[8];
|
|
||||||
blake2s_ctx b2s_ctx;
|
|
||||||
|
|
||||||
blake2s(&digest0[0], 32, NULL, 0, &msg, 17, &b2s_ctx);
|
|
||||||
fw_blake2s(&digest1[0], 32, NULL, 0, &msg, 17, &b2s_ctx);
|
|
||||||
|
|
||||||
puts("\r\ndigest #0: \r\n");
|
|
||||||
hexdump((uint8_t *)digest0, 32);
|
|
||||||
|
|
||||||
puts("digest #1: \r\n");
|
|
||||||
hexdump((uint8_t *)digest1, 32);
|
|
||||||
|
|
||||||
if (!memeq(digest0, digest1, 32)) {
|
|
||||||
failmsg("Digests not the same");
|
|
||||||
anyfailed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check and display test results.
|
// Check and display test results.
|
||||||
puts("\r\n--> ");
|
puts("\r\n--> ");
|
||||||
if (anyfailed) {
|
if (anyfailed) {
|
||||||
@ -381,6 +359,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
puts("\r\nHere are 256 bytes from the TRNG:\r\n");
|
puts("\r\nHere are 256 bytes from the TRNG:\r\n");
|
||||||
|
|
||||||
for (int j = 0; j < 8; j++) {
|
for (int j = 0; j < 8; j++) {
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
while ((*trng_status &
|
while ((*trng_status &
|
||||||
@ -396,7 +375,10 @@ int main(void)
|
|||||||
|
|
||||||
puts("Now echoing what you type...\r\n");
|
puts("Now echoing what you type...\r\n");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
in = readbyte(); // blocks
|
in = readbyte(&mode, &mode_bytes_left);
|
||||||
|
|
||||||
|
writebyte(MODE_CDC);
|
||||||
|
writebyte(1);
|
||||||
writebyte(in);
|
writebyte(in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# Uses ../.clang-format
|
# Uses ../.clang-format
|
||||||
FMTFILES=main.c lib.h lib.c proto.h proto.c types.h assert.c assert.h led.c led.h
|
FMTFILES=main.c lib.h lib.c proto.h proto.c types.h assert.c assert.h led.c \
|
||||||
|
led.h syscall.c spi.c spi.h flash.c flash.h
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt:
|
fmt:
|
||||||
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||||
|
216
hw/application_fpga/fw/tk1/flash.c
Normal file
216
hw/application_fpga/fw/tk1/flash.c
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
// Copyright (C) 2024 - Tillitis AB
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include "flash.h"
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
#include "../tk1_mem.h"
|
||||||
|
#include "spi.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static volatile uint32_t *timer = (volatile uint32_t *)TK1_MMIO_TIMER_TIMER;
|
||||||
|
static volatile uint32_t *timer_prescaler = (volatile uint32_t *)TK1_MMIO_TIMER_PRESCALER;
|
||||||
|
static volatile uint32_t *timer_status = (volatile uint32_t *)TK1_MMIO_TIMER_STATUS;
|
||||||
|
static volatile uint32_t *timer_ctrl = (volatile uint32_t *)TK1_MMIO_TIMER_CTRL;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// CPU clock frequency in Hz
|
||||||
|
#define CPUFREQ 21000000
|
||||||
|
#define PAGE_SIZE 256
|
||||||
|
|
||||||
|
static void delay(int timeout_ms)
|
||||||
|
{
|
||||||
|
// Tick once every centisecond
|
||||||
|
*timer_prescaler = CPUFREQ / 100;
|
||||||
|
*timer = timeout_ms / 10;
|
||||||
|
|
||||||
|
*timer_ctrl |= (1 << TK1_MMIO_TIMER_CTRL_START_BIT);
|
||||||
|
|
||||||
|
while (*timer_status != 0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop timer
|
||||||
|
*timer_ctrl |= (1 << TK1_MMIO_TIMER_CTRL_STOP_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool flash_is_busy(void)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf = READ_STATUS_REG_1;
|
||||||
|
uint8_t rx_buf = {0x00};
|
||||||
|
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, &rx_buf, sizeof(rx_buf));
|
||||||
|
|
||||||
|
if (rx_buf & (1 << STATUS_REG_BUSY_BIT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocking until !busy
|
||||||
|
void flash_wait_busy(void)
|
||||||
|
{
|
||||||
|
while (flash_is_busy()) {
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_write_enable(void)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf = WRITE_ENABLE;
|
||||||
|
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_write_disable(void)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf = WRITE_DISABLE;
|
||||||
|
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_sector_erase(uint32_t address)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[4] = {0x00};
|
||||||
|
tx_buf[0] = SECTOR_ERASE;
|
||||||
|
tx_buf[1] = (address >> ADDR_BYTE_3_BIT) & 0xFF;
|
||||||
|
tx_buf[2] = (address >> ADDR_BYTE_2_BIT) & 0xFF;
|
||||||
|
/* tx_buf[3] is within a sector, and hence does not make a difference */
|
||||||
|
|
||||||
|
flash_write_enable();
|
||||||
|
spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
flash_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_block_32_erase(uint32_t address)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[4] = {0x00};
|
||||||
|
tx_buf[0] = BLOCK_ERASE_32K;
|
||||||
|
tx_buf[1] = (address >> ADDR_BYTE_3_BIT) & 0xFF;
|
||||||
|
tx_buf[2] = (address >> ADDR_BYTE_2_BIT) & 0xFF;
|
||||||
|
tx_buf[3] = (address >> ADDR_BYTE_1_BIT) & 0xFF;
|
||||||
|
|
||||||
|
flash_write_enable();
|
||||||
|
spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
flash_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 64 KiB block erase, only cares about address bits 16 and above.
|
||||||
|
void flash_block_64_erase(uint32_t address)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[4] = {0x00};
|
||||||
|
tx_buf[0] = BLOCK_ERASE_64K;
|
||||||
|
tx_buf[1] = (address >> ADDR_BYTE_3_BIT) & 0xFF;
|
||||||
|
/* tx_buf[2] and tx_buf[3] is within a block, and hence does not make a
|
||||||
|
* difference */
|
||||||
|
|
||||||
|
flash_write_enable();
|
||||||
|
spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
flash_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_release_powerdown(void)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[4] = {0x00};
|
||||||
|
tx_buf[0] = RELEASE_POWER_DOWN;
|
||||||
|
|
||||||
|
spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_powerdown(void)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf = POWER_DOWN;
|
||||||
|
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_read_manufacturer_device_id(uint8_t *device_id)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[4] = {0x00};
|
||||||
|
tx_buf[0] = READ_MANUFACTURER_ID;
|
||||||
|
|
||||||
|
spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, device_id, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_read_jedec_id(uint8_t *jedec_id)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf = READ_JEDEC_ID;
|
||||||
|
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, jedec_id, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_read_unique_id(uint8_t *unique_id)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[5] = {0x00};
|
||||||
|
tx_buf[0] = READ_UNIQUE_ID;
|
||||||
|
|
||||||
|
spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, unique_id, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_read_status(uint8_t *status_reg)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf = READ_STATUS_REG_1;
|
||||||
|
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, status_reg, 1);
|
||||||
|
|
||||||
|
tx_buf = READ_STATUS_REG_2;
|
||||||
|
spi_transfer(&tx_buf, sizeof(tx_buf), NULL, 0, status_reg + 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int flash_read_data(uint32_t address, uint8_t *dest_buf, size_t size)
|
||||||
|
{
|
||||||
|
uint8_t tx_buf[4] = {0x00};
|
||||||
|
tx_buf[0] = READ_DATA;
|
||||||
|
tx_buf[1] = (address >> ADDR_BYTE_3_BIT) & 0xFF;
|
||||||
|
tx_buf[2] = (address >> ADDR_BYTE_2_BIT) & 0xFF;
|
||||||
|
tx_buf[3] = (address >> ADDR_BYTE_1_BIT) & 0xFF;
|
||||||
|
|
||||||
|
return spi_transfer(tx_buf, sizeof(tx_buf), NULL, 0, dest_buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only handles writes where the least significant byte of the start address is
|
||||||
|
// zero.
|
||||||
|
int flash_write_data(uint32_t address, uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
if (size <= 0 || size > 4096) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t left = size;
|
||||||
|
uint8_t *p_data = data;
|
||||||
|
size_t n_bytes = 0;
|
||||||
|
|
||||||
|
uint8_t tx_buf[4] = {
|
||||||
|
PAGE_PROGRAM, /* tx_buf[0] */
|
||||||
|
(address >> ADDR_BYTE_3_BIT) & 0xFF, /* tx_buf[1] */
|
||||||
|
(address >> ADDR_BYTE_2_BIT) & 0xFF, /* tx_buf[2] */
|
||||||
|
0x00, /* tx_buf[3] */
|
||||||
|
};
|
||||||
|
|
||||||
|
while (left > 0) {
|
||||||
|
if (left >= PAGE_SIZE) {
|
||||||
|
n_bytes = PAGE_SIZE;
|
||||||
|
} else {
|
||||||
|
n_bytes = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash_write_enable();
|
||||||
|
|
||||||
|
if (spi_transfer(tx_buf, sizeof(tx_buf), p_data, n_bytes, NULL,
|
||||||
|
0) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
left -= n_bytes;
|
||||||
|
p_data += n_bytes;
|
||||||
|
|
||||||
|
address += n_bytes;
|
||||||
|
tx_buf[1] = (address >> ADDR_BYTE_3_BIT) & 0xFF;
|
||||||
|
tx_buf[2] = (address >> ADDR_BYTE_2_BIT) & 0xFF;
|
||||||
|
|
||||||
|
flash_wait_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
57
hw/application_fpga/fw/tk1/flash.h
Normal file
57
hw/application_fpga/fw/tk1/flash.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright (C) 2024 - Tillitis AB
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#ifndef TKEY_FLASH_H
|
||||||
|
#define TKEY_FLASH_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define WRITE_ENABLE 0x06
|
||||||
|
#define WRITE_DISABLE 0x04
|
||||||
|
|
||||||
|
#define READ_STATUS_REG_1 0x05
|
||||||
|
#define READ_STATUS_REG_2 0x35
|
||||||
|
#define WRITE_STATUS_REG 0x01
|
||||||
|
|
||||||
|
#define PAGE_PROGRAM 0x02
|
||||||
|
#define SECTOR_ERASE 0x20
|
||||||
|
#define BLOCK_ERASE_32K 0x52
|
||||||
|
#define BLOCK_ERASE_64K 0xD8
|
||||||
|
#define CHIP_ERASE 0xC7
|
||||||
|
|
||||||
|
#define POWER_DOWN 0xB9
|
||||||
|
#define READ_DATA 0x03
|
||||||
|
#define RELEASE_POWER_DOWN 0xAB
|
||||||
|
|
||||||
|
#define READ_MANUFACTURER_ID 0x90
|
||||||
|
#define READ_JEDEC_ID 0x9F
|
||||||
|
#define READ_UNIQUE_ID 0x4B
|
||||||
|
|
||||||
|
#define ENABLE_RESET 0x66
|
||||||
|
#define RESET 0x99
|
||||||
|
|
||||||
|
#define ADDR_BYTE_3_BIT 16
|
||||||
|
#define ADDR_BYTE_2_BIT 8
|
||||||
|
#define ADDR_BYTE_1_BIT 0
|
||||||
|
|
||||||
|
#define STATUS_REG_BUSY_BIT 0
|
||||||
|
#define STATUS_REG_WEL_BIT 1
|
||||||
|
|
||||||
|
bool flash_is_busy(void);
|
||||||
|
void flash_wait_busy(void);
|
||||||
|
void flash_write_enable(void);
|
||||||
|
void flash_write_disable(void);
|
||||||
|
void flash_sector_erase(uint32_t address);
|
||||||
|
void flash_block_32_erase(uint32_t address);
|
||||||
|
void flash_block_64_erase(uint32_t address);
|
||||||
|
void flash_release_powerdown(void);
|
||||||
|
void flash_powerdown(void);
|
||||||
|
void flash_read_manufacturer_device_id(uint8_t *device_id);
|
||||||
|
void flash_read_jedec_id(uint8_t *jedec_id);
|
||||||
|
void flash_read_unique_id(uint8_t *unique_id);
|
||||||
|
void flash_read_status(uint8_t *status_reg);
|
||||||
|
int flash_read_data(uint32_t address, uint8_t *dest_buf, size_t size);
|
||||||
|
int flash_write_data(uint32_t address, uint8_t *data, size_t size);
|
||||||
|
|
||||||
|
#endif
|
@ -420,6 +420,9 @@ int main(void)
|
|||||||
/*@+mustfreeonly@*/
|
/*@+mustfreeonly@*/
|
||||||
ctx.use_uss = FALSE;
|
ctx.use_uss = FALSE;
|
||||||
|
|
||||||
|
uint8_t mode = 0;
|
||||||
|
uint8_t mode_bytes_left = 0;
|
||||||
|
|
||||||
scramble_ram();
|
scramble_ram();
|
||||||
|
|
||||||
#if defined(SIMULATION)
|
#if defined(SIMULATION)
|
||||||
@ -429,7 +432,8 @@ int main(void)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case FW_STATE_INITIAL:
|
case FW_STATE_INITIAL:
|
||||||
if (readcommand(&hdr, cmd, state) == -1) {
|
if (readcommand(&hdr, cmd, state, &mode,
|
||||||
|
&mode_bytes_left) == -1) {
|
||||||
state = FW_STATE_FAIL;
|
state = FW_STATE_FAIL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -438,7 +442,8 @@ int main(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FW_STATE_LOADING:
|
case FW_STATE_LOADING:
|
||||||
if (readcommand(&hdr, cmd, state) == -1) {
|
if (readcommand(&hdr, cmd, state, &mode,
|
||||||
|
&mode_bytes_left) == -1) {
|
||||||
state = FW_STATE_FAIL;
|
state = FW_STATE_FAIL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
7
hw/application_fpga/fw/tk1/picorv32/README.md
Normal file
7
hw/application_fpga/fw/tk1/picorv32/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# PicoRV32
|
||||||
|
|
||||||
|
## custom_ops.S
|
||||||
|
|
||||||
|
Custom PicoRV32 instructions are located in `custom_ops.S`.
|
||||||
|
`custom_ops.S` is imported from upstream PicoRV32 commit:
|
||||||
|
YosysHQ/picorv32@70f3c33
|
102
hw/application_fpga/fw/tk1/picorv32/custom_ops.S
Normal file
102
hw/application_fpga/fw/tk1/picorv32/custom_ops.S
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
|
||||||
|
#define regnum_q0 0
|
||||||
|
#define regnum_q1 1
|
||||||
|
#define regnum_q2 2
|
||||||
|
#define regnum_q3 3
|
||||||
|
|
||||||
|
#define regnum_x0 0
|
||||||
|
#define regnum_x1 1
|
||||||
|
#define regnum_x2 2
|
||||||
|
#define regnum_x3 3
|
||||||
|
#define regnum_x4 4
|
||||||
|
#define regnum_x5 5
|
||||||
|
#define regnum_x6 6
|
||||||
|
#define regnum_x7 7
|
||||||
|
#define regnum_x8 8
|
||||||
|
#define regnum_x9 9
|
||||||
|
#define regnum_x10 10
|
||||||
|
#define regnum_x11 11
|
||||||
|
#define regnum_x12 12
|
||||||
|
#define regnum_x13 13
|
||||||
|
#define regnum_x14 14
|
||||||
|
#define regnum_x15 15
|
||||||
|
#define regnum_x16 16
|
||||||
|
#define regnum_x17 17
|
||||||
|
#define regnum_x18 18
|
||||||
|
#define regnum_x19 19
|
||||||
|
#define regnum_x20 20
|
||||||
|
#define regnum_x21 21
|
||||||
|
#define regnum_x22 22
|
||||||
|
#define regnum_x23 23
|
||||||
|
#define regnum_x24 24
|
||||||
|
#define regnum_x25 25
|
||||||
|
#define regnum_x26 26
|
||||||
|
#define regnum_x27 27
|
||||||
|
#define regnum_x28 28
|
||||||
|
#define regnum_x29 29
|
||||||
|
#define regnum_x30 30
|
||||||
|
#define regnum_x31 31
|
||||||
|
|
||||||
|
#define regnum_zero 0
|
||||||
|
#define regnum_ra 1
|
||||||
|
#define regnum_sp 2
|
||||||
|
#define regnum_gp 3
|
||||||
|
#define regnum_tp 4
|
||||||
|
#define regnum_t0 5
|
||||||
|
#define regnum_t1 6
|
||||||
|
#define regnum_t2 7
|
||||||
|
#define regnum_s0 8
|
||||||
|
#define regnum_s1 9
|
||||||
|
#define regnum_a0 10
|
||||||
|
#define regnum_a1 11
|
||||||
|
#define regnum_a2 12
|
||||||
|
#define regnum_a3 13
|
||||||
|
#define regnum_a4 14
|
||||||
|
#define regnum_a5 15
|
||||||
|
#define regnum_a6 16
|
||||||
|
#define regnum_a7 17
|
||||||
|
#define regnum_s2 18
|
||||||
|
#define regnum_s3 19
|
||||||
|
#define regnum_s4 20
|
||||||
|
#define regnum_s5 21
|
||||||
|
#define regnum_s6 22
|
||||||
|
#define regnum_s7 23
|
||||||
|
#define regnum_s8 24
|
||||||
|
#define regnum_s9 25
|
||||||
|
#define regnum_s10 26
|
||||||
|
#define regnum_s11 27
|
||||||
|
#define regnum_t3 28
|
||||||
|
#define regnum_t4 29
|
||||||
|
#define regnum_t5 30
|
||||||
|
#define regnum_t6 31
|
||||||
|
|
||||||
|
// x8 is s0 and also fp
|
||||||
|
#define regnum_fp 8
|
||||||
|
|
||||||
|
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||||
|
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||||
|
|
||||||
|
#define picorv32_getq_insn(_rd, _qs) \
|
||||||
|
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_setq_insn(_qd, _rs) \
|
||||||
|
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_retirq_insn() \
|
||||||
|
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_maskirq_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_waitirq_insn(_rd) \
|
||||||
|
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_timer_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
@ -22,7 +22,8 @@ static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
|
|||||||
enum cmdlen len);
|
enum cmdlen len);
|
||||||
static int parseframe(uint8_t b, struct frame_header *hdr);
|
static int parseframe(uint8_t b, struct frame_header *hdr);
|
||||||
static void write(uint8_t *buf, size_t nbytes);
|
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 size_t bytelen(enum cmdlen cmdlen);
|
||||||
|
|
||||||
static uint8_t genhdr(uint8_t id, uint8_t endpoint, uint8_t status,
|
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;
|
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;
|
uint8_t in = 0;
|
||||||
|
|
||||||
set_led((state == FW_STATE_LOADING) ? LED_BLACK : LED_WHITE);
|
set_led((state == FW_STATE_LOADING) ? LED_BLACK : LED_WHITE);
|
||||||
in = readbyte();
|
in = readbyte(mode, mode_bytes_left);
|
||||||
|
|
||||||
if (parseframe(in, hdr) == -1) {
|
if (parseframe(in, hdr) == -1) {
|
||||||
htif_puts("Couldn't parse header\n");
|
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);
|
(void)memset(cmd, 0, CMDLEN_MAXBYTES);
|
||||||
// Now we know the size of the cmd frame, read it all
|
// 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");
|
htif_puts("read: buffer overrun\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -115,6 +117,10 @@ void fwreply(struct frame_header hdr, enum fwcmd rspcode, uint8_t *buf)
|
|||||||
|
|
||||||
nbytes = bytelen(len);
|
nbytes = bytelen(len);
|
||||||
|
|
||||||
|
// Mode Protocol Header
|
||||||
|
writebyte(MODE_CDC);
|
||||||
|
writebyte(2);
|
||||||
|
|
||||||
// Frame Protocol Header
|
// Frame Protocol Header
|
||||||
writebyte(genhdr(hdr.id, hdr.endpoint, 0x0, len));
|
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);
|
writebyte(rspcode);
|
||||||
nbytes--;
|
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)
|
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 (;;) {
|
for (;;) {
|
||||||
if (*can_rx) {
|
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) {
|
if (nbytes > bufsize) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n = 0; n < nbytes; n++) {
|
for (int n = 0; n < nbytes; n++) {
|
||||||
buf[n] = readbyte();
|
buf[n] = readbyte(mode, mode_bytes_left);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
#ifndef PROTO_H
|
#ifndef PROTO_H
|
||||||
#define PROTO_H
|
#define PROTO_H
|
||||||
|
|
||||||
|
enum mode {
|
||||||
|
MODE_TKEYCTRL = 0x20,
|
||||||
|
MODE_CDC = 0x40,
|
||||||
|
MODE_HID = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
enum endpoints {
|
enum endpoints {
|
||||||
DST_HW_IFPGA,
|
DST_HW_IFPGA,
|
||||||
DST_HW_AFPGA,
|
DST_HW_AFPGA,
|
||||||
@ -52,7 +58,8 @@ struct frame_header {
|
|||||||
|
|
||||||
/*@ -exportlocal @*/
|
/*@ -exportlocal @*/
|
||||||
void writebyte(uint8_t b);
|
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);
|
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
|
#endif
|
||||||
|
88
hw/application_fpga/fw/tk1/spi.c
Normal file
88
hw/application_fpga/fw/tk1/spi.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (C) 2024 - Tillitis AB
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include "spi.h"
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
#include "../tk1_mem.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static volatile uint32_t *spi_en = (volatile uint32_t *)(TK1_MMIO_TK1_BASE | 0x200);
|
||||||
|
static volatile uint32_t *spi_xfer = (volatile uint32_t *)(TK1_MMIO_TK1_BASE | 0x204);
|
||||||
|
static volatile uint32_t *spi_data = (volatile uint32_t *)(TK1_MMIO_TK1_BASE | 0x208);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// returns non-zero when the SPI-master is ready, and zero if not
|
||||||
|
// ready. This can be used to check if the SPI-master is available
|
||||||
|
// in the hardware.
|
||||||
|
int spi_ready(void)
|
||||||
|
{
|
||||||
|
return *spi_xfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_enable(void)
|
||||||
|
{
|
||||||
|
*spi_en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_disable(void)
|
||||||
|
{
|
||||||
|
*spi_en = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _spi_write(uint8_t *cmd, size_t size)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
while (!spi_ready()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
*spi_data = cmd[i];
|
||||||
|
*spi_xfer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!spi_ready()) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _spi_read(uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
|
||||||
|
while (!spi_ready()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
|
||||||
|
*spi_data = 0x00;
|
||||||
|
*spi_xfer = 1;
|
||||||
|
|
||||||
|
// wait until spi master is done
|
||||||
|
while (!spi_ready()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i] = (*spi_data & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to both read and write data to the connected SPI flash.
|
||||||
|
int spi_transfer(uint8_t *cmd, size_t cmd_size, uint8_t *tx_buf, size_t tx_size,
|
||||||
|
uint8_t *rx_buf, size_t rx_size)
|
||||||
|
{
|
||||||
|
if (cmd == NULL || cmd_size == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_enable();
|
||||||
|
|
||||||
|
_spi_write(cmd, cmd_size);
|
||||||
|
|
||||||
|
if (tx_buf != NULL || tx_size != 0) {
|
||||||
|
_spi_write(tx_buf, tx_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_buf != NULL && rx_size != 0) {
|
||||||
|
_spi_read(rx_buf, rx_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_disable();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
13
hw/application_fpga/fw/tk1/spi.h
Normal file
13
hw/application_fpga/fw/tk1/spi.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (C) 2024 - Tillitis AB
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#ifndef TKEY_SPI_H
|
||||||
|
#define TKEY_SPI_H
|
||||||
|
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
|
||||||
|
int spi_ready(void);
|
||||||
|
int spi_transfer(uint8_t *cmd, size_t cmd_size, uint8_t *tx_buf, size_t tx_size,
|
||||||
|
uint8_t *rx_buf, size_t rx_size);
|
||||||
|
|
||||||
|
#endif
|
@ -1,11 +1,102 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022, 2023 - Tillitis AB
|
* Copyright (C) 2022, 2023, 2024, 2025 - Tillitis AB
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../tk1_mem.h"
|
||||||
|
#include "picorv32/custom_ops.S" // PicoRV32 custom instructions
|
||||||
|
|
||||||
|
#define illegal_insn() .word 0
|
||||||
|
|
||||||
|
#define FW_SP_STORAGE (TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE - 4)
|
||||||
|
#define FW_STACK_TOP (TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE - 2*4)
|
||||||
|
|
||||||
.section ".text.init"
|
.section ".text.init"
|
||||||
.globl _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
|
j init
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IRQ handler
|
||||||
|
*/
|
||||||
|
.=0x10
|
||||||
|
irq_handler:
|
||||||
|
// PicoRV32 stores the IRQ bitmask in x4.
|
||||||
|
// If bit 31 is 1: IRQ31 was triggered.
|
||||||
|
li t4, (1 << 31)
|
||||||
|
beq x4, t4, irq_source_ok
|
||||||
|
unexpected_irq_source:
|
||||||
|
illegal_insn()
|
||||||
|
j unexpected_irq_source
|
||||||
|
irq_source_ok:
|
||||||
|
|
||||||
|
// Save app stack pointer. App is responsible for saving the rest of
|
||||||
|
// the registers.
|
||||||
|
li t0, FW_SP_STORAGE
|
||||||
|
sw sp, 0(t0)
|
||||||
|
|
||||||
|
// Setup firmware stack pointer
|
||||||
|
li sp, FW_STACK_TOP
|
||||||
|
|
||||||
|
// Run syscall handler
|
||||||
|
call syscall_handler
|
||||||
|
|
||||||
|
// Restore app stack pointer
|
||||||
|
li t0, FW_SP_STORAGE
|
||||||
|
lw sp, 0(t0)
|
||||||
|
|
||||||
|
// Verify that interrupt return address (x3) is in app RAM
|
||||||
|
li t0, TK1_RAM_BASE // 0x40000000
|
||||||
|
blt x3, t0, x3_invalid
|
||||||
|
li t0, TK1_RAM_BASE + TK1_RAM_SIZE // 0x40020000
|
||||||
|
bge x3, t0, x3_invalid
|
||||||
|
j x3_valid
|
||||||
|
x3_invalid:
|
||||||
|
illegal_insn()
|
||||||
|
j x3_invalid
|
||||||
|
x3_valid:
|
||||||
|
|
||||||
|
// Remove data left over from the syscall handling
|
||||||
|
mv x0, zero
|
||||||
|
mv x1, zero
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler
|
||||||
|
// x3 (interrupt return address) assumed preserved
|
||||||
|
mv x4, zero
|
||||||
|
mv x5, zero
|
||||||
|
mv x6, zero
|
||||||
|
mv x7, zero
|
||||||
|
mv x8, zero
|
||||||
|
mv x9, zero
|
||||||
|
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||||
|
mv x11, zero
|
||||||
|
mv x12, zero
|
||||||
|
mv x13, zero
|
||||||
|
mv x14, zero
|
||||||
|
mv x15, zero
|
||||||
|
mv x16, zero
|
||||||
|
mv x17, zero
|
||||||
|
mv x18, zero
|
||||||
|
mv x19, zero
|
||||||
|
mv x20, zero
|
||||||
|
mv x21, zero
|
||||||
|
mv x22, zero
|
||||||
|
mv x23, zero
|
||||||
|
mv x24, zero
|
||||||
|
mv x25, zero
|
||||||
|
mv x26, zero
|
||||||
|
mv x27, zero
|
||||||
|
mv x28, zero
|
||||||
|
mv x29, zero
|
||||||
|
mv x30, zero
|
||||||
|
mv x31, zero
|
||||||
|
|
||||||
|
picorv32_retirq_insn() // Return from interrupt
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Init
|
||||||
|
*/
|
||||||
|
.=0x100
|
||||||
|
init:
|
||||||
li x1, 0
|
li x1, 0
|
||||||
li x2, 0
|
li x2, 0
|
||||||
li x3, 0
|
li x3, 0
|
||||||
|
41
hw/application_fpga/fw/tk1/syscall.c
Normal file
41
hw/application_fpga/fw/tk1/syscall.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../tk1/assert.h"
|
||||||
|
#include "../tk1/flash.h"
|
||||||
|
#include "../tk1/led.h"
|
||||||
|
#include "../tk1/syscall_nrs.h"
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
static volatile uint32_t *system_reset = (volatile uint32_t *)TK1_MMIO_TK1_SYSTEM_RESET;
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// Proof-of-concept firmware for handling syscalls.
|
||||||
|
// This is NOT a best-practice example of secure syscall implementation.
|
||||||
|
|
||||||
|
int32_t syscall_handler(uint32_t syscall_nr, uint32_t arg1)
|
||||||
|
{
|
||||||
|
switch (syscall_nr) {
|
||||||
|
case TK1_SYSCALL_RESET:
|
||||||
|
*system_reset = 1;
|
||||||
|
return 0;
|
||||||
|
case TK1_SYSCALL_SET_LED:
|
||||||
|
set_led(arg1);
|
||||||
|
return 0;
|
||||||
|
case TK1_SYSCALL_GET_FLASH_CAPACITY: {
|
||||||
|
uint8_t jedec_id[3];
|
||||||
|
flash_release_powerdown();
|
||||||
|
flash_read_jedec_id(jedec_id);
|
||||||
|
flash_powerdown();
|
||||||
|
return jedec_id[2];
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert(1 == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(1 == 2);
|
||||||
|
return -1; // This should never run
|
||||||
|
}
|
13
hw/application_fpga/fw/tk1/syscall_nrs.h
Normal file
13
hw/application_fpga/fw/tk1/syscall_nrs.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (C) 2025 - Tillitis AB
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#ifndef TKEY_SYSCALL_H
|
||||||
|
#define TKEY_SYSCALL_H
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TK1_SYSCALL_RESET = 1,
|
||||||
|
TK1_SYSCALL_SET_LED = 10,
|
||||||
|
TK1_SYSCALL_GET_FLASH_CAPACITY = 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -14,7 +14,7 @@ typedef long long int64_t;
|
|||||||
typedef unsigned char uint8_t;
|
typedef unsigned char uint8_t;
|
||||||
typedef unsigned long size_t;
|
typedef unsigned long size_t;
|
||||||
|
|
||||||
#define NULL ((char *)0)
|
#define NULL ((void *)0)
|
||||||
|
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE !FALSE
|
#define TRUE !FALSE
|
||||||
|
@ -82,8 +82,8 @@
|
|||||||
#define TK1_MMIO_TIMER_TIMER 0xc100002c
|
#define TK1_MMIO_TIMER_TIMER 0xc100002c
|
||||||
|
|
||||||
#define TK1_MMIO_UDS_BASE 0xc2000000
|
#define TK1_MMIO_UDS_BASE 0xc2000000
|
||||||
#define TK1_MMIO_UDS_FIRST 0xc2000040
|
#define TK1_MMIO_UDS_FIRST 0xc2000000
|
||||||
#define TK1_MMIO_UDS_LAST 0xc200005c
|
#define TK1_MMIO_UDS_LAST 0xc200001c
|
||||||
|
|
||||||
#define TK1_MMIO_UART_BASE 0xc3000000
|
#define TK1_MMIO_UART_BASE 0xc3000000
|
||||||
#define TK1_MMIO_UART_RX_STATUS 0xc3000080
|
#define TK1_MMIO_UART_RX_STATUS 0xc3000080
|
||||||
|
@ -20,6 +20,9 @@ module application_fpga (
|
|||||||
output wire interface_rx,
|
output wire interface_rx,
|
||||||
input wire interface_tx,
|
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_ss,
|
||||||
output wire spi_sck,
|
output wire spi_sck,
|
||||||
output wire spi_mosi,
|
output wire spi_mosi,
|
||||||
@ -54,11 +57,13 @@ module application_fpga (
|
|||||||
localparam UART_PREFIX = 6'h03;
|
localparam UART_PREFIX = 6'h03;
|
||||||
localparam TOUCH_SENSE_PREFIX = 6'h04;
|
localparam TOUCH_SENSE_PREFIX = 6'h04;
|
||||||
localparam FW_RAM_PREFIX = 6'h10;
|
localparam FW_RAM_PREFIX = 6'h10;
|
||||||
|
localparam IRQ31_PREFIX = 6'h21;
|
||||||
localparam TK1_PREFIX = 6'h3f;
|
localparam TK1_PREFIX = 6'h3f;
|
||||||
|
|
||||||
// Instruction used to cause a trap.
|
// Instruction used to cause a trap.
|
||||||
localparam ILLEGAL_INSTRUCTION = 32'h0;
|
localparam ILLEGAL_INSTRUCTION = 32'h0;
|
||||||
|
|
||||||
|
localparam IRQ31_IRQ_MASK = 2 ** 31;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Registers, memories with associated wires.
|
// Registers, memories with associated wires.
|
||||||
@ -77,11 +82,13 @@ module application_fpga (
|
|||||||
wire reset_n;
|
wire reset_n;
|
||||||
|
|
||||||
/* verilator lint_off UNOPTFLAT */
|
/* verilator lint_off UNOPTFLAT */
|
||||||
|
reg [31 : 0] cpu_irq;
|
||||||
wire cpu_trap;
|
wire cpu_trap;
|
||||||
wire cpu_valid;
|
wire cpu_valid;
|
||||||
wire cpu_instr;
|
wire cpu_instr;
|
||||||
wire [03 : 0] cpu_wstrb;
|
wire [03 : 0] cpu_wstrb;
|
||||||
/* verilator lint_off UNUSED */
|
/* verilator lint_off UNUSED */
|
||||||
|
wire [31 : 0] cpu_eoi;
|
||||||
wire [31 : 0] cpu_addr;
|
wire [31 : 0] cpu_addr;
|
||||||
wire [31 : 0] cpu_wdata;
|
wire [31 : 0] cpu_wdata;
|
||||||
|
|
||||||
@ -129,6 +136,7 @@ module application_fpga (
|
|||||||
reg [31 : 0] fw_ram_write_data;
|
reg [31 : 0] fw_ram_write_data;
|
||||||
wire [31 : 0] fw_ram_read_data;
|
wire [31 : 0] fw_ram_read_data;
|
||||||
wire fw_ram_ready;
|
wire fw_ram_ready;
|
||||||
|
wire fw_ram_en;
|
||||||
|
|
||||||
reg touch_sense_cs;
|
reg touch_sense_cs;
|
||||||
reg touch_sense_we;
|
reg touch_sense_we;
|
||||||
@ -136,13 +144,17 @@ module application_fpga (
|
|||||||
wire [31 : 0] touch_sense_read_data;
|
wire [31 : 0] touch_sense_read_data;
|
||||||
wire touch_sense_ready;
|
wire touch_sense_ready;
|
||||||
|
|
||||||
|
reg irq31_cs;
|
||||||
|
reg irq31_we;
|
||||||
|
reg irq31_eoi;
|
||||||
|
|
||||||
reg tk1_cs;
|
reg tk1_cs;
|
||||||
reg tk1_we;
|
reg tk1_we;
|
||||||
reg [ 7 : 0] tk1_address;
|
reg [ 7 : 0] tk1_address;
|
||||||
reg [31 : 0] tk1_write_data;
|
reg [31 : 0] tk1_write_data;
|
||||||
wire [31 : 0] tk1_read_data;
|
wire [31 : 0] tk1_read_data;
|
||||||
wire tk1_ready;
|
wire tk1_ready;
|
||||||
wire system_mode;
|
wire rw_locked;
|
||||||
wire force_trap;
|
wire force_trap;
|
||||||
wire [14 : 0] ram_addr_rand;
|
wire [14 : 0] ram_addr_rand;
|
||||||
wire [31 : 0] ram_data_rand;
|
wire [31 : 0] ram_data_rand;
|
||||||
@ -163,12 +175,17 @@ module application_fpga (
|
|||||||
|
|
||||||
|
|
||||||
picorv32 #(
|
picorv32 #(
|
||||||
.ENABLE_COUNTERS(0),
|
.ENABLE_COUNTERS (0),
|
||||||
.TWO_STAGE_SHIFT(0),
|
.TWO_STAGE_SHIFT (0),
|
||||||
.CATCH_MISALIGN (0),
|
.CATCH_MISALIGN (0),
|
||||||
.COMPRESSED_ISA (1),
|
.COMPRESSED_ISA (1),
|
||||||
.ENABLE_FAST_MUL(1),
|
.ENABLE_FAST_MUL (1),
|
||||||
.BARREL_SHIFTER (1)
|
.BARREL_SHIFTER (1),
|
||||||
|
.ENABLE_IRQ (1),
|
||||||
|
.ENABLE_IRQ_QREGS(0),
|
||||||
|
.ENABLE_IRQ_TIMER(0),
|
||||||
|
.MASKED_IRQ (~IRQ31_IRQ_MASK),
|
||||||
|
.LATCHED_IRQ (IRQ31_IRQ_MASK)
|
||||||
) cpu (
|
) cpu (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.resetn(reset_n),
|
.resetn(reset_n),
|
||||||
@ -182,11 +199,12 @@ module application_fpga (
|
|||||||
.mem_rdata(muxed_rdata_reg),
|
.mem_rdata(muxed_rdata_reg),
|
||||||
.mem_instr(cpu_instr),
|
.mem_instr(cpu_instr),
|
||||||
|
|
||||||
|
.irq(cpu_irq),
|
||||||
|
.eoi(cpu_eoi),
|
||||||
|
|
||||||
// Defined unused ports. Makes lint happy. But
|
// Defined unused ports. Makes lint happy. But
|
||||||
// we still needs to help lint with empty ports.
|
// we still needs to help lint with empty ports.
|
||||||
/* verilator lint_off PINCONNECTEMPTY */
|
/* verilator lint_off PINCONNECTEMPTY */
|
||||||
.irq(32'h0),
|
|
||||||
.eoi(),
|
|
||||||
.trace_valid(),
|
.trace_valid(),
|
||||||
.trace_data(),
|
.trace_data(),
|
||||||
.mem_la_read(),
|
.mem_la_read(),
|
||||||
@ -237,8 +255,7 @@ module application_fpga (
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset_n(reset_n),
|
.reset_n(reset_n),
|
||||||
|
|
||||||
.system_mode(system_mode),
|
.en(fw_ram_en),
|
||||||
|
|
||||||
.cs(fw_ram_cs),
|
.cs(fw_ram_cs),
|
||||||
.we(fw_ram_we),
|
.we(fw_ram_we),
|
||||||
.address(fw_ram_address),
|
.address(fw_ram_address),
|
||||||
@ -277,7 +294,7 @@ module application_fpga (
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset_n(reset_n),
|
.reset_n(reset_n),
|
||||||
|
|
||||||
.system_mode(system_mode),
|
.en(~rw_locked),
|
||||||
|
|
||||||
.cs(uds_cs),
|
.cs(uds_cs),
|
||||||
.address(uds_address),
|
.address(uds_address),
|
||||||
@ -293,6 +310,9 @@ module application_fpga (
|
|||||||
.rxd(interface_tx),
|
.rxd(interface_tx),
|
||||||
.txd(interface_rx),
|
.txd(interface_rx),
|
||||||
|
|
||||||
|
.ch552_cts(interface_ch552_cts),
|
||||||
|
.fpga_cts (interface_fpga_cts),
|
||||||
|
|
||||||
.cs(uart_cs),
|
.cs(uart_cs),
|
||||||
.we(uart_we),
|
.we(uart_we),
|
||||||
.address(uart_address),
|
.address(uart_address),
|
||||||
@ -320,7 +340,7 @@ module application_fpga (
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset_n(reset_n),
|
.reset_n(reset_n),
|
||||||
|
|
||||||
.system_mode(system_mode),
|
.rw_locked(rw_locked),
|
||||||
|
|
||||||
.cpu_addr (cpu_addr),
|
.cpu_addr (cpu_addr),
|
||||||
.cpu_instr (cpu_instr),
|
.cpu_instr (cpu_instr),
|
||||||
@ -347,6 +367,10 @@ module application_fpga (
|
|||||||
.gpio3(app_gpio3),
|
.gpio3(app_gpio3),
|
||||||
.gpio4(app_gpio4),
|
.gpio4(app_gpio4),
|
||||||
|
|
||||||
|
.access_level_hi(irq31_eoi),
|
||||||
|
|
||||||
|
.fw_ram_en(fw_ram_en),
|
||||||
|
|
||||||
.cs(tk1_cs),
|
.cs(tk1_cs),
|
||||||
.we(tk1_we),
|
.we(tk1_we),
|
||||||
.address(tk1_address),
|
.address(tk1_address),
|
||||||
@ -373,6 +397,20 @@ module application_fpga (
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// irq_ctrl
|
||||||
|
// Interrupt logic
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
always @* begin : irq_ctrl
|
||||||
|
reg irq31_set;
|
||||||
|
|
||||||
|
irq31_set = irq31_cs & irq31_we;
|
||||||
|
cpu_irq = {irq31_set, 31'h0};
|
||||||
|
|
||||||
|
irq31_eoi = cpu_eoi[31];
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// cpu_mem_ctrl
|
// cpu_mem_ctrl
|
||||||
// CPU memory decode and control logic.
|
// CPU memory decode and control logic.
|
||||||
@ -392,7 +430,7 @@ module application_fpga (
|
|||||||
|
|
||||||
ram_cs = 1'h0;
|
ram_cs = 1'h0;
|
||||||
ram_we = 4'h0;
|
ram_we = 4'h0;
|
||||||
ram_address = cpu_addr[17 : 2];
|
ram_address = cpu_addr[16 : 2];
|
||||||
ram_write_data = cpu_wdata;
|
ram_write_data = cpu_wdata;
|
||||||
|
|
||||||
fw_ram_cs = 1'h0;
|
fw_ram_cs = 1'h0;
|
||||||
@ -422,6 +460,9 @@ module application_fpga (
|
|||||||
touch_sense_we = |cpu_wstrb;
|
touch_sense_we = |cpu_wstrb;
|
||||||
touch_sense_address = cpu_addr[9 : 2];
|
touch_sense_address = cpu_addr[9 : 2];
|
||||||
|
|
||||||
|
irq31_cs = 1'h0;
|
||||||
|
irq31_we = |cpu_wstrb;
|
||||||
|
|
||||||
tk1_cs = 1'h0;
|
tk1_cs = 1'h0;
|
||||||
tk1_we = |cpu_wstrb;
|
tk1_we = |cpu_wstrb;
|
||||||
tk1_address = cpu_addr[9 : 2];
|
tk1_address = cpu_addr[9 : 2];
|
||||||
@ -494,6 +535,11 @@ module application_fpga (
|
|||||||
muxed_ready_new = fw_ram_ready;
|
muxed_ready_new = fw_ram_ready;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
IRQ31_PREFIX: begin
|
||||||
|
irq31_cs = 1'h1;
|
||||||
|
muxed_ready_new = 1'h1;
|
||||||
|
end
|
||||||
|
|
||||||
TK1_PREFIX: begin
|
TK1_PREFIX: begin
|
||||||
tk1_cs = 1'h1;
|
tk1_cs = 1'h1;
|
||||||
muxed_rdata_new = tk1_read_data;
|
muxed_rdata_new = tk1_read_data;
|
||||||
|
@ -33,6 +33,9 @@ module application_fpga_sim (
|
|||||||
output wire interface_rx,
|
output wire interface_rx,
|
||||||
input wire interface_tx,
|
input wire interface_tx,
|
||||||
|
|
||||||
|
input wire interface_ch552_cts,
|
||||||
|
output wire interface_fpga_cts,
|
||||||
|
|
||||||
output wire spi_ss,
|
output wire spi_ss,
|
||||||
output wire spi_sck,
|
output wire spi_sck,
|
||||||
output wire spi_mosi,
|
output wire spi_mosi,
|
||||||
@ -67,11 +70,13 @@ module application_fpga_sim (
|
|||||||
localparam UART_PREFIX = 6'h03;
|
localparam UART_PREFIX = 6'h03;
|
||||||
localparam TOUCH_SENSE_PREFIX = 6'h04;
|
localparam TOUCH_SENSE_PREFIX = 6'h04;
|
||||||
localparam FW_RAM_PREFIX = 6'h10;
|
localparam FW_RAM_PREFIX = 6'h10;
|
||||||
|
localparam IRQ31_PREFIX = 6'h21;
|
||||||
localparam TK1_PREFIX = 6'h3f;
|
localparam TK1_PREFIX = 6'h3f;
|
||||||
|
|
||||||
// Instruction used to cause a trap.
|
// Instruction used to cause a trap.
|
||||||
localparam ILLEGAL_INSTRUCTION = 32'h0;
|
localparam ILLEGAL_INSTRUCTION = 32'h0;
|
||||||
|
|
||||||
|
localparam IRQ31_IRQ_MASK = 2 ** 31;
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Registers, memories with associated wires.
|
// Registers, memories with associated wires.
|
||||||
@ -89,11 +94,13 @@ module application_fpga_sim (
|
|||||||
wire reset_n;
|
wire reset_n;
|
||||||
|
|
||||||
/* verilator lint_off UNOPTFLAT */
|
/* verilator lint_off UNOPTFLAT */
|
||||||
|
reg [31 : 0] cpu_irq;
|
||||||
wire cpu_trap;
|
wire cpu_trap;
|
||||||
wire cpu_valid;
|
wire cpu_valid;
|
||||||
wire cpu_instr;
|
wire cpu_instr;
|
||||||
wire [ 3 : 0] cpu_wstrb;
|
wire [ 3 : 0] cpu_wstrb;
|
||||||
/* verilator lint_off UNUSED */
|
/* verilator lint_off UNUSED */
|
||||||
|
wire [31 : 0] cpu_eoi;
|
||||||
wire [31 : 0] cpu_addr;
|
wire [31 : 0] cpu_addr;
|
||||||
wire [31 : 0] cpu_wdata;
|
wire [31 : 0] cpu_wdata;
|
||||||
|
|
||||||
@ -141,6 +148,7 @@ module application_fpga_sim (
|
|||||||
reg [31 : 0] fw_ram_write_data;
|
reg [31 : 0] fw_ram_write_data;
|
||||||
wire [31 : 0] fw_ram_read_data;
|
wire [31 : 0] fw_ram_read_data;
|
||||||
wire fw_ram_ready;
|
wire fw_ram_ready;
|
||||||
|
wire fw_ram_en;
|
||||||
|
|
||||||
reg touch_sense_cs;
|
reg touch_sense_cs;
|
||||||
reg touch_sense_we;
|
reg touch_sense_we;
|
||||||
@ -148,13 +156,17 @@ module application_fpga_sim (
|
|||||||
wire [31 : 0] touch_sense_read_data;
|
wire [31 : 0] touch_sense_read_data;
|
||||||
wire touch_sense_ready;
|
wire touch_sense_ready;
|
||||||
|
|
||||||
|
reg irq31_cs;
|
||||||
|
reg irq31_we;
|
||||||
|
reg irq31_eoi;
|
||||||
|
|
||||||
reg tk1_cs;
|
reg tk1_cs;
|
||||||
reg tk1_we;
|
reg tk1_we;
|
||||||
reg [ 7 : 0] tk1_address;
|
reg [ 7 : 0] tk1_address;
|
||||||
reg [31 : 0] tk1_write_data;
|
reg [31 : 0] tk1_write_data;
|
||||||
wire [31 : 0] tk1_read_data;
|
wire [31 : 0] tk1_read_data;
|
||||||
wire tk1_ready;
|
wire tk1_ready;
|
||||||
wire system_mode;
|
wire rw_locked;
|
||||||
wire force_trap;
|
wire force_trap;
|
||||||
wire [14 : 0] ram_addr_rand;
|
wire [14 : 0] ram_addr_rand;
|
||||||
wire [31 : 0] ram_data_rand;
|
wire [31 : 0] ram_data_rand;
|
||||||
@ -174,12 +186,17 @@ module application_fpga_sim (
|
|||||||
|
|
||||||
|
|
||||||
picorv32 #(
|
picorv32 #(
|
||||||
.ENABLE_COUNTERS(0),
|
.ENABLE_COUNTERS (0),
|
||||||
.TWO_STAGE_SHIFT(0),
|
.TWO_STAGE_SHIFT (0),
|
||||||
.CATCH_MISALIGN (0),
|
.CATCH_MISALIGN (0),
|
||||||
.COMPRESSED_ISA (1),
|
.COMPRESSED_ISA (1),
|
||||||
.ENABLE_FAST_MUL(1),
|
.ENABLE_FAST_MUL (1),
|
||||||
.BARREL_SHIFTER (1)
|
.BARREL_SHIFTER (1),
|
||||||
|
.ENABLE_IRQ (1),
|
||||||
|
.ENABLE_IRQ_QREGS(0),
|
||||||
|
.ENABLE_IRQ_TIMER(0),
|
||||||
|
.MASKED_IRQ (~IRQ31_IRQ_MASK),
|
||||||
|
.LATCHED_IRQ (IRQ31_IRQ_MASK)
|
||||||
) cpu (
|
) cpu (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.resetn(reset_n),
|
.resetn(reset_n),
|
||||||
@ -193,11 +210,12 @@ module application_fpga_sim (
|
|||||||
.mem_rdata(muxed_rdata_reg),
|
.mem_rdata(muxed_rdata_reg),
|
||||||
.mem_instr(cpu_instr),
|
.mem_instr(cpu_instr),
|
||||||
|
|
||||||
|
.irq(cpu_irq),
|
||||||
|
.eoi(cpu_eoi),
|
||||||
|
|
||||||
// Defined unused ports. Makes lint happy. But
|
// Defined unused ports. Makes lint happy. But
|
||||||
// we still needs to help lint with empty ports.
|
// we still needs to help lint with empty ports.
|
||||||
/* verilator lint_off PINCONNECTEMPTY */
|
/* verilator lint_off PINCONNECTEMPTY */
|
||||||
.irq(32'h0),
|
|
||||||
.eoi(),
|
|
||||||
.trace_valid(),
|
.trace_valid(),
|
||||||
.trace_data(),
|
.trace_data(),
|
||||||
.mem_la_read(),
|
.mem_la_read(),
|
||||||
@ -248,8 +266,7 @@ module application_fpga_sim (
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset_n(reset_n),
|
.reset_n(reset_n),
|
||||||
|
|
||||||
.system_mode(system_mode),
|
.en(fw_ram_en),
|
||||||
|
|
||||||
.cs(fw_ram_cs),
|
.cs(fw_ram_cs),
|
||||||
.we(fw_ram_we),
|
.we(fw_ram_we),
|
||||||
.address(fw_ram_address),
|
.address(fw_ram_address),
|
||||||
@ -288,7 +305,7 @@ module application_fpga_sim (
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset_n(reset_n),
|
.reset_n(reset_n),
|
||||||
|
|
||||||
.system_mode(system_mode),
|
.en(~rw_locked),
|
||||||
|
|
||||||
.cs(uds_cs),
|
.cs(uds_cs),
|
||||||
.address(uds_address),
|
.address(uds_address),
|
||||||
@ -304,6 +321,9 @@ module application_fpga_sim (
|
|||||||
.rxd(interface_tx),
|
.rxd(interface_tx),
|
||||||
.txd(interface_rx),
|
.txd(interface_rx),
|
||||||
|
|
||||||
|
.ch552_cts(interface_ch552_cts),
|
||||||
|
.fpga_cts (interface_fpga_cts),
|
||||||
|
|
||||||
.cs(uart_cs),
|
.cs(uart_cs),
|
||||||
.we(uart_we),
|
.we(uart_we),
|
||||||
.address(uart_address),
|
.address(uart_address),
|
||||||
@ -333,7 +353,7 @@ module application_fpga_sim (
|
|||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset_n(reset_n),
|
.reset_n(reset_n),
|
||||||
|
|
||||||
.system_mode(system_mode),
|
.rw_locked(rw_locked),
|
||||||
|
|
||||||
.cpu_addr (cpu_addr),
|
.cpu_addr (cpu_addr),
|
||||||
.cpu_instr (cpu_instr),
|
.cpu_instr (cpu_instr),
|
||||||
@ -360,6 +380,10 @@ module application_fpga_sim (
|
|||||||
.gpio3(app_gpio3),
|
.gpio3(app_gpio3),
|
||||||
.gpio4(app_gpio4),
|
.gpio4(app_gpio4),
|
||||||
|
|
||||||
|
.access_level_hi(irq31_eoi),
|
||||||
|
|
||||||
|
.fw_ram_en(fw_ram_en),
|
||||||
|
|
||||||
.cs(tk1_cs),
|
.cs(tk1_cs),
|
||||||
.we(tk1_we),
|
.we(tk1_we),
|
||||||
.address(tk1_address),
|
.address(tk1_address),
|
||||||
@ -385,6 +409,20 @@ module application_fpga_sim (
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// irq_ctrl
|
||||||
|
// Interrupt logic
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
always @* begin : irq_ctrl
|
||||||
|
reg irq31_set;
|
||||||
|
|
||||||
|
irq31_set = irq31_cs & irq31_we;
|
||||||
|
cpu_irq = {irq31_set, 31'h0};
|
||||||
|
|
||||||
|
irq31_eoi = cpu_eoi[31];
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// cpu_mem_ctrl
|
// cpu_mem_ctrl
|
||||||
// CPU memory decode and control logic.
|
// CPU memory decode and control logic.
|
||||||
@ -406,7 +444,7 @@ module application_fpga_sim (
|
|||||||
|
|
||||||
ram_cs = 1'h0;
|
ram_cs = 1'h0;
|
||||||
ram_we = 4'h0;
|
ram_we = 4'h0;
|
||||||
ram_address = cpu_addr[17 : 2];
|
ram_address = cpu_addr[16 : 2];
|
||||||
ram_write_data = cpu_wdata;
|
ram_write_data = cpu_wdata;
|
||||||
|
|
||||||
fw_ram_cs = 1'h0;
|
fw_ram_cs = 1'h0;
|
||||||
@ -436,6 +474,9 @@ module application_fpga_sim (
|
|||||||
touch_sense_we = |cpu_wstrb;
|
touch_sense_we = |cpu_wstrb;
|
||||||
touch_sense_address = cpu_addr[9 : 2];
|
touch_sense_address = cpu_addr[9 : 2];
|
||||||
|
|
||||||
|
irq31_cs = 1'h0;
|
||||||
|
irq31_we = |cpu_wstrb;
|
||||||
|
|
||||||
tk1_cs = 1'h0;
|
tk1_cs = 1'h0;
|
||||||
tk1_we = |cpu_wstrb;
|
tk1_we = |cpu_wstrb;
|
||||||
tk1_address = cpu_addr[9 : 2];
|
tk1_address = cpu_addr[9 : 2];
|
||||||
@ -528,6 +569,13 @@ module application_fpga_sim (
|
|||||||
muxed_ready_new = fw_ram_ready;
|
muxed_ready_new = fw_ram_ready;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
IRQ31_PREFIX: begin
|
||||||
|
`verbose($display("Access to syscall interrupt trigger");)
|
||||||
|
ascii_state = "Syscall IRQ trigger";
|
||||||
|
irq31_cs = 1'h1;
|
||||||
|
muxed_ready_new = 1'h1;
|
||||||
|
end
|
||||||
|
|
||||||
TK1_PREFIX: begin
|
TK1_PREFIX: begin
|
||||||
`verbose($display("Access to TK1 core");)
|
`verbose($display("Access to TK1 core");)
|
||||||
ascii_state = "TK1 core";
|
ascii_state = "TK1 core";
|
||||||
|
@ -315,6 +315,7 @@ int main(int argc, char **argv, char **env)
|
|||||||
uart_init(&u, &top.interface_tx, &top.interface_rx, BIT_DIV);
|
uart_init(&u, &top.interface_tx, &top.interface_rx, BIT_DIV);
|
||||||
|
|
||||||
top.clk = 0;
|
top.clk = 0;
|
||||||
|
top.interface_ch552_cts = 1;
|
||||||
|
|
||||||
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
||||||
uint8_t to_host = 0;
|
uint8_t to_host = 0;
|
||||||
|
@ -29,6 +29,8 @@ module tb_application_fpga_sim ();
|
|||||||
reg tb_clk = 0;
|
reg tb_clk = 0;
|
||||||
wire tb_interface_rx;
|
wire tb_interface_rx;
|
||||||
reg tb_interface_tx = 1'h1; // Set to 1 to simulate inactive UART
|
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_ss;
|
||||||
wire tb_spi_sck;
|
wire tb_spi_sck;
|
||||||
wire tb_spi_mosi;
|
wire tb_spi_mosi;
|
||||||
@ -49,6 +51,8 @@ module tb_application_fpga_sim ();
|
|||||||
.clk(tb_clk),
|
.clk(tb_clk),
|
||||||
.interface_rx(tb_interface_rx),
|
.interface_rx(tb_interface_rx),
|
||||||
.interface_tx(tb_interface_tx),
|
.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_ss(tb_spi_ss),
|
||||||
.spi_sck(tb_spi_sck),
|
.spi_sck(tb_spi_sck),
|
||||||
.spi_mosi(tb_spi_mosi),
|
.spi_mosi(tb_spi_mosi),
|
||||||
@ -80,7 +84,7 @@ module tb_application_fpga_sim ();
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
initial begin
|
initial begin
|
||||||
// End simulation after XXX time units (set by timescale)
|
// End simulation after XXX time units (set by timescale)
|
||||||
#20000000;
|
#14000;
|
||||||
$display("TIMEOUT");
|
$display("TIMEOUT");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
@ -3,7 +3,6 @@ TARGET = usb_device_cdc
|
|||||||
CH554_SDCC=~/ch554_sdcc/
|
CH554_SDCC=~/ch554_sdcc/
|
||||||
CHPROG=chprog
|
CHPROG=chprog
|
||||||
|
|
||||||
|
|
||||||
# Adjust the XRAM location and size to leave space for the USB DMA buffers
|
# Adjust the XRAM location and size to leave space for the USB DMA buffers
|
||||||
# Buffer layout in XRAM:
|
# Buffer layout in XRAM:
|
||||||
# 0x0000 Ep0Buffer[8]
|
# 0x0000 Ep0Buffer[8]
|
||||||
@ -11,8 +10,11 @@ CHPROG=chprog
|
|||||||
# 0x0080 EP2Buffer[2*64]
|
# 0x0080 EP2Buffer[2*64]
|
||||||
#
|
#
|
||||||
# This takes a total of 256bytes, so there are 768 bytes left.
|
# This takes a total of 256bytes, so there are 768 bytes left.
|
||||||
XRAM_SIZE = 0x0300
|
#XRAM_SIZE = 0x0300
|
||||||
XRAM_LOC = 0x0100
|
#XRAM_LOC = 0x0100
|
||||||
|
|
||||||
|
XRAM_SIZE = 0x0400
|
||||||
|
XRAM_LOC = 0x0000
|
||||||
|
|
||||||
FREQ_SYS = 16000000
|
FREQ_SYS = 16000000
|
||||||
|
|
||||||
@ -21,7 +23,8 @@ usb_strings.h: encode_usb_strings.py
|
|||||||
|
|
||||||
C_FILES = \
|
C_FILES = \
|
||||||
main.c \
|
main.c \
|
||||||
include/debug.c
|
include/debug.c \
|
||||||
|
include/print.c
|
||||||
|
|
||||||
pre-flash:
|
pre-flash:
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ WCHISP ?= wchisptool -g -f
|
|||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
|
|
||||||
|
EXTRA_FLAGS = -D BUILD_CODE
|
||||||
|
|
||||||
FREQ_SYS ?= 24000000
|
FREQ_SYS ?= 24000000
|
||||||
|
|
||||||
XRAM_SIZE ?= 0x0400
|
XRAM_SIZE ?= 0x0400
|
||||||
|
@ -37,17 +37,17 @@ if __name__ == "__main__":
|
|||||||
f.write('#ifndef USB_STRINGS\n')
|
f.write('#ifndef USB_STRINGS\n')
|
||||||
f.write('#define 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(' ')
|
||||||
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(product)]))
|
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(product)]))
|
||||||
f.write('\n};\n\n')
|
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(' ')
|
||||||
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(manufacturer)]))
|
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(manufacturer)]))
|
||||||
f.write('\n};\n\n')
|
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(' ')
|
||||||
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(serial)]))
|
f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(serial)]))
|
||||||
f.write('\n};\n\n')
|
f.write('\n};\n\n')
|
||||||
|
@ -16,31 +16,31 @@ Header file for CH554 microcontrollers.
|
|||||||
/* sbit are bit addressable, others are byte addressable */
|
/* sbit are bit addressable, others are byte addressable */
|
||||||
|
|
||||||
/* System Registers */
|
/* System Registers */
|
||||||
SFR(PSW, 0xD0); // program status word
|
SFR(PSW, 0xD0); // program status word
|
||||||
SBIT(CY, 0xD0, 7); // carry flag
|
SBIT(CY, 0xD0, 7); // carry flag
|
||||||
SBIT(AC, 0xD0, 6); // auxiliary carry flag
|
SBIT(AC, 0xD0, 6); // auxiliary carry flag
|
||||||
SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0
|
SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0
|
||||||
SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit
|
SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit
|
||||||
SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low 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
|
#define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection
|
||||||
// RS1 & RS0: register R0-R7 bank selection
|
// RS1 & RS0: register R0-R7 bank selection
|
||||||
// 00 - bank 0, R0-R7 @ address 0x00-0x07
|
// 00 - bank 0, R0-R7 @ address 0x00-0x07
|
||||||
// 01 - bank 1, R0-R7 @ address 0x08-0x0F
|
// 01 - bank 1, R0-R7 @ address 0x08-0x0F
|
||||||
// 10 - bank 2, R0-R7 @ address 0x10-0x17
|
// 10 - bank 2, R0-R7 @ address 0x10-0x17
|
||||||
// 11 - bank 3, R0-R7 @ address 0x18-0x1F
|
// 11 - bank 3, R0-R7 @ address 0x18-0x1F
|
||||||
SBIT(OV, 0xD0, 2); // overflow flag
|
SBIT(OV, 0xD0, 2); // overflow flag
|
||||||
SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1
|
SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1
|
||||||
SBIT(P, 0xD0, 0); // ReadOnly: parity flag
|
SBIT(P, 0xD0, 0); // ReadOnly: parity flag
|
||||||
SFR(ACC, 0xE0); // accumulator
|
SFR(ACC, 0xE0); // accumulator
|
||||||
SFR(B, 0xF0); // general purpose register B
|
SFR(B, 0xF0); // general purpose register B
|
||||||
SFR(SP, 0x81); // stack pointer
|
SFR(SP, 0x81); // stack pointer
|
||||||
//sfr16 DPTR = 0x82; // DPTR pointer, little-endian
|
//sfr16 DPTR = 0x82; // DPTR pointer, little-endian
|
||||||
SFR(DPL, 0x82); // data pointer low
|
SFR(DPL, 0x82); // data pointer low
|
||||||
SFR(DPH, 0x83); // data pointer high
|
SFR(DPH, 0x83); // data pointer high
|
||||||
SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode
|
SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode
|
||||||
//sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID
|
//sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID
|
||||||
#define CHIP_ID SAFE_MOD
|
#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 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 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
|
#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
|
#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 */
|
/* 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),
|
#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)
|
// 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2)
|
||||||
#define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit
|
#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 GF1 0x08 // general purpose flag bit 1
|
||||||
#define GF0 0x04 // general purpose flag bit 0
|
#define GF0 0x04 // general purpose flag bit 0
|
||||||
#define PD 0x02 // power-down enable bit, auto clear by wake-up hardware
|
#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_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 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
|
#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/128 = 750KHz: 0 0 1
|
||||||
Fsys = Fpll/512 =187.5KHz: 0 0 0
|
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_BY_USB 0x80 // enable wake-up by USB event
|
||||||
#define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level
|
#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
|
#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_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_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
|
#define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level
|
||||||
SFR(RESET_KEEP, 0xFE); // value keeper during reset
|
SFR(RESET_KEEP, 0xFE); // value keeper during reset
|
||||||
SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536
|
SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536
|
||||||
|
|
||||||
/* Interrupt Registers */
|
/* Interrupt Registers */
|
||||||
SFR(IE, 0xA8); // interrupt enable
|
SFR(IE, 0xA8); // interrupt enable
|
||||||
SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0
|
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(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(ET2, 0xA8, 5); // enable timer2 interrupt
|
||||||
SBIT(ES, 0xA8, 4); // enable UART0 interrupt
|
SBIT(ES, 0xA8, 4); // enable UART0 interrupt
|
||||||
SBIT(ET1, 0xA8, 3); // enable timer1 interrupt
|
SBIT(ET1, 0xA8, 3); // enable timer1 interrupt
|
||||||
SBIT(EX1, 0xA8, 2); // enable external interrupt INT1
|
SBIT(EX1, 0xA8, 2); // enable external interrupt INT1
|
||||||
SBIT(ET0, 0xA8, 1); // enable timer0 interrupt
|
SBIT(ET0, 0xA8, 1); // enable timer0 interrupt
|
||||||
SBIT(EX0, 0xA8, 0); // enable external interrupt INT0
|
SBIT(EX0, 0xA8, 0); // enable external interrupt INT0
|
||||||
SFR(IP, 0xB8); // interrupt priority and current priority
|
SFR(IP, 0xB8); // interrupt priority and current priority
|
||||||
SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag
|
SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag
|
||||||
SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag
|
SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag
|
||||||
// PH_FLAG & PL_FLAG: current interrupt priority
|
// PH_FLAG & PL_FLAG: current interrupt priority
|
||||||
// 00 - no interrupt now
|
// 00 - no interrupt now
|
||||||
// 01 - low level priority interrupt action now
|
// 01 - low level priority interrupt action now
|
||||||
// 10 - high level priority interrupt action now
|
// 10 - high level priority interrupt action now
|
||||||
// 11 - unknown error
|
// 11 - unknown error
|
||||||
SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level
|
SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level
|
||||||
SBIT(PS, 0xB8, 4); // UART0 interrupt priority level
|
SBIT(PS, 0xB8, 4); // UART0 interrupt priority level
|
||||||
SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level
|
SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level
|
||||||
SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level
|
SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level
|
||||||
SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level
|
SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level
|
||||||
SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level
|
SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level
|
||||||
SFR(IE_EX, 0xE8); // extend interrupt enable
|
SFR(IE_EX, 0xE8); // extend interrupt enable
|
||||||
SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt
|
SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt
|
||||||
SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt
|
SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt
|
||||||
SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt
|
SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt
|
||||||
SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt
|
SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt
|
||||||
SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt
|
SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt
|
||||||
SBIT(IE_USB, 0xE8, 2); // enable USB interrupt
|
SBIT(IE_USB, 0xE8, 2); // enable USB interrupt
|
||||||
SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt
|
SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt
|
||||||
SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt
|
SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt
|
||||||
SFR(IP_EX, 0xE9); // extend interrupt priority
|
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_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_GPIO 0x40 // GPIO input interrupt priority level
|
||||||
#define bIP_PWMX 0x20 // PWM1/2 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_USB 0x04 // USB interrupt priority level
|
||||||
#define bIP_TKEY 0x02 // touch-key timer interrupt priority level
|
#define bIP_TKEY 0x02 // touch-key timer interrupt priority level
|
||||||
#define bIP_SPI0 0x01 // SPI0 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_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_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
|
#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
|
#define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge
|
||||||
|
|
||||||
/* FlashROM and Data-Flash Registers */
|
/* FlashROM and Data-Flash Registers */
|
||||||
SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian
|
SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian
|
||||||
SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM
|
SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM
|
||||||
SFR(ROM_ADDR_H, 0x85); // address high 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
|
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_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_DATA_H, 0x8F); // data high byte for flash-ROM writing
|
||||||
SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control
|
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_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
|
#define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command
|
||||||
//sfr ROM_STATUS = 0x86; // ReadOnly: flash-ROM status
|
//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
|
#define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command
|
||||||
|
|
||||||
/* Port Registers */
|
/* Port Registers */
|
||||||
SFR(P1, 0x90); // port 1 input & output
|
SFR(P1, 0x90); // port 1 input & output
|
||||||
SBIT(SCK, 0x90, 7); // serial clock for SPI0
|
SBIT(SCK, 0x90, 7); // serial clock for SPI0
|
||||||
SBIT(TXD1, 0x90, 7); // TXD output for UART1
|
SBIT(TXD1, 0x90, 7); // TXD output for UART1
|
||||||
SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key
|
SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key
|
||||||
SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0
|
SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0
|
||||||
SBIT(RXD1, 0x90, 6); // RXD input for UART1
|
SBIT(RXD1, 0x90, 6); // RXD input for UART1
|
||||||
SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key
|
SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key
|
||||||
SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0
|
SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0
|
||||||
SBIT(PWM1, 0x90, 5); // PWM output for PWM1
|
SBIT(PWM1, 0x90, 5); // PWM output for PWM1
|
||||||
SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key
|
SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key
|
||||||
SBIT(UCC2, 0x90, 5); // CC2 for USB type-C
|
SBIT(UCC2, 0x90, 5); // CC2 for USB type-C
|
||||||
SBIT(AIN2, 0x90, 5); // AIN2 for ADC
|
SBIT(AIN2, 0x90, 5); // AIN2 for ADC
|
||||||
SBIT(T2_, 0x90, 4); // alternate pin for T2
|
SBIT(T2_, 0x90, 4); // alternate pin for T2
|
||||||
SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1
|
SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1
|
||||||
SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0
|
SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0
|
||||||
SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key
|
SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key
|
||||||
SBIT(UCC1, 0x90, 4); // CC1 for USB type-C
|
SBIT(UCC1, 0x90, 4); // CC1 for USB type-C
|
||||||
SBIT(AIN1, 0x90, 4); // AIN1 for ADC
|
SBIT(AIN1, 0x90, 4); // AIN1 for ADC
|
||||||
SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0
|
SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0
|
||||||
SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0
|
SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0
|
||||||
SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture
|
SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture
|
||||||
SBIT(CAP2, 0x90, 1); // capture2 input for timer2
|
SBIT(CAP2, 0x90, 1); // capture2 input for timer2
|
||||||
SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key
|
SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key
|
||||||
SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C
|
SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C
|
||||||
SBIT(AIN0, 0x90, 1); // AIN0 for ADC
|
SBIT(AIN0, 0x90, 1); // AIN0 for ADC
|
||||||
SBIT(T2, 0x90, 0); // external count input
|
SBIT(T2, 0x90, 0); // external count input
|
||||||
SBIT(CAP1, 0x90, 0); // capture1 input for timer2
|
SBIT(CAP1, 0x90, 0); // capture1 input for timer2
|
||||||
SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key
|
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_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_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)
|
// Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3)
|
||||||
// 0 0: float input only, without pullup resistance
|
// 0 0: float input only, without pullup resistance
|
||||||
// 0 1: push-pull output, strong driving high level and low level
|
// 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 bAIN0 0x02 // AIN0 for ADC
|
||||||
#define bT2 0x01 // external count input or clock output for timer2
|
#define bT2 0x01 // external count input or clock output for timer2
|
||||||
#define bCAP1 bT2 // capture1 input for timer2
|
#define bCAP1 bT2 // capture1 input for timer2
|
||||||
SFR(P2, 0xA0); // port 2
|
SFR(P2, 0xA0); // port 2
|
||||||
SFR(P3, 0xB0); // port 3 input & output
|
SFR(P3, 0xB0); // port 3 input & output
|
||||||
SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input
|
SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input
|
||||||
SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input
|
SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input
|
||||||
SBIT(T1, 0xB0, 5); // external count input for timer1
|
SBIT(T1, 0xB0, 5); // external count input for timer1
|
||||||
SBIT(PWM2, 0xB0, 4); // PWM output for PWM2
|
SBIT(PWM2, 0xB0, 4); // PWM output for PWM2
|
||||||
SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1
|
SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1
|
||||||
SBIT(T0, 0xB0, 4); // external count input for timer0
|
SBIT(T0, 0xB0, 4); // external count input for timer0
|
||||||
SBIT(INT1, 0xB0, 3); // external interrupt 1 input
|
SBIT(INT1, 0xB0, 3); // external interrupt 1 input
|
||||||
SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1
|
SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1
|
||||||
SBIT(INT0, 0xB0, 2); // external interrupt 0 input
|
SBIT(INT0, 0xB0, 2); // external interrupt 0 input
|
||||||
SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C
|
SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C
|
||||||
SBIT(AIN3, 0xB0, 2); // AIN3 for ADC
|
SBIT(AIN3, 0xB0, 2); // AIN3 for ADC
|
||||||
SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2
|
SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2
|
||||||
SBIT(TXD, 0xB0, 1); // TXD output for UART0
|
SBIT(TXD, 0xB0, 1); // TXD output for UART0
|
||||||
SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1
|
SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1
|
||||||
SBIT(RXD, 0xB0, 0); // RXD input for UART0
|
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_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(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain
|
||||||
#define bUDM 0x80 // ReadOnly: pin UDM input
|
#define bUDM 0x80 // ReadOnly: pin UDM input
|
||||||
#define bUDP 0x40 // ReadOnly: pin UDP input
|
#define bUDP 0x40 // ReadOnly: pin UDP input
|
||||||
#define bT1 0x20 // external count input for timer1
|
#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 bTXD 0x02 // TXD output for UART0
|
||||||
#define bPWM1_ 0x01 // alternate pin for PWM1
|
#define bPWM1_ 0x01 // alternate pin for PWM1
|
||||||
#define bRXD 0x01 // RXD input for UART0
|
#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 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 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
|
#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 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 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
|
#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
|
SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting
|
||||||
#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status
|
#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmit status
|
||||||
#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status
|
#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receive status
|
||||||
#define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status
|
#define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status
|
||||||
#define GF2 0x08 // general purpose flag bit 2
|
#define GF2 0x08 // general purpose flag bit 2
|
||||||
#define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction
|
#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
|
#define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected
|
||||||
|
|
||||||
/* Timer0/1 Registers */
|
/* Timer0/1 Registers */
|
||||||
SFR(TCON, 0x88); // timer 0/1 control and external interrupt control
|
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(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
|
||||||
SBIT(TR1, 0x88, 6); // timer1 run enable
|
SBIT(TR1, 0x88, 6); // timer1 run enable
|
||||||
SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
|
SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine
|
||||||
SBIT(TR0, 0x88, 4); // timer0 run enable
|
SBIT(TR0, 0x88, 4); // timer0 run enable
|
||||||
SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine
|
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(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(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
|
SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action
|
||||||
SFR(TMOD, 0x89); // timer 0/1 mode
|
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_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_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
|
#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
|
// 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
|
// 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
|
// 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(TL0, 0x8A); // low byte of timer 0 count
|
||||||
SFR(TL1, 0x8B); // low byte of timer 1 count
|
SFR(TL1, 0x8B); // low byte of timer 1 count
|
||||||
SFR(TH0, 0x8C); // high byte of timer 0 count
|
SFR(TH0, 0x8C); // high byte of timer 0 count
|
||||||
SFR(TH1, 0x8D); // high byte of timer 1 count
|
SFR(TH1, 0x8D); // high byte of timer 1 count
|
||||||
|
|
||||||
/* UART0 Registers */
|
/* UART0 Registers */
|
||||||
SFR(SCON, 0x98); // UART0 control (serial port control)
|
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(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
|
SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable
|
||||||
// SM0 & SM1: UART0 mode
|
// SM0 & SM1: UART0 mode
|
||||||
// 00 - mode 0, shift Register, baud rate fixed at: Fsys/12
|
// 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
|
// 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
|
// 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
|
// 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
|
#define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode
|
||||||
SBIT(REN, 0x98, 4); // enable UART0 receiving
|
SBIT(REN, 0x98, 4); // enable UART0 receive
|
||||||
SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3
|
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(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(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 receiving, 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 receiving, writing for transmittal
|
SFR(SBUF, 0x99); // UART0 data buffer: reading for receive, writing for transmit
|
||||||
|
|
||||||
/* Timer2/Capture2 Registers */
|
/* Timer2/Capture2 Registers */
|
||||||
SFR(T2CON, 0xC8); // timer 2 control
|
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(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(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(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(RCLK, 0xC8, 5); // selection UART0 receive 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(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(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(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(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
|
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(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 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,
|
#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
|
// 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
|
// 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 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
|
#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
|
SFR16(RCAP2, 0xCA); // reload & capture value, little-endian
|
||||||
SFR(RCAP2L, 0xCA); // low byte of reload & capture value
|
SFR(RCAP2L, 0xCA); // low byte of reload & capture value
|
||||||
SFR(RCAP2H, 0xCB); // high byte of reload & capture value
|
SFR(RCAP2H, 0xCB); // high byte of reload & capture value
|
||||||
SFR16(T2COUNT, 0xCC); // counter, little-endian
|
SFR16(T2COUNT, 0xCC); // counter, little-endian
|
||||||
SFR(TL2, 0xCC); // low byte of timer 2 count
|
SFR(TL2, 0xCC); // low byte of timer 2 count
|
||||||
SFR(TH2, 0xCD); // high byte of timer 2 count
|
SFR(TH2, 0xCD); // high byte of timer 2 count
|
||||||
SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2
|
SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2
|
||||||
SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2
|
SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2
|
||||||
SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2
|
SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2
|
||||||
|
|
||||||
/* PWM1/2 Registers */
|
/* PWM1/2 Registers */
|
||||||
SFR(PWM_DATA2, 0x9B); // PWM data for PWM2
|
SFR(PWM_DATA2, 0x9B); // PWM data for PWM2
|
||||||
SFR(PWM_DATA1, 0x9C); // PWM data for PWM1
|
SFR(PWM_DATA1, 0x9C); // PWM data for PWM1
|
||||||
SFR(PWM_CTRL, 0x9D); // PWM 1/2 control
|
SFR(PWM_CTRL, 0x9D); // PWM 1/2 control
|
||||||
#define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end
|
#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 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
|
#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 bPWM2_OUT_EN 0x08 // PWM2 output enable
|
||||||
#define bPWM1_OUT_EN 0x04 // PWM1 output enable
|
#define bPWM1_OUT_EN 0x04 // PWM1 output enable
|
||||||
#define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2
|
#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 */
|
/* SPI0/Master0/Slave Registers */
|
||||||
SFR(SPI0_STAT, 0xF8); // SPI 0 status
|
SFR(SPI0_STAT, 0xF8); // SPI 0 status
|
||||||
SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0
|
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_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_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_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_FREE, 0xF8, 3); // ReadOnly: SPI0 free status
|
||||||
SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0
|
SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0
|
||||||
SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx 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_DATA, 0xF9); // FIFO data port: reading for receive, writing for transmit
|
||||||
SFR(SPI0_CTRL, 0xFA); // SPI 0 control
|
SFR(SPI0_CTRL, 0xFA); // SPI 0 control
|
||||||
#define bS0_MISO_OE 0x80 // SPI0 MISO output enable
|
#define bS0_MISO_OE 0x80 // SPI0 MISO output enable
|
||||||
#define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable
|
#define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable
|
||||||
#define bS0_SCK_OE 0x20 // SPI0 SCK 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_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_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
|
#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
|
//sfr SPI0_S_PRE = 0xFB; // preset value for SPI slave
|
||||||
#define SPI0_S_PRE SPI0_CK_SE
|
#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_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_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
|
#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
|
#define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection
|
||||||
|
|
||||||
/* UART1 Registers */
|
/* UART1 Registers */
|
||||||
SFR(SCON1, 0xC0); // UART1 control (serial port control)
|
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(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(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(U1REN, 0xC0, 4); // enable UART1 receive
|
||||||
SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode
|
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(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(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 receiving, 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 receiving, writing for transmittal
|
SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receive, writing for transmit
|
||||||
SFR(SBAUD1, 0xC2); // UART1 baud rate setting
|
SFR(SBAUD1, 0xC2); // UART1 baud rate setting
|
||||||
|
|
||||||
/* ADC and comparator Registers */
|
/* ADC and comparator Registers */
|
||||||
SFR(ADC_CTRL, 0x80); // ADC control
|
SFR(ADC_CTRL, 0x80); // ADC control
|
||||||
SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input
|
SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input
|
||||||
SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear
|
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_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(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(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_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit
|
||||||
SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit
|
SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit
|
||||||
// ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection
|
// ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection
|
||||||
// 00: AIN0(P1.1)
|
// 00: AIN0(P1.1)
|
||||||
// 01: AIN1(P1.4)
|
// 01: AIN1(P1.4)
|
||||||
// 10: AIN2(P1.5)
|
// 10: AIN2(P1.5)
|
||||||
// 11: AIN3(P3.2)
|
// 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 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 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
|
#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 */
|
/* 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_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_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS
|
||||||
#define bTKC_CHAN2 0x04 // touch-key channel selection high bit
|
#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)
|
// 101: TIN4(P1.6)
|
||||||
// 110: TIN5(P1.7)
|
// 110: TIN5(P1.7)
|
||||||
// 111: enable touch-key but disable all channel
|
// 111: enable touch-key but disable all channel
|
||||||
SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian
|
SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian
|
||||||
SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data
|
SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data
|
||||||
SFR(TKEY_DATH, 0xC5); // ReadOnly: high 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
|
#define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid
|
||||||
|
|
||||||
/* USB/Host/Device Registers */
|
/* 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 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_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
|
#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
|
// 01: enable 56K pullup resistance for default USB power
|
||||||
// 10: enable 22K pullup resistance for 1.5A USB power
|
// 10: enable 22K pullup resistance for 1.5A USB power
|
||||||
// 11: enable 10K pullup resistance for 3A 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_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_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
||||||
#define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM 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_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_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
|
#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
|
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_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 transmittal (IN): 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_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_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 receiving (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 receiving (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_ACK 0x00
|
||||||
#define UEP_R_RES_TOUT 0x04
|
#define UEP_R_RES_TOUT 0x04
|
||||||
#define UEP_R_RES_NAK 0x08
|
#define UEP_R_RES_NAK 0x08
|
||||||
#define UEP_R_RES_STALL 0x0C
|
#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)
|
// 00: ACK (ready)
|
||||||
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
|
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
|
||||||
// 10: NAK (busy)
|
// 10: NAK (busy)
|
||||||
// 11: STALL (error)
|
// 11: STALL (error)
|
||||||
#define bUEP_T_RES1 0x02 // handshake response type high bit 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 transmittal (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 transmittal (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_ACK 0x00
|
||||||
#define UEP_T_RES_TOUT 0x01
|
#define UEP_T_RES_TOUT 0x01
|
||||||
#define UEP_T_RES_NAK 0x02
|
#define UEP_T_RES_NAK 0x02
|
||||||
#define UEP_T_RES_STALL 0x03
|
#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)
|
// 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
|
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
|
||||||
// 10: NAK (busy)
|
// 10: NAK (busy)
|
||||||
// 11: STALL (error)
|
// 11: STALL (error)
|
||||||
SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length
|
SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmit length
|
||||||
SFR(UEP2_CTRL, 0xD4); // endpoint 2 control
|
SFR(UEP2_CTRL, 0xD4); // endpoint 2 control
|
||||||
SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length
|
SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmit length
|
||||||
SFR(UEP3_CTRL, 0xD6); // endpoint 3 control
|
SFR(UEP3_CTRL, 0xD6); // endpoint 3 control
|
||||||
SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length
|
SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmit length
|
||||||
SFR(USB_INT_FG, 0xD8); // USB interrupt flag
|
SFR(USB_INT_FG, 0xD8); // USB interrupt flag
|
||||||
SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received
|
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_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(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_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_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_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_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_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
|
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(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_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_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
|
#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
|
// 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_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
|
#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_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_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_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_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status
|
||||||
#define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend 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_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
|
#define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host
|
||||||
SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length
|
SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receive length
|
||||||
SFR(UEP0_CTRL, 0xDC); // endpoint 0 control
|
SFR(UEP0_CTRL, 0xDC); // endpoint 0 control
|
||||||
SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length
|
SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmit length
|
||||||
SFR(UEP4_CTRL, 0xDE); // endpoint 4 control
|
SFR(UEP4_CTRL, 0xDE); // endpoint 4 control
|
||||||
SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length
|
SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmit length
|
||||||
SFR(USB_INT_EN, 0xE1); // USB interrupt enable
|
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_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_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
|
||||||
#define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
|
#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_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_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
|
#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_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_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
|
#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_RESET_SIE 0x04 // force reset USB SIE, need software clear
|
||||||
#define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB
|
#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
|
#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 bUDA_GP_BIT 0x80 // general purpose bit
|
||||||
#define MASK_USB_ADDR 0x7F // bit mask for USB device address
|
#define MASK_USB_ADDR 0x7F // bit mask for USB device address
|
||||||
SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian
|
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_L, 0xE4); // endpoint 2 buffer start address low byte
|
||||||
SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte
|
SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte
|
||||||
SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian
|
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_L, 0xE6); // endpoint 3 buffer start address low byte
|
||||||
SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte
|
SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte
|
||||||
SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode
|
SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode
|
||||||
#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
|
#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receive (OUT)
|
||||||
#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
|
#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmit (IN)
|
||||||
#define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
|
#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
|
// 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
|
// 0 0 x: disable endpoint and disable buffer
|
||||||
// 1 0 0: 64 bytes buffer for receiving (OUT endpoint)
|
// 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 receiving (OUT endpoint), total=128bytes
|
// 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 transmittal (IN endpoint)
|
// 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 transmittal (IN endpoint), total=128bytes
|
// 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 receiving (OUT endpoint) + 64 bytes buffer for transmittal (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 receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes
|
// 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 receiving (OUT)
|
#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receive (OUT)
|
||||||
#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
|
#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
|
// 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)
|
// 0 0: single 64 bytes buffer for endpoint 0 receive & transmit (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
|
// 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 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN 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 receiving & transmittal (OUT & IN endpoint)
|
// 1 1: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint)
|
||||||
// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes
|
// + 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
|
SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode
|
||||||
#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
|
#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receive (OUT)
|
||||||
#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
|
#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmit (IN)
|
||||||
#define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
|
#define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
|
||||||
#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
|
#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receive (OUT)
|
||||||
#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
|
#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmit (IN)
|
||||||
#define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
|
#define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
|
||||||
SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian
|
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_L, 0xEC); // endpoint 0 buffer start address low byte
|
||||||
SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte
|
SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte
|
||||||
SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian
|
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_L, 0xEE); // endpoint 1 buffer start address low byte
|
||||||
SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte
|
SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte
|
||||||
//sfr UH_SETUP = 0xD2; // host aux setup
|
//sfr UH_SETUP = 0xD2; // host aux setup
|
||||||
#define UH_SETUP UEP1_CTRL
|
#define UH_SETUP UEP1_CTRL
|
||||||
#define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub
|
#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
|
#define bUH_SOF_EN 0x40 // USB host automatic SOF enable
|
||||||
//sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control
|
//sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control
|
||||||
#define UH_RX_CTRL UEP2_CTRL
|
#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_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
|
//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 UH_EP_PID UEP2_T_LEN
|
||||||
#define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer
|
#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
|
#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 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_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
|
#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 transmittal endpoint transmittal length
|
//sfr UH_TX_LEN = 0xD7; // host transmit endpoint transmit length
|
||||||
#define UH_TX_LEN UEP3_T_LEN
|
#define UH_TX_LEN UEP3_T_LEN
|
||||||
//sfr UH_EP_MOD = 0xEB; // host endpoint mode
|
//sfr UH_EP_MOD = 0xEB; // host endpoint mode
|
||||||
#define UH_EP_MOD UEP2_3_MOD
|
#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
|
#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
|
// 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
|
// 0 x: disable endpoint and disable buffer
|
||||||
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
|
// 1 0: 64 bytes buffer for transmit (OUT endpoint)
|
||||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
|
// 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 receiving
|
#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
|
#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
|
// 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
|
// 0 x: disable endpoint and disable buffer
|
||||||
// 1 0: 64 bytes buffer for receiving (IN endpoint)
|
// 1 0: 64 bytes buffer for receive (IN endpoint)
|
||||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
|
// 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
|
//sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian
|
||||||
#define UH_RX_DMA UEP2_DMA
|
#define UH_RX_DMA UEP2_DMA
|
||||||
//sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte
|
//sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte
|
||||||
|
@ -11,6 +11,8 @@ Header file for CH554 microcontrollers.
|
|||||||
#ifndef __USB_DEF__
|
#ifndef __USB_DEF__
|
||||||
#define __USB_DEF__
|
#define __USB_DEF__
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
/*----- USB constant and structure define --------------------------------*/
|
/*----- USB constant and structure define --------------------------------*/
|
||||||
|
|
||||||
/* USB PID */
|
/* USB PID */
|
||||||
@ -53,34 +55,41 @@ Header file for CH554 microcontrollers.
|
|||||||
#define HUB_SET_DESCRIPTOR 0x07
|
#define HUB_SET_DESCRIPTOR 0x07
|
||||||
#endif
|
#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 */
|
/* Bit define for USB request type */
|
||||||
#ifndef USB_REQ_TYP_MASK
|
#ifndef USB_REQ_TYPE_MASK
|
||||||
#define USB_REQ_TYP_IN 0x80 /* control IN, device to host */
|
#define USB_REQ_TYPE_IN 0x80 /* Control IN, device to host */
|
||||||
#define USB_REQ_TYP_OUT 0x00 /* control OUT, host to device */
|
#define USB_REQ_TYPE_OUT 0x00 /* Control OUT, host to device */
|
||||||
#define USB_REQ_TYP_READ 0x80 /* control read, device to host */
|
#define USB_REQ_TYPE_READ 0x80 /* Control read, device to host */
|
||||||
#define USB_REQ_TYP_WRITE 0x00 /* control write, host to device */
|
#define USB_REQ_TYPE_WRITE 0x00 /* Control write, host to device */
|
||||||
#define USB_REQ_TYP_MASK 0x60 /* bit mask of request type */
|
#define USB_REQ_TYPE_MASK 0x60 /* Bit mask of request type */
|
||||||
#define USB_REQ_TYP_STANDARD 0x00
|
#define USB_REQ_TYPE_STANDARD 0x00
|
||||||
#define USB_REQ_TYP_CLASS 0x20
|
#define USB_REQ_TYPE_CLASS 0x20
|
||||||
#define USB_REQ_TYP_VENDOR 0x40
|
#define USB_REQ_TYPE_VENDOR 0x40
|
||||||
#define USB_REQ_TYP_RESERVED 0x60
|
#define USB_REQ_TYPE_RESERVED 0x60
|
||||||
#define USB_REQ_RECIP_MASK 0x1F /* bit mask of request recipient */
|
#define USB_REQ_RECIP_MASK 0x1F /* Bit mask of request recipient */
|
||||||
#define USB_REQ_RECIP_DEVICE 0x00
|
#define USB_REQ_RECIP_DEVICE 0x00
|
||||||
#define USB_REQ_RECIP_INTERF 0x01
|
#define USB_REQ_RECIP_INTERF 0x01
|
||||||
#define USB_REQ_RECIP_ENDP 0x02
|
#define USB_REQ_RECIP_ENDP 0x02
|
||||||
#define USB_REQ_RECIP_OTHER 0x03
|
#define USB_REQ_RECIP_OTHER 0x03
|
||||||
#endif
|
#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 */
|
/* USB request type for hub class request */
|
||||||
#ifndef HUB_GET_HUB_DESCRIPTOR
|
#ifndef HUB_GET_HUB_DESCRIPTOR
|
||||||
#define HUB_CLEAR_HUB_FEATURE 0x20
|
#define HUB_CLEAR_HUB_FEATURE 0x20
|
||||||
@ -96,95 +105,129 @@ Header file for CH554 microcontrollers.
|
|||||||
|
|
||||||
/* Hub class feature selectors */
|
/* Hub class feature selectors */
|
||||||
#ifndef HUB_PORT_RESET
|
#ifndef HUB_PORT_RESET
|
||||||
#define HUB_C_HUB_LOCAL_POWER 0
|
#define HUB_C_HUB_LOCAL_POWER 0
|
||||||
#define HUB_C_HUB_OVER_CURRENT 1
|
#define HUB_C_HUB_OVER_CURRENT 1
|
||||||
#define HUB_PORT_CONNECTION 0
|
#define HUB_PORT_CONNECTION 0
|
||||||
#define HUB_PORT_ENABLE 1
|
#define HUB_PORT_ENABLE 1
|
||||||
#define HUB_PORT_SUSPEND 2
|
#define HUB_PORT_SUSPEND 2
|
||||||
#define HUB_PORT_OVER_CURRENT 3
|
#define HUB_PORT_OVER_CURRENT 3
|
||||||
#define HUB_PORT_RESET 4
|
#define HUB_PORT_RESET 4
|
||||||
#define HUB_PORT_POWER 8
|
#define HUB_PORT_POWER 8
|
||||||
#define HUB_PORT_LOW_SPEED 9
|
#define HUB_PORT_LOW_SPEED 9
|
||||||
#define HUB_C_PORT_CONNECTION 16
|
#define HUB_C_PORT_CONNECTION 16
|
||||||
#define HUB_C_PORT_ENABLE 17
|
#define HUB_C_PORT_ENABLE 17
|
||||||
#define HUB_C_PORT_SUSPEND 18
|
#define HUB_C_PORT_SUSPEND 18
|
||||||
#define HUB_C_PORT_OVER_CURRENT 19
|
#define HUB_C_PORT_OVER_CURRENT 19
|
||||||
#define HUB_C_PORT_RESET 20
|
#define HUB_C_PORT_RESET 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* USB descriptor type */
|
/* USB descriptor type */
|
||||||
#ifndef USB_DESCR_TYP_DEVICE
|
#ifndef USB_DESC_TYPE_DEVICE
|
||||||
#define USB_DESCR_TYP_DEVICE 0x01
|
#define USB_DESC_TYPE_DEVICE 0x01 // USB 1.1
|
||||||
#define USB_DESCR_TYP_CONFIG 0x02
|
#define USB_DESC_TYPE_CONFIGURATION 0x02 // USB 1.1
|
||||||
#define USB_DESCR_TYP_STRING 0x03
|
#define USB_DESC_TYPE_STRING 0x03 // USB 1.1
|
||||||
#define USB_DESCR_TYP_INTERF 0x04
|
#define USB_DESC_TYPE_INTERFACE 0x04 // USB 1.1
|
||||||
#define USB_DESCR_TYP_ENDP 0x05
|
#define USB_DESC_TYPE_ENDPOINT 0x05 // USB 1.1
|
||||||
#define USB_DESCR_TYP_QUALIF 0x06
|
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 // USB 2.0
|
||||||
#define USB_DESCR_TYP_SPEED 0x07
|
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 // USB 2.0
|
||||||
#define USB_DESCR_TYP_OTG 0x09
|
#define USB_DESC_TYPE_INTERFACE_POWER 0x08 // USB 2.0
|
||||||
#define USB_DESCR_TYP_HID 0x21
|
#define USB_DESC_TYPE_OTG 0x09 // USB 2.0
|
||||||
#define USB_DESCR_TYP_REPORT 0x22
|
#define USB_DESC_TYPE_DEBUG 0x0A // USB 2.0
|
||||||
#define USB_DESCR_TYP_PHYSIC 0x23
|
#define USB_DESC_TYPE_INTERFACE_ASSOCIATION 0x0B // USB 2.0
|
||||||
#define USB_DESCR_TYP_CS_INTF 0x24
|
#define USB_DESC_TYPE_BOS 0x0F // USB 3.x (Binary Object Store)
|
||||||
#define USB_DESCR_TYP_CS_ENDP 0x25
|
#define USB_DESC_TYPE_DEVICE_CAPABILITY 0x10 // USB 3.x
|
||||||
#define USB_DESCR_TYP_HUB 0x29
|
#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
|
#endif
|
||||||
|
|
||||||
/* USB device class */
|
/* USB device class */
|
||||||
#ifndef USB_DEV_CLASS_HUB
|
#ifndef USB_DEV_CLASS
|
||||||
#define USB_DEV_CLASS_RESERVED 0x00
|
// Descriptor Usage; Description ; Examples
|
||||||
#define USB_DEV_CLASS_AUDIO 0x01
|
#define USB_DEV_CLASS_RESERVED 0x00 // Device ; Unspecified ; Device class is unspecified, interface descriptors are used to determine needed drivers
|
||||||
#define USB_DEV_CLASS_COMMUNIC 0x02
|
#define USB_DEV_CLASS_AUDIO 0x01 // Interface ; Audio ; Speaker, microphone, sound card, MIDI
|
||||||
#define USB_DEV_CLASS_HID 0x03
|
#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_MONITOR 0x04
|
#define USB_DEV_CLASS_HID 0x03 // Interface ; Human interface device (HID) ; Keyboard, mouse, joystick
|
||||||
#define USB_DEV_CLASS_PHYSIC_IF 0x05
|
#define USB_DEV_CLASS_PHYSICAL 0x05 // Interface ; Physical interface device (PID) ; Force feedback joystick
|
||||||
#define USB_DEV_CLASS_POWER 0x06
|
#define USB_DEV_CLASS_IMAGE 0x06 // Interface ; Media (PTP/MTP) ; Scanner, Camera
|
||||||
#define USB_DEV_CLASS_PRINTER 0x07
|
#define USB_DEV_CLASS_PRINTER 0x07 // Interface ; Printer ; Laser printer, inkjet printer, CNC machine
|
||||||
#define USB_DEV_CLASS_STORAGE 0x08
|
#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
|
#define USB_DEV_CLASS_HUB 0x09 // Device ; USB hub ; High speed USB hub
|
||||||
#define USB_DEV_CLASS_VEN_SPEC 0xFF
|
#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
|
#endif
|
||||||
|
|
||||||
/* USB endpoint type and attributes */
|
/* USB endpoint type and attributes */
|
||||||
#ifndef USB_ENDP_TYPE_MASK
|
#ifndef USB_EP_TYPE_MASK
|
||||||
#define USB_ENDP_DIR_MASK 0x80
|
#define USB_EP_TYPE_CONTROL 0x00
|
||||||
#define USB_ENDP_ADDR_MASK 0x0F
|
#define USB_EP_TYPE_ISOCHRONOUS 0x01
|
||||||
#define USB_ENDP_TYPE_MASK 0x03
|
#define USB_EP_TYPE_BULK 0x02
|
||||||
#define USB_ENDP_TYPE_CTRL 0x00
|
#define USB_EP_TYPE_INTERRUPT 0x03
|
||||||
#define USB_ENDP_TYPE_ISOCH 0x01
|
|
||||||
#define USB_ENDP_TYPE_BULK 0x02
|
#define USB_EP_DIR_MASK 0x80
|
||||||
#define USB_ENDP_TYPE_INTER 0x03
|
#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
|
#endif
|
||||||
|
|
||||||
#ifndef USB_DEVICE_ADDR
|
#ifndef USB_DEVICE_ADDR
|
||||||
#define USB_DEVICE_ADDR 0x02 /* 默认的USB设备地址 */
|
#define USB_DEVICE_ADDR 0x02
|
||||||
#endif
|
#endif
|
||||||
#ifndef DEFAULT_ENDP0_SIZE
|
#ifndef DEFAULT_EP0_SIZE
|
||||||
#define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */
|
#define DEFAULT_EP0_SIZE 64 /* Default maximum packet size for Endpoint 0 */
|
||||||
#endif
|
#endif
|
||||||
#ifndef DEFAULT_ENDP1_SIZE
|
#ifndef DEFAULT_EP1_SIZE
|
||||||
#define DEFAULT_ENDP1_SIZE 8 /* default maximum packet size for endpoint 1 */
|
#define DEFAULT_EP1_SIZE 8 /* Default maximum packet size for Endpoint 1 */
|
||||||
#endif
|
#endif
|
||||||
#ifndef MAX_PACKET_SIZE
|
#ifndef MAX_PACKET_SIZE
|
||||||
#define MAX_PACKET_SIZE 64 /* maximum packet size */
|
#define MAX_PACKET_SIZE 64 /* Maximum packet size */
|
||||||
#endif
|
#endif
|
||||||
#ifndef USB_BO_CBW_SIZE
|
#ifndef USB_BO_CBW_SIZE
|
||||||
#define USB_BO_CBW_SIZE 0x1F /* 命令块CBW的总长度 */
|
#define USB_BO_CBW_SIZE 0x1F
|
||||||
#define USB_BO_CSW_SIZE 0x0D /* 命令状态块CSW的总长度 */
|
#define USB_BO_CSW_SIZE 0x0D
|
||||||
#endif
|
#endif
|
||||||
#ifndef USB_BO_CBW_SIG0
|
#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_SIG1 0x53
|
||||||
#define USB_BO_CBW_SIG2 0x42
|
#define USB_BO_CBW_SIG2 0x42
|
||||||
#define USB_BO_CBW_SIG3 0x43
|
#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_SIG1 0x53
|
||||||
#define USB_BO_CSW_SIG2 0x42
|
#define USB_BO_CSW_SIG2 0x42
|
||||||
#define USB_BO_CSW_SIG3 0x53
|
#define USB_BO_CSW_SIG3 0x53
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct _USB_SETUP_REQ {
|
typedef struct _USB_SETUP_REQ {
|
||||||
uint8_t bRequestType;
|
uint8_t bmRequestType;
|
||||||
uint8_t bRequest;
|
uint8_t bRequest;
|
||||||
uint8_t wValueL;
|
uint8_t wValueL;
|
||||||
uint8_t wValueH;
|
uint8_t wValueH;
|
||||||
@ -194,7 +237,7 @@ typedef struct _USB_SETUP_REQ {
|
|||||||
uint8_t wLengthH;
|
uint8_t wLengthH;
|
||||||
} USB_SETUP_REQ, *PUSB_SETUP_REQ;
|
} 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 {
|
typedef struct _USB_DEVICE_DESCR {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
@ -217,7 +260,7 @@ typedef struct _USB_DEVICE_DESCR {
|
|||||||
uint8_t bNumConfigurations;
|
uint8_t bNumConfigurations;
|
||||||
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
|
} 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 {
|
typedef struct _USB_CONFIG_DESCR {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
@ -231,7 +274,7 @@ typedef struct _USB_CONFIG_DESCR {
|
|||||||
uint8_t MaxPower;
|
uint8_t MaxPower;
|
||||||
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
|
} 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 {
|
typedef struct _USB_INTERF_DESCR {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
@ -245,7 +288,7 @@ typedef struct _USB_INTERF_DESCR {
|
|||||||
uint8_t iInterface;
|
uint8_t iInterface;
|
||||||
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
|
} 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 {
|
typedef struct _USB_ENDPOINT_DESCR {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
@ -257,7 +300,7 @@ typedef struct _USB_ENDPOINT_DESCR {
|
|||||||
uint8_t bInterval;
|
uint8_t bInterval;
|
||||||
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
|
} 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 {
|
typedef struct _USB_CONFIG_DESCR_LONG {
|
||||||
USB_CFG_DESCR cfg_descr;
|
USB_CFG_DESCR cfg_descr;
|
||||||
@ -265,7 +308,7 @@ typedef struct _USB_CONFIG_DESCR_LONG {
|
|||||||
USB_ENDP_DESCR endp_descr[1];
|
USB_ENDP_DESCR endp_descr[1];
|
||||||
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
|
} 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 {
|
typedef struct _USB_HUB_DESCR {
|
||||||
uint8_t bDescLength;
|
uint8_t bDescLength;
|
||||||
@ -279,7 +322,7 @@ typedef struct _USB_HUB_DESCR {
|
|||||||
uint8_t PortPwrCtrlMask;
|
uint8_t PortPwrCtrlMask;
|
||||||
} USB_HUB_DESCR, *PUSB_HUB_DESCR;
|
} 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 {
|
typedef struct _USB_HID_DESCR {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
@ -293,9 +336,9 @@ typedef struct _USB_HID_DESCR {
|
|||||||
uint8_t wDescriptorLengthH;
|
uint8_t wDescriptorLengthH;
|
||||||
} USB_HID_DESCR, *PUSB_HID_DESCR;
|
} 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_Sig0;
|
||||||
uint8_t mCBW_Sig1;
|
uint8_t mCBW_Sig1;
|
||||||
uint8_t mCBW_Sig2;
|
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_DataLen0;
|
||||||
uint8_t mCBW_DataLen1;
|
uint8_t mCBW_DataLen1;
|
||||||
uint8_t mCBW_DataLen2;
|
uint8_t mCBW_DataLen2;
|
||||||
uint8_t mCBW_DataLen3; /* uppest byte of data length, always is 0 */
|
uint8_t mCBW_DataLen3; /* MSB byte of data length, always is 0 */
|
||||||
uint8_t mCBW_Flag; /* transfer direction and etc. */
|
uint8_t mCBW_Flag; /* Transfer direction and etc. */
|
||||||
uint8_t mCBW_LUN;
|
uint8_t mCBW_LUN;
|
||||||
uint8_t mCBW_CB_Len; /* length of command block */
|
uint8_t mCBW_CB_Len; /* Length of command block */
|
||||||
uint8_t mCBW_CB_Buf[16]; /* command block buffer */
|
uint8_t mCBW_CB_Buf[16]; /* Command block buffer */
|
||||||
} UDISK_BOC_CBW, *PUDISK_BOC_CBW;
|
} 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_Sig0;
|
||||||
uint8_t mCSW_Sig1;
|
uint8_t mCSW_Sig1;
|
||||||
uint8_t mCSW_Sig2;
|
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_Tag1;
|
||||||
uint8_t mCSW_Tag2;
|
uint8_t mCSW_Tag2;
|
||||||
uint8_t mCSW_Tag3;
|
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_Residue1;
|
||||||
uint8_t mCSW_Residue2;
|
uint8_t mCSW_Residue2;
|
||||||
uint8_t mCSW_Residue3; /* uppest byte of remainder length, always is 0 */
|
uint8_t mCSW_Residue3; /* MSB byte of remainder length, always is 0 */
|
||||||
uint8_t mCSW_Status; /* return: result status */
|
uint8_t mCSW_Status; /* Return: result status */
|
||||||
} UDISK_BOC_CSW, *PUDISK_BOC_CSW;
|
} 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__
|
#endif // __USB_DEF__
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
* Version : V1.0
|
* Version : V1.0
|
||||||
* Date : 2017/01/20
|
* Date : 2017/01/20
|
||||||
* Description : CH554 DEBUG Interface
|
* Description : CH554 DEBUG Interface
|
||||||
CH554 main frequency modification, delay function definition
|
CH554 main frequency modification, delay function definition
|
||||||
Serial port 0 and serial port 1 initialization
|
Serial port 0 and serial port 1 initialization
|
||||||
Serial port 0 and serial port 1 transceiver subfunctions
|
Serial port 0 and serial port 1 transceiver subfunctions
|
||||||
Watchdog initialization
|
Watchdog initialization
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -17,42 +17,40 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : CfgFsys( )
|
* Function Name : CfgFsys( )
|
||||||
* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed
|
* 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:
|
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
|
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 = 0x55;
|
||||||
SAFE_MOD = 0xAA;
|
SAFE_MOD = 0xAA;
|
||||||
// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal
|
// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal
|
||||||
// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal
|
// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal
|
||||||
|
|
||||||
#if FREQ_SYS == 32000000
|
#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
|
#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
|
#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
|
#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
|
#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
|
#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
|
#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
|
#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
|
#else
|
||||||
#warning FREQ_SYS invalid or not set
|
#warning FREQ_SYS invalid or not set
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SAFE_MOD = 0x00;
|
SAFE_MOD = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : mDelayus(UNIT16 n)
|
* Function Name : mDelayus(UNIT16 n)
|
||||||
* Description : us delay function
|
* Description : us delay function
|
||||||
@ -60,55 +58,55 @@ void CfgFsys( )
|
|||||||
* Output : None
|
* Output : None
|
||||||
* Return : None
|
* Return : None
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void mDelayuS( uint16_t n ) // Delay in uS
|
void mDelayuS(uint16_t n) // Delay in uS
|
||||||
{
|
{
|
||||||
#ifdef FREQ_SYS
|
#ifdef FREQ_SYS
|
||||||
#if FREQ_SYS <= 6000000
|
#if FREQ_SYS <= 6000000
|
||||||
n >>= 2;
|
n >>= 2;
|
||||||
|
#endif
|
||||||
|
#if FREQ_SYS <= 3000000
|
||||||
|
n >>= 2;
|
||||||
|
#endif
|
||||||
|
#if FREQ_SYS <= 750000
|
||||||
|
n >>= 4;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if FREQ_SYS <= 3000000
|
while (n) { // Total = 12~13 Fsys cycles, 1uS @Fsys=12MHz
|
||||||
n >>= 2;
|
++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
|
#endif
|
||||||
#if FREQ_SYS <= 750000
|
--n;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -118,17 +116,17 @@ void mDelayuS( uint16_t n ) // Delay in uS
|
|||||||
* Output : None
|
* Output : None
|
||||||
* Return : None
|
* Return : None
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void mDelaymS( uint16_t n ) // Delay in mS
|
void mDelaymS(uint16_t n) // Delay in mS
|
||||||
{
|
{
|
||||||
while ( n ) {
|
while (n) {
|
||||||
#ifdef DELAY_MS_HW
|
#ifdef DELAY_MS_HW
|
||||||
while ( ( TKEY_CTRL & bTKC_IF ) == 0 );
|
while ( ( TKEY_CTRL & bTKC_IF ) == 0 );
|
||||||
while ( TKEY_CTRL & bTKC_IF );
|
while ( TKEY_CTRL & bTKC_IF );
|
||||||
#else
|
#else
|
||||||
mDelayuS( 1000 );
|
mDelayuS(1000);
|
||||||
#endif
|
#endif
|
||||||
-- n;
|
--n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SDCC < 370
|
#if SDCC < 370
|
||||||
@ -139,7 +137,8 @@ void putchar(char c)
|
|||||||
SBUF = c;
|
SBUF = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
char getchar() {
|
char getchar(void)
|
||||||
|
{
|
||||||
while(!RI); /* assumes UART is initialized */
|
while(!RI); /* assumes UART is initialized */
|
||||||
RI = 0;
|
RI = 0;
|
||||||
return SBUF;
|
return SBUF;
|
||||||
@ -154,7 +153,8 @@ int putchar(int c)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getchar() {
|
int getchar(void)
|
||||||
|
{
|
||||||
while(!RI); /* assumes UART is initialized */
|
while(!RI); /* assumes UART is initialized */
|
||||||
RI = 0;
|
RI = 0;
|
||||||
return SBUF;
|
return SBUF;
|
||||||
@ -162,42 +162,106 @@ int getchar() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set pin p1.4 and p1.5 to GPIO output mode.
|
// Set pin p1.4 and p1.5 to GPIO output mode.
|
||||||
void gpio_init(){
|
void gpio_init()
|
||||||
// p1.4
|
{
|
||||||
P1_MOD_OC &= ~0x10;
|
// p1.4
|
||||||
P1_DIR_PU |= 0x10;
|
P1_MOD_OC &= ~0x10;
|
||||||
|
P1_DIR_PU |= 0x10;
|
||||||
// p1.5
|
|
||||||
P1_MOD_OC &= ~0x20;
|
|
||||||
P1_DIR_PU |= 0x20;
|
|
||||||
|
|
||||||
|
// p1.5
|
||||||
|
P1_MOD_OC &= ~0x20;
|
||||||
|
P1_DIR_PU |= 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_set(uint8_t pin) {
|
void gpio_set(uint8_t pin)
|
||||||
switch (pin)
|
{
|
||||||
{
|
switch (pin) {
|
||||||
case 0x10: // p1.4
|
case 0x10: // p1.4
|
||||||
P1 |= 0x10;
|
P1 |= 0x10;
|
||||||
break;
|
break;
|
||||||
case 0x20: // p1.5
|
case 0x20: // p1.5
|
||||||
P1 |= 0x20;
|
P1 |= 0x20;
|
||||||
break;
|
break;
|
||||||
default: // do nothing, unsupported pin.
|
default: // do nothing, unsupported pin.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpio_unset(uint8_t pin) {
|
void gpio_unset(uint8_t pin)
|
||||||
switch (pin)
|
{
|
||||||
{
|
switch (pin) {
|
||||||
case 0x10:
|
case 0x10:
|
||||||
P1 &= ~0x10;
|
P1 &= ~0x10;
|
||||||
break;
|
break;
|
||||||
case 0x20:
|
case 0x20:
|
||||||
P1 &= ~0x20;
|
P1 &= ~0x20;
|
||||||
break;
|
break;
|
||||||
default: // do nothing, unsupported pin.
|
default: // do nothing, unsupported pin.
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
|
@ -1,138 +1,221 @@
|
|||||||
|
#ifndef __DEBUG_H__
|
||||||
|
#define __DEBUG_H__
|
||||||
|
|
||||||
/* Debug */
|
/* Debug */
|
||||||
/* Provide printf subroutine and delay function */
|
/* Provide printf subroutine and delay function */
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifndef UART0_BAUD
|
#include "ch554.h"
|
||||||
#define UART0_BAUD 9600
|
|
||||||
|
// 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
|
#endif
|
||||||
|
|
||||||
#ifndef UART1_BAUD
|
#ifndef UART1_BAUD
|
||||||
#define UART1_BAUD 9600
|
#define UART1_BAUD 500000
|
||||||
|
//#define UART1_BAUD 1000000
|
||||||
#endif
|
#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
|
// Set pin p1.4 and p1.5 to GPIO output mode.
|
||||||
void mDelaymS (uint16_t n); // Delay in mS
|
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()
|
* Function Name : CH554UART0Alter()
|
||||||
* Description : CH554 serial port 0 pin mapping, serial port mapping to P0.2 and P0.3
|
* Description : Set the alternate pin mappings for UART0 (RX on P1.2, TX on P1.3)
|
||||||
|
*******************************************************************************/
|
||||||
*******************************************************************************/
|
|
||||||
inline void CH554UART0Alter()
|
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()
|
* 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
|
* Description : CH554 UART0 is initialized
|
||||||
As a baud rate generator
|
* T1 is used as the baud rate generator of UART0 by default
|
||||||
*******************************************************************************/
|
* T2 can also be used as baud rate generator
|
||||||
inline void mInitSTDIO( )
|
* RX on P3.0, TX on P3.1
|
||||||
|
*******************************************************************************/
|
||||||
|
inline void mInitSTDIO( )
|
||||||
{
|
{
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
uint8_t x2;
|
uint8_t x2;
|
||||||
|
|
||||||
SM0 = 0;
|
SM0 = 0; // 8-bit data asynchronous communication
|
||||||
SM1 = 1;
|
SM1 = 1; // Variable baud rate, which is generated by timer T1 or T2
|
||||||
SM2 = 0; //Serial port 0 usage mode 1
|
|
||||||
//Use Timer1 as a baud rate generator
|
// With SM0=0 and SM1=1 we are now in UART0 Mode 1
|
||||||
RCLK = 0; //UART0 receive clock
|
|
||||||
TCLK = 0; //UART0 transmit clock
|
SM2 = 0; // In Mode 1, SM2=0 gives that the Receive interrupt flag bit is set when receiving data and the reception is valid
|
||||||
PCON |= SMOD;
|
|
||||||
x = 10 * FREQ_SYS / UART0_BAUD / 16; //If you change the main frequency, be careful not to overflow the value of x
|
// 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;
|
x2 = x % 10;
|
||||||
x /= 10;
|
x /= 10;
|
||||||
if ( x2 >= 5 ) x ++; //rounding
|
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
|
TMOD = (TMOD & ~bT1_GATE & ~bT1_CT & ~MASK_T1_MOD) | bT1_M1; // Timer1 as 8-bit auto-reload timer
|
||||||
TH1 = 0-x; //12MHz crystal oscillator, buad / 12 is the actual need to set the baud rate
|
T2MOD = T2MOD | bTMR_CLK | bT1_CLK; // Timer1 clock selection
|
||||||
TR1 = 1; //Start timer 1
|
TH1 = 0-x; // 12MHz crystal oscillator, baud / 12 is the actual need to set the baud rate
|
||||||
TI = 1;
|
TR1 = 1; // Start timer 1
|
||||||
REN = 1; //Serial 0 receive enable
|
TI = 1; // Enable transmit interrupt
|
||||||
|
REN = 1; // UART0 receive enable
|
||||||
|
ES = 1; // UART0 interrupt enable
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : CH554UART0RcvByte()
|
* Function Name : CH554UART0RcvByte()
|
||||||
* Description : CH554UART0 receives a byte
|
* Description : CH554UART0 receives a byte
|
||||||
* Return : SBUF
|
* Return : SBUF
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
inline uint8_t CH554UART0RcvByte( )
|
inline uint8_t CH554UART0RcvByte()
|
||||||
{
|
{
|
||||||
while(RI == 0); // wait for uart rx interrupt flag
|
while (RI == 0)
|
||||||
|
; // Wait for uart rx interrupt flag
|
||||||
RI = 0;
|
RI = 0;
|
||||||
return SBUF;
|
return SBUF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : CH554UART0SendByte(uint8_t SendDat)
|
* Function Name : CH554UART0SendByte(uint8_t SendDat)
|
||||||
* Description : CH554UART0 sends a byte
|
* Description : CH554UART0 sends a byte
|
||||||
* Input : uint8_t SendDat; the data to be sent
|
* Input : uint8_t SendDat; the data to be sent
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
inline void CH554UART0SendByte(uint8_t SendDat)
|
inline void CH554UART0SendByte(uint8_t SendDat)
|
||||||
{
|
{
|
||||||
|
SBUF = SendDat;
|
||||||
SBUF = SendDat;
|
while (TI == 0)
|
||||||
while(TI ==0); // wait for transmit to finish (TI == 1)
|
; // Wait for transmit to finish (TI == 1)
|
||||||
TI = 0;
|
TI = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : CH554UART1Alter()
|
* Function Name : CH554UART1Alter()
|
||||||
* Description : Set the alternate pin mappings for UART1 (TX on P3.2, RX on P3.4)
|
* Description : Set the alternate pin mappings for UART1 (RX on P3.4, TX on P3.2)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
inline void CH554UART1Alter()
|
inline void CH554UART1Alter()
|
||||||
{
|
{
|
||||||
PIN_FUNC |= bUART1_PIN_X;
|
PIN_FUNC |= bUART1_PIN_X; // RX on P3.4, TX on P3.2
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : UART1Setup()
|
* Function Name : UART1Setup()
|
||||||
* Description : CH554串口1初始化
|
* Description : CH554 serial port 1 initialization
|
||||||
*******************************************************************************/
|
* RX on P1.6, TX on P1.7
|
||||||
inline void UART1Setup()
|
*
|
||||||
|
*******************************************************************************/
|
||||||
|
inline void UART1Setup()
|
||||||
{
|
{
|
||||||
U1SM0 = 0; //UART1选择8位数据位
|
U1SM0 = 0; // UART1 selects 8-bit data bit
|
||||||
U1SMOD = 1; //快速模式
|
U1SMOD = 1; // Fast mode
|
||||||
U1REN = 1; //使能接收
|
U1REN = 1; // Enable receiving
|
||||||
// should correct for rounding in SBAUD1 calculation
|
// Should correct for rounding in SBAUD1 calculation
|
||||||
SBAUD1 = 256 - FREQ_SYS/16/UART1_BAUD;
|
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()
|
* Function Name : UART1Clean()
|
||||||
* Description : CH554UART1接收一个字节
|
* Description : Read out spurious data
|
||||||
* Return : SBUF
|
*******************************************************************************/
|
||||||
*******************************************************************************/
|
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( )
|
inline uint8_t CH554UART1RcvByte( )
|
||||||
{
|
{
|
||||||
while(U1RI == 0); //查询接收,中断方式可不用
|
while (U1RI == 0) // Query reception, interrupt mode is not required
|
||||||
|
;
|
||||||
U1RI = 0;
|
U1RI = 0;
|
||||||
return SBUF1;
|
return SBUF1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Function Name : CH554UART1SendByte(uint8_t SendDat)
|
* Function Name : CH554UART1SendByte(uint8_t SendDat)
|
||||||
* Description : CH554UART1发送一个字节
|
* Description : CH554UART1 sends a byte
|
||||||
* Input : uint8_t SendDat;要发送的数据
|
* Input : uint8_t SendDat; data to be sent
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
inline void CH554UART1SendByte(uint8_t SendDat)
|
inline void CH554UART1SendByte(uint8_t SendDat)
|
||||||
{
|
{
|
||||||
SBUF1 = SendDat; //查询发送,中断方式可不用下面2条语句,但发送前需TI=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);
|
while (U1TI == 0)
|
||||||
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
|
#if SDCC < 370
|
||||||
void putchar(char c);
|
void putchar(char c);
|
||||||
char getchar();
|
char getchar(void);
|
||||||
#else
|
#else
|
||||||
int putchar(int c);
|
int putchar(int c);
|
||||||
int getchar(void);
|
int getchar(void);
|
||||||
@ -149,16 +232,15 @@ int getchar(void);
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
inline void CH554WDTModeSelect(uint8_t mode)
|
inline void CH554WDTModeSelect(uint8_t mode)
|
||||||
{
|
{
|
||||||
SAFE_MOD = 0x55;
|
SAFE_MOD = 0x55;
|
||||||
SAFE_MOD = 0xaa; //Enter Safe Mode
|
SAFE_MOD = 0xaa; // Enter Safe Mode
|
||||||
if(mode){
|
if (mode) {
|
||||||
GLOBAL_CFG |= bWDOG_EN; //Start watchdog reset
|
GLOBAL_CFG |= bWDOG_EN; // Start watchdog reset
|
||||||
}
|
} else {
|
||||||
|
GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer
|
||||||
else GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer
|
}
|
||||||
SAFE_MOD = 0x00; //exit safe Mode
|
SAFE_MOD = 0x00; // Exit safe Mode
|
||||||
WDOG_COUNT = 0; //Watchdog assignment initial value
|
WDOG_COUNT = 0; // Watchdog assignment initial value
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -173,12 +255,7 @@ inline void CH554WDTModeSelect(uint8_t mode)
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
inline void CH554WDTFeed(uint8_t tim)
|
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.
|
#endif
|
||||||
void gpio_init();
|
|
||||||
void gpio_set(uint8_t pin);
|
|
||||||
void gpio_unset(uint8_t pin);
|
|
||||||
|
40
hw/usb_interface/ch552_fw/include/mem.h
Normal file
40
hw/usb_interface/ch552_fw/include/mem.h
Normal 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
|
188
hw/usb_interface/ch552_fw/include/print.c
Normal file
188
hw/usb_interface/ch552_fw/include/print.c
Normal 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
|
||||||
|
}
|
42
hw/usb_interface/ch552_fw/include/print.h
Normal file
42
hw/usb_interface/ch552_fw/include/print.h
Normal 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
|
64
hw/usb_interface/ch552_fw/include/usb_strings.h
Normal file
64
hw/usb_interface/ch552_fw/include/usb_strings.h
Normal 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
@ -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
|
|
Loading…
x
Reference in New Issue
Block a user