Using latest drivers
This commit is contained in:
parent
36723052d5
commit
88be5bb38a
15 changed files with 43308 additions and 82 deletions
|
@ -1,4 +1,5 @@
|
|||
[target.thumbv7em-none-eabihf]
|
||||
runner = "arm-none-eabi-gdb -x openocd.gdb -q"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tfixed-link.x",
|
||||
]
|
||||
|
|
1
.vscode/.cortex-debug.peripherals.state.json
vendored
Normal file
1
.vscode/.cortex-debug.peripherals.state.json
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
[]
|
1
.vscode/.cortex-debug.registers.state.json
vendored
Normal file
1
.vscode/.cortex-debug.registers.state.json
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
[]
|
114
.vscode/launch.json
vendored
Normal file
114
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "PineTime Debug",
|
||||
"device": "nRF52832",
|
||||
"svdFile": ".vscode/nrf52.svd",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"configFiles": [
|
||||
// Tell OpenOCD to open the ST Link connection.
|
||||
"scripts/swd-stlink.ocd",
|
||||
// Tell OpenOCD to run our custom debug commands.
|
||||
"scripts/debug.ocd"
|
||||
],
|
||||
"executable": "./target/thumbv7em-none-eabihf/debug/pinetime-rs",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"preLaunchCommands": [
|
||||
// Before loading the Application, run these gdb commands.
|
||||
// Set timeout for executing openocd commands.
|
||||
"set remotetimeout 60",
|
||||
|
||||
// This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
|
||||
"set breakpoint pending on",
|
||||
|
||||
// Display the Arm instruction when hitting breakpoint.
|
||||
// "display/i $pc",
|
||||
|
||||
// Load Bootloader symbols in case we jump to the Bootloader.
|
||||
// "symbol-file bin/targets/bluepill_boot/app/apps/boot/boot.elf",
|
||||
|
||||
// Restore Application symbols.
|
||||
// "symbol-file bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
|
||||
"monitor arm semihosting enable"
|
||||
],
|
||||
"postLaunchCommands": [
|
||||
// After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
|
||||
// If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
|
||||
// "stepi", // Must step before setting PC
|
||||
// "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
|
||||
// "stepi", // Execute the Reset Handler
|
||||
//"break main", // Break at main()
|
||||
"break __assert_func", // Break for any assert failures
|
||||
"break os_default_irq", // Break for any unhandled interrupts
|
||||
"break HardFault",
|
||||
"break rust_begin_unwind"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PineTime Debug Release",
|
||||
"device": "nRF52832",
|
||||
"svdFile": ".vscode/nrf52.svd",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"configFiles": [
|
||||
// Tell OpenOCD to open the ST Link connection.
|
||||
"scripts/swd-stlink.ocd",
|
||||
// Tell OpenOCD to run our custom debug commands.
|
||||
"scripts/debug.ocd"
|
||||
],
|
||||
"executable": "./target/thumbv7em-none-eabihf/release/pinetime-rs",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
// "swoConfig": {
|
||||
// "enabled": true,
|
||||
// "cpuFrequency": 16000000,
|
||||
// "swoFrequency": 2000000,
|
||||
// "source": "probe",
|
||||
// "decoders": [
|
||||
// {
|
||||
// "type": "console",
|
||||
// "label": "ITM",
|
||||
// "port": 0
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
"preLaunchCommands": [
|
||||
// Before loading the Application, run these gdb commands.
|
||||
// Set timeout for executing openocd commands.
|
||||
"set remotetimeout 60",
|
||||
|
||||
// This indicates that an unrecognized breakpoint location should automatically result in a pending breakpoint being created.
|
||||
"set breakpoint pending on",
|
||||
|
||||
// Display the Arm instruction when hitting breakpoint.
|
||||
// "display/i $pc",
|
||||
|
||||
// Load Bootloader symbols in case we jump to the Bootloader.
|
||||
// "symbol-file bin/targets/bluepill_boot/app/apps/boot/boot.elf",
|
||||
|
||||
// Restore Application symbols.
|
||||
// "symbol-file bin/targets/bluepill_my_sensor/app/apps/my_sensor_app/my_sensor_app.elf",
|
||||
"set print asm-demangle on",
|
||||
//"monitor semihosting ioclient 3",
|
||||
"monitor arm semihosting enable"
|
||||
],
|
||||
"postLaunchCommands": [
|
||||
// After loading the Application, run these gdb commands. The Application ELF image does not contain a valid Image Header.
|
||||
// If not using the Stub Bootloader boot_stub, we need to bypass the Bootloader and jump to the Application directly:
|
||||
// "stepi", // Must step before setting PC
|
||||
// "set $pc = Reset_Handler", // Prepare to jump to the Application's Reset Handler
|
||||
// "stepi", // Execute the Reset Handler
|
||||
//"break main", // Break at main()
|
||||
"break __assert_func", // Break for any assert failures
|
||||
"break os_default_irq", // Break for any unhandled interrupts
|
||||
"break HardFault"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
42660
.vscode/nrf52.svd
vendored
Normal file
42660
.vscode/nrf52.svd
vendored
Normal file
File diff suppressed because it is too large
Load diff
41
.vscode/tasks.json
vendored
Normal file
41
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "cargo release",
|
||||
"type": "shell",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"command": "cargo",
|
||||
"args": [
|
||||
"build",
|
||||
"--release",
|
||||
"-Zfeatures=build_dep"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "flash release",
|
||||
"type": "shell",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"command": "cargo",
|
||||
"args": [
|
||||
"embed",
|
||||
"--release"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "flash debug",
|
||||
"type": "shell",
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"command": "cargo",
|
||||
"args": [
|
||||
"embed"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
97
Cargo.lock
generated
97
Cargo.lock
generated
|
@ -59,12 +59,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.5"
|
||||
|
@ -104,6 +98,12 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
|
@ -198,11 +198,18 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-semihosting"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "113ef0ecffee2b62b58f9380f4469099b30e9f9cbee2804771b4203ba1762cfa"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cst816s"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "988624bfaeaa34565792f7badc33cd02e84ba51fff4bbc3cd76f59d4af5658e7"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"embedded-hal",
|
||||
|
@ -224,6 +231,23 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
|
||||
|
||||
[[package]]
|
||||
name = "display-interface"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da12a892db5cce95ae247e8803dc653b1a73da3b0450f7983eb518dd54f583cf"
|
||||
|
||||
[[package]]
|
||||
name = "display-interface-spi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94d08c3a1682b166cbcbb4fe009a31a1834ba46c16599bf7a9b3cc7bc31b38b0"
|
||||
dependencies = [
|
||||
"byte-slice-cast",
|
||||
"display-interface",
|
||||
"embedded-hal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-graphics"
|
||||
version = "0.6.2"
|
||||
|
@ -424,10 +448,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "nrf52-hal-common"
|
||||
version = "0.8.1"
|
||||
name = "nrf-hal-common"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03dcdf72cd52a1c4829905e08a90ad6f4dc0f9d15ecf1883cc74f098199aa873"
|
||||
checksum = "cc36b48f37fdeeb88821733f8049bfee490fa76376746760c83bc4faa850320b"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"cortex-m",
|
||||
|
@ -441,24 +465,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nrf52832-hal"
|
||||
version = "0.8.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd4803f1d08e6a4c8726ae68b40cecf7c2ab05f49b1ce29af932d052cb61114c"
|
||||
checksum = "e9656eab0c535fb4429876525fb5db1604bceeed80cc91a7b91d7b683db4a3a0"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"cortex-m",
|
||||
"embedded-hal",
|
||||
"nb",
|
||||
"nrf52-hal-common",
|
||||
"nrf-hal-common",
|
||||
"nrf52832-pac",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nrf52832-pac"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c4545414415bddd872f13c0a5418ecc380e34347a52cb048cfed38c1b0957fa"
|
||||
checksum = "72920484274fae0792a40345049da2723612465c7202561b6a17ad3c127259db"
|
||||
dependencies = [
|
||||
"bare-metal",
|
||||
"cortex-m",
|
||||
|
@ -466,32 +490,18 @@ dependencies = [
|
|||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e521b6adefa0b2c1fa5d2abdf9a5216288686fe6146249215d884c0e5ab320b0"
|
||||
|
||||
[[package]]
|
||||
name = "panic-halt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
|
@ -504,13 +514,17 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
"cortex-m-semihosting",
|
||||
"cst816s",
|
||||
"cstr_core",
|
||||
"display-interface",
|
||||
"display-interface-spi",
|
||||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"lvgl",
|
||||
"nrf52832-hal",
|
||||
"numtoa",
|
||||
"panic-halt",
|
||||
"st7789",
|
||||
]
|
||||
|
||||
|
@ -546,9 +560,9 @@ checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
|
|||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.2"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
|
@ -606,16 +620,15 @@ checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
|||
|
||||
[[package]]
|
||||
name = "st7789"
|
||||
version = "0.2.3"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ccc7b7e79f9e578e981bfab45b502b72ca02717a4356df0478228a6ff7c47c4"
|
||||
checksum = "a9f2a309b876ab3ac011a437624b439ec22387db20c86e024b5aae8090428623"
|
||||
dependencies = [
|
||||
"display-interface",
|
||||
"embedded-graphics",
|
||||
"embedded-hal",
|
||||
"heapless",
|
||||
"nb",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -8,14 +8,17 @@ license = "BSD-3-Clause"
|
|||
[dependencies]
|
||||
cortex-m = "0.6"
|
||||
cortex-m-rt = "0.6"
|
||||
cortex-m-semihosting = "0.3.5"
|
||||
embedded-graphics = "0.6"
|
||||
embedded-hal = {version ="0.2.3", features = ["unproven"] }
|
||||
#nrf52832-hal = { version = "0.10", default-features = false, features = ["xxAA-package", "rt"] }
|
||||
nrf52832-hal = {version = "0.8.1", default-features = false, features = ["xxAA-package", "rt"]}
|
||||
st7789 = { version = "0.2", features = ["graphics", "batch", "buffer"], default-features = false }
|
||||
nrf52832-hal = { version = "0.10", default-features = false, features = ["xxAA-package", "rt"] }
|
||||
st7789 = { version = "0.5.0", features = ["graphics", "batch", "buffer"], default-features = false }
|
||||
display-interface = "0.4"
|
||||
display-interface-spi = "0.4"
|
||||
panic-halt = "0.2.0"
|
||||
cstr_core = "0.2.0"
|
||||
numtoa = "0.2.3"
|
||||
cst816s = "0.1.4"
|
||||
cst816s = { path = "../cst816s" }
|
||||
lvgl = { path = "../lvgl-rs/lvgl" }
|
||||
|
||||
[profile.dev]
|
||||
|
|
49
openocd.gdb
Normal file
49
openocd.gdb
Normal file
|
@ -0,0 +1,49 @@
|
|||
target extended-remote :3333
|
||||
|
||||
# print demangled symbols
|
||||
set print asm-demangle on
|
||||
|
||||
# set backtrace limit to not have infinite backtrace loops
|
||||
set backtrace limit 32
|
||||
|
||||
# detect unhandled exceptions, hard faults and panics
|
||||
#break DefaultHandler
|
||||
break HardFault
|
||||
break rust_begin_unwind
|
||||
#break panic
|
||||
# # run the next few lines so the panic message is printed immediately
|
||||
# # the number needs to be adjusted for your panic handler
|
||||
# commands $bpnum
|
||||
# next 4
|
||||
# end
|
||||
|
||||
# *try* to stop at the user entry point (it might be gone due to inlining)
|
||||
# break main
|
||||
|
||||
monitor arm semihosting enable
|
||||
|
||||
# # send captured ITM to the file itm.fifo
|
||||
# # (the microcontroller SWO pin must be connected to the programmer SWO pin)
|
||||
# # 8000000 must match the core clock frequency
|
||||
# monitor tpiu config internal itm.txt uart off 8000000
|
||||
|
||||
# # OR: make the microcontroller SWO pin output compatible with UART (8N1)
|
||||
# # 8000000 must match the core clock frequency
|
||||
# # 2000000 is the frequency of the SWO pin
|
||||
# monitor tpiu config external uart off 8000000 2000000
|
||||
|
||||
# # enable ITM port 0
|
||||
# monitor itm port 0 on
|
||||
|
||||
# don't confirm when quitting debugger
|
||||
define hook-quit
|
||||
set confirm off
|
||||
end
|
||||
|
||||
load
|
||||
#monitor reset halt
|
||||
|
||||
# start the process but immediately halt the processor
|
||||
# stepi
|
||||
|
||||
continue
|
10
scripts/debug.ocd
Normal file
10
scripts/debug.ocd
Normal file
|
@ -0,0 +1,10 @@
|
|||
# This is an OpenOCD script that connects to the nRF52 for Cortex Debug.
|
||||
|
||||
# Debug Level must be 2 or greater or gdb will fail.
|
||||
debug_level 2
|
||||
|
||||
$_TARGETNAME configure -event reset-init {
|
||||
# Arm Semihosting is used to show debug console output and may only be enabled after init event. We wait for the event and enable Arm Semihosting.
|
||||
echo "Enable ARM Semihosting to show debug output"
|
||||
arm semihosting enable
|
||||
}
|
4
scripts/flash-init.ocd
Normal file
4
scripts/flash-init.ocd
Normal file
|
@ -0,0 +1,4 @@
|
|||
# This is an OpenOCD script that prepares the microcontroller before any flashing.
|
||||
|
||||
# Disable all openocd messages.
|
||||
debug_level 0
|
14
scripts/swd-stlink.ocd
Normal file
14
scripts/swd-stlink.ocd
Normal file
|
@ -0,0 +1,14 @@
|
|||
# OpenOCD script for using ST-Link v2 as SWD Programmer for nRF52
|
||||
|
||||
# VSCode debugger searches this folder for OpenOCD scripts
|
||||
add_script_search_dir openocd/scripts
|
||||
|
||||
# Set OpenOCD logging
|
||||
source [find scripts/flash-init.ocd]
|
||||
|
||||
# Select the ST-Link v2 interface (SWD transport)
|
||||
source [find interface/stlink-v2.cfg]
|
||||
transport select hla_swd
|
||||
|
||||
# Select nRF52 as target
|
||||
source [find target/nrf52.cfg]
|
|
@ -4,9 +4,7 @@
|
|||
//! default also wants SYST for its Delay implementation.
|
||||
|
||||
use embedded_hal::blocking::delay::DelayUs;
|
||||
use hal::nrf52832_pac as pac;
|
||||
use nrf52832_hal::prelude::TimerExt;
|
||||
use nrf52832_hal::{self as hal, timer::Timer};
|
||||
use nrf52832_hal::{self as hal, pac, timer::Timer};
|
||||
|
||||
pub struct TimerDelay {
|
||||
timer: hal::Timer<pac::TIMER0>,
|
||||
|
@ -15,8 +13,7 @@ pub struct TimerDelay {
|
|||
impl TimerDelay {
|
||||
pub fn new(timer0: pac::TIMER0) -> Self {
|
||||
Self {
|
||||
//timer: Timer::new(timer0),
|
||||
timer: timer0.constrain(),
|
||||
timer: Timer::new(timer0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
97
src/main.rs
97
src/main.rs
|
@ -1,41 +1,44 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate panic_halt;
|
||||
|
||||
mod backlight;
|
||||
mod delay;
|
||||
mod monotonic_nrf52;
|
||||
|
||||
// use nrf52832_hal::gpio::Level;
|
||||
// use nrf52832_hal::{self as p_hal, pac};
|
||||
// use p_hal::{delay::Delay, spim, twim};
|
||||
use nrf52832_hal as p_hal;
|
||||
use p_hal::gpio::{GpioExt, Level};
|
||||
use p_hal::nrf52832_pac as pac;
|
||||
use p_hal::{delay::Delay, rng::RngExt, spim, twim};
|
||||
use nrf52832_hal::gpio::Level;
|
||||
use nrf52832_hal::{self as p_hal, pac};
|
||||
use p_hal::{delay::Delay, spim, twim};
|
||||
|
||||
use cortex_m_rt as rt;
|
||||
use cortex_m_semihosting::hprintln;
|
||||
use cst816s::CST816S;
|
||||
use cstr_core::CStr;
|
||||
use embedded_graphics::prelude::*;
|
||||
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
|
||||
use embedded_hal::digital::v2::OutputPin;
|
||||
use nrf52832_hal::prelude::ClocksExt;
|
||||
use numtoa::NumToA;
|
||||
use rt::entry;
|
||||
use st7789::Orientation;
|
||||
use st7789::{Orientation, ST7789};
|
||||
|
||||
use lvgl::input_device::{InputData, Pointer};
|
||||
use lvgl::style::Style;
|
||||
use lvgl::widgets::{Btn, Label};
|
||||
use lvgl::{self, Align, Color, Part, State, Widget, UI};
|
||||
|
||||
use crate::monotonic_nrf52::Instant;
|
||||
use core::panic::PanicInfo;
|
||||
use core::time::Duration;
|
||||
use display_interface_spi::SPIInterfaceNoCS;
|
||||
|
||||
///
|
||||
/// This example was written and tested for the PineTime smart watch
|
||||
///
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
hprintln!("\nStarting...").unwrap();
|
||||
|
||||
let cp = pac::CorePeripherals::take().unwrap();
|
||||
let mut delay_source = Delay::new(cp.SYST);
|
||||
|
||||
|
@ -43,25 +46,24 @@ fn main() -> ! {
|
|||
// Optimize clock config
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
let lcd_delay = delay::TimerDelay::new(dp.TIMER0);
|
||||
//let lcd_delay = delay::TimerDelay::new(dp.TIMER0);
|
||||
|
||||
// Initialize monotonic timer on TIMER1 (for RTFM)
|
||||
monotonic_nrf52::Tim1::initialize(dp.TIMER1);
|
||||
|
||||
// Set up clocks. On reset, the high frequency clock is already used,
|
||||
// but we also need to switch to the external HF oscillator. This is
|
||||
// needed for Bluetooth to work.
|
||||
let _clocks = p_hal::clocks::Clocks::new(dp.CLOCK).enable_ext_hfosc();
|
||||
|
||||
//let _clocks = p_hal::clocks::Clocks::new(dp.CLOCK).enable_ext_hfosc();
|
||||
let _clockit = dp.CLOCK.constrain().enable_ext_hfosc();
|
||||
|
||||
//let gpio = p_hal::gpio::p0::Parts::new(dp.P0);
|
||||
let gpio = dp.P0.split();
|
||||
let gpio = p_hal::gpio::p0::Parts::new(dp.P0);
|
||||
|
||||
// Set up SPI pins
|
||||
let spi_clk = gpio.p0_02.into_push_pull_output(Level::Low).degrade();
|
||||
let spi_mosi = gpio.p0_03.into_push_pull_output(Level::Low).degrade();
|
||||
let spi_miso = gpio.p0_04.into_floating_input().degrade();
|
||||
let spi_pins = spim::Pins {
|
||||
sck: spi_clk,
|
||||
miso: Some(spi_miso),
|
||||
miso: None,
|
||||
mosi: Some(spi_mosi),
|
||||
};
|
||||
|
||||
|
@ -109,9 +111,12 @@ fn main() -> ! {
|
|||
spim::Frequency::M8,
|
||||
// SPI must be used in mode 3. Mode 0 (the default) won't work.
|
||||
spim::MODE_3,
|
||||
0,
|
||||
122,
|
||||
);
|
||||
|
||||
// display interface abstraction from SPI and DC
|
||||
let di = SPIInterfaceNoCS::new(spi, lcd_dc);
|
||||
|
||||
// Chip select must be held low while driving the display. It must be high
|
||||
// when using other SPI devices on the same bus (such as external flash
|
||||
// storage) so that the display controller won't respond to the wrong
|
||||
|
@ -119,17 +124,17 @@ fn main() -> ! {
|
|||
lcd_cs.set_low().unwrap();
|
||||
|
||||
// Initialize LCD
|
||||
let mut lcd = st7789::ST7789::new(
|
||||
spi,
|
||||
lcd_dc,
|
||||
let mut lcd = ST7789::new(
|
||||
di,
|
||||
lcd_rst,
|
||||
lvgl::HOR_RES_MAX as u16,
|
||||
lvgl::VER_RES_MAX as u16,
|
||||
lcd_delay,
|
||||
);
|
||||
|
||||
lcd.init().unwrap();
|
||||
lcd.set_orientation(&Orientation::Portrait).unwrap();
|
||||
lcd.init(&mut delay_source).unwrap();
|
||||
lcd.set_orientation(Orientation::Portrait).unwrap();
|
||||
|
||||
hprintln!("\nAll devices set!").unwrap();
|
||||
|
||||
// Initialize LVGL
|
||||
let mut ui = UI::init().unwrap();
|
||||
|
@ -182,7 +187,17 @@ fn main() -> ! {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let mut loop_time = Instant::now();
|
||||
let mut total_time = Duration::from_secs(0);
|
||||
let mut time_text_buf = [0u8; 20];
|
||||
|
||||
let mut last_update_time_secs = 0;
|
||||
let mut last_inc_time_ms = 0;
|
||||
|
||||
hprintln!("\nLVGL widgets built!").unwrap();
|
||||
loop {
|
||||
ui.task_handler();
|
||||
|
||||
if let Some(evt) = touchpad.read_one_touch_event(true) {
|
||||
latest_touch_point = Point::new(evt.x, evt.y);
|
||||
// Pressed
|
||||
|
@ -196,12 +211,32 @@ fn main() -> ! {
|
|||
.once();
|
||||
delay_source.delay_us(1u32);
|
||||
}
|
||||
ui.task_handler();
|
||||
ui.tick_inc(Duration::from_secs(1));
|
||||
|
||||
total_time += Duration::from_micros(loop_time.elapsed().as_cycles() as u64);
|
||||
|
||||
if total_time.as_secs() > last_update_time_secs {
|
||||
last_update_time_secs = total_time.as_secs();
|
||||
|
||||
let text = (total_time.as_secs() as u32).numtoa(10, &mut time_text_buf);
|
||||
|
||||
let time_text = unsafe { CStr::from_bytes_with_nul_unchecked(&text) };
|
||||
time_lbl.set_text(time_text).unwrap();
|
||||
time_lbl
|
||||
.set_align(&mut button, Align::OutTopMid, 0, -50)
|
||||
.unwrap();
|
||||
|
||||
// Reset buffer
|
||||
for p in time_text_buf.iter_mut() {
|
||||
*p = '\0' as u8;
|
||||
}
|
||||
}
|
||||
|
||||
if total_time.as_millis() > last_inc_time_ms {
|
||||
//let diff_ms = total_time.as_millis() - last_inc_time_ms;
|
||||
last_inc_time_ms = total_time.as_millis();
|
||||
}
|
||||
ui.tick_inc(Duration::from_millis(50));
|
||||
|
||||
loop_time = Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
|
283
src/monotonic_nrf52.rs
Normal file
283
src/monotonic_nrf52.rs
Normal file
|
@ -0,0 +1,283 @@
|
|||
//! Using NRF52 as monotonic timer
|
||||
//!
|
||||
//! Source:
|
||||
//! https://github.com/rtfm-rs/rtfm-examples/blob/master/rtfm_v5/monotonic_nrf52/src/monotonic_nrf52.rs
|
||||
|
||||
use core::u32;
|
||||
use core::{
|
||||
cmp::Ordering,
|
||||
convert::{Infallible, TryInto},
|
||||
fmt, ops,
|
||||
};
|
||||
use nrf52832_hal::target;
|
||||
|
||||
/// A measurement of the counter. Opaque and useful only with `Duration`
|
||||
///
|
||||
/// # Correctness
|
||||
///
|
||||
/// Adding or subtracting a `Duration` of more than `(1 << 31)` cycles to an `Instant` effectively
|
||||
/// makes it "wrap around" and creates an incorrect value. This is also true if the operation is
|
||||
/// done in steps, e.g. `(instant + dur) + dur` where `dur` is `(1 << 30)` ticks.
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub struct Instant {
|
||||
inner: i32,
|
||||
}
|
||||
|
||||
impl Instant {
|
||||
/// Returns an instant corresponding to "now"
|
||||
pub fn now() -> Self {
|
||||
let now = {
|
||||
let timer = unsafe { &*target::TIMER1::ptr() };
|
||||
timer.tasks_capture[0].write(|w| unsafe { w.bits(1) });
|
||||
timer.cc[0].read().bits()
|
||||
};
|
||||
|
||||
Instant { inner: now as i32 }
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed since this instant was created.
|
||||
pub fn elapsed(&self) -> Duration {
|
||||
Instant::now() - *self
|
||||
}
|
||||
|
||||
/// Returns the underlying count
|
||||
pub fn counts(&self) -> u32 {
|
||||
self.inner as u32
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one.
|
||||
pub fn duration_since(&self, earlier: Instant) -> Duration {
|
||||
let diff = self.inner - earlier.inner;
|
||||
assert!(diff >= 0, "second instant is later than self");
|
||||
Duration { inner: diff as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Instant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Instant")
|
||||
.field(&(self.inner as u32))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::AddAssign<Duration> for Instant {
|
||||
fn add_assign(&mut self, dur: Duration) {
|
||||
// NOTE this is a debug assertion because there's no foolproof way to detect a wrap around;
|
||||
// the user may write `(instant + dur) + dur` where `dur` is `(1<<31)-1` ticks.
|
||||
debug_assert!(dur.inner < (1 << 31));
|
||||
self.inner = self.inner.wrapping_add(dur.inner as i32);
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<Duration> for Instant {
|
||||
type Output = Self;
|
||||
|
||||
fn add(mut self, dur: Duration) -> Self {
|
||||
self += dur;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::SubAssign<Duration> for Instant {
|
||||
fn sub_assign(&mut self, dur: Duration) {
|
||||
// NOTE see the NOTE in `<Instant as AddAssign<Duration>>::add_assign`
|
||||
debug_assert!(dur.inner < (1 << 31));
|
||||
self.inner = self.inner.wrapping_sub(dur.inner as i32);
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub<Duration> for Instant {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(mut self, dur: Duration) -> Self {
|
||||
self -= dur;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub<Instant> for Instant {
|
||||
type Output = Duration;
|
||||
|
||||
fn sub(self, other: Instant) -> Duration {
|
||||
self.duration_since(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Instant {
|
||||
fn cmp(&self, rhs: &Self) -> Ordering {
|
||||
self.inner.wrapping_sub(rhs.inner).cmp(&0)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Instant {
|
||||
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(rhs))
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Duration` type to represent a span of time.
|
||||
///
|
||||
/// This data type is only available on ARMv7-M
|
||||
///
|
||||
/// # Correctness
|
||||
///
|
||||
/// This type is *not* appropriate for representing time spans in the order of, or larger than,
|
||||
/// seconds because it can hold a maximum of `(1 << 31)` "ticks" where each tick is the inverse of
|
||||
/// the CPU frequency, which usually is dozens of MHz.
|
||||
#[derive(Clone, Copy, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Duration {
|
||||
inner: u32,
|
||||
}
|
||||
|
||||
impl Duration {
|
||||
/// Creates a new `Duration` from the specified number of clock cycles
|
||||
pub fn from_cycles(cycles: u32) -> Self {
|
||||
Duration { inner: cycles }
|
||||
}
|
||||
|
||||
/// Returns the total number of clock cycles contained by this `Duration`
|
||||
pub fn as_cycles(&self) -> u32 {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
// Used internally by RTFM to convert the duration into a known type
|
||||
impl TryInto<u32> for Duration {
|
||||
type Error = Infallible;
|
||||
|
||||
fn try_into(self) -> Result<u32, Infallible> {
|
||||
Ok(self.as_cycles())
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::AddAssign for Duration {
|
||||
fn add_assign(&mut self, dur: Duration) {
|
||||
self.inner += dur.inner;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<Duration> for Duration {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
Duration {
|
||||
inner: self.inner + other.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<u32> for Duration {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: u32) -> Self {
|
||||
Duration {
|
||||
inner: self.inner * other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::MulAssign<u32> for Duration {
|
||||
fn mul_assign(&mut self, other: u32) {
|
||||
*self = *self * other;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::SubAssign for Duration {
|
||||
fn sub_assign(&mut self, rhs: Duration) {
|
||||
self.inner -= rhs.inner;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub<Duration> for Duration {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self {
|
||||
Duration {
|
||||
inner: self.inner - rhs.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds the `millis` and `micros` methods to the `u32` type
|
||||
///
|
||||
/// This trait is only available on ARMv7-M
|
||||
pub trait U32Ext {
|
||||
/// Converts the `u32` value as seconds into ticks
|
||||
fn secs(self) -> Duration;
|
||||
|
||||
/// Converts the `u32` value as milliseconds into ticks
|
||||
fn millis(self) -> Duration;
|
||||
|
||||
/// Converts the `u32` value as microseconds into ticks
|
||||
fn micros(self) -> Duration;
|
||||
|
||||
/// Converts the `u32` value as hertz into ticks
|
||||
fn hz(self) -> Duration;
|
||||
}
|
||||
|
||||
impl U32Ext for u32 {
|
||||
fn secs(self) -> Duration {
|
||||
self.millis() * 1_000
|
||||
}
|
||||
|
||||
fn millis(self) -> Duration {
|
||||
self.micros() * 1_000
|
||||
}
|
||||
|
||||
fn micros(self) -> Duration {
|
||||
Duration { inner: self }
|
||||
}
|
||||
|
||||
fn hz(self) -> Duration {
|
||||
(1_000_000 / self).micros()
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementor of the `rtfm::Monotonic` traits and used to consume the timer
|
||||
/// to not allow for erroneous configuration.
|
||||
///
|
||||
/// The timer must be initialized through `initialize()`.
|
||||
pub struct Tim1;
|
||||
|
||||
impl Tim1 {
|
||||
pub fn initialize(timer: target::TIMER1) {
|
||||
// Auto restart, make sure the entire timer won't stop for any event
|
||||
timer.shorts.write(|w| {
|
||||
w.compare0_clear()
|
||||
.enabled()
|
||||
.compare0_stop()
|
||||
.disabled()
|
||||
.compare1_clear()
|
||||
.enabled()
|
||||
.compare1_stop()
|
||||
.disabled()
|
||||
.compare2_clear()
|
||||
.enabled()
|
||||
.compare2_stop()
|
||||
.disabled()
|
||||
.compare3_clear()
|
||||
.enabled()
|
||||
.compare3_stop()
|
||||
.disabled()
|
||||
});
|
||||
|
||||
// 1 MHz mode
|
||||
timer.prescaler.write(|w| unsafe { w.prescaler().bits(4) });
|
||||
|
||||
// 32 bit mode
|
||||
timer.bitmode.write(|w| w.bitmode()._32bit());
|
||||
|
||||
// Set compare value to max, not sure if this is needed
|
||||
timer.cc[0].write(|w| unsafe { w.cc().bits(u32::MAX) });
|
||||
|
||||
// Clear the counter value
|
||||
timer.tasks_clear.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
// Start the timer
|
||||
timer.tasks_start.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
// Throw away the timer, it is now setup and consumed
|
||||
drop(timer);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue