Compare commits
9 Commits
0b4408cf8a
...
v0.5.1
Author | SHA1 | Date | |
---|---|---|---|
49b72d683f | |||
21c44e6327 | |||
147c57defb | |||
5cbbb53094 | |||
491ef3ce09 | |||
e3cdd21b41 | |||
482a725ef7 | |||
9f5a31c5b6 | |||
5cbec366bc |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -6,13 +6,28 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [v0.5.1]
|
||||
|
||||
### Changes
|
||||
|
||||
- Updated dependencies:
|
||||
- `cortex-m-rtic` (dev-depencency) to 1.1.2
|
||||
- `once_cell` to 1.12.0
|
||||
- Other depencies: Only revision has changed
|
||||
|
||||
## [v0.5.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Reactored IRQ handling, so that `unmask` operations can be moved to HAL
|
||||
- Added UART IRQ handler. Right now, can only perform reception, TX still needs to be done in
|
||||
a blocking manner
|
||||
- Added RTIC template and RTIC UART IRQ application
|
||||
|
||||
### Fixed
|
||||
|
||||
- Bugfix in UART code where RX and TX could not be enabled or disabled independently
|
||||
|
||||
## [v0.4.3]
|
||||
|
||||
- Various smaller fixes for READMEs, update of links in documentation
|
||||
|
35
Cargo.toml
35
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "va108xx-hal"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
|
||||
edition = "2021"
|
||||
description = "HAL for the Vorago VA108xx family of microcontrollers"
|
||||
@@ -8,30 +8,43 @@ homepage = "https://egit.irs.uni-stuttgart.de/rust/va108xx-hal"
|
||||
repository = "https://egit.irs.uni-stuttgart.de/rust/va108xx-hal"
|
||||
license = "Apache-2.0"
|
||||
keywords = ["no-std", "hal", "cortex-m", "vorago", "va108xx"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
categories = ["aerospace", "embedded", "no-std", "hardware-support"]
|
||||
|
||||
[dependencies]
|
||||
va108xx = "0.2.4"
|
||||
cortex-m = "0.7"
|
||||
cortex-m-rt = "0.7"
|
||||
nb = "1"
|
||||
paste = "1.0"
|
||||
embedded-hal = { features = ["unproven"], version = "0.2.6" }
|
||||
void = { version = "1.0", default-features = false }
|
||||
once_cell = { version = "1.8.0", default-features = false }
|
||||
libm = "0.2.1"
|
||||
libm = "0.2.2"
|
||||
|
||||
[dependencies.va108xx]
|
||||
version = "0.2.4"
|
||||
[dependencies.embedded-hal]
|
||||
version = "0.2.7"
|
||||
features = ["unproven"]
|
||||
|
||||
[dependencies.void]
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.12.0"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
rt = ["va108xx/rt"]
|
||||
|
||||
[dev-dependencies]
|
||||
cortex-m-rtic = "0.6.0-rc.4"
|
||||
panic-rtt-target = { version = "0.1", features = ["cortex-m"] }
|
||||
rtt-target = { version = "0.3", features = ["cortex-m"] }
|
||||
cortex-m-rtic = "1.1.2"
|
||||
panic-halt = "0.2"
|
||||
|
||||
[dev-dependencies.rtt-target]
|
||||
version = "0.3"
|
||||
features = ["cortex-m"]
|
||||
|
||||
[dev-dependencies.panic-rtt-target]
|
||||
version = "0.1"
|
||||
features = ["cortex-m"]
|
||||
|
||||
[profile.dev]
|
||||
debug = true
|
||||
lto = false
|
||||
|
@@ -1,5 +1,12 @@
|
||||
//! UART example application. Sends a test string over a UART and then enters
|
||||
//! echo mode
|
||||
//! More complex UART application
|
||||
//!
|
||||
//! Uses the IRQ capabilities of the VA10820 peripheral and the RTIC framework to poll the UART in
|
||||
//! a non-blocking way. You can send variably sized strings to the VA10820 which will be echoed
|
||||
//! back to the sender.
|
||||
//!
|
||||
//! This script was tested with an Arduino Due. You can find the test script in the
|
||||
//! [`/test/DueSerialTest`](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/test/DueSerialTest)
|
||||
//! folder.
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
|
36
src/uart.rs
36
src/uart.rs
@@ -2,7 +2,8 @@
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! - [UART example](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/examples/uart.rs)
|
||||
//! - [UART simple example](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/examples/uart.rs)
|
||||
//! - [UART with IRQ and RTIC](https://egit.irs.uni-stuttgart.de/rust/va108xx-hal/src/branch/main/examples/uart-irq-rtic.rs)
|
||||
use core::{convert::Infallible, ptr};
|
||||
use core::{marker::PhantomData, ops::Deref};
|
||||
use libm::floorf;
|
||||
@@ -177,7 +178,7 @@ impl From<Bps> for Config {
|
||||
// IRQ Definitions
|
||||
//==================================================================================================
|
||||
|
||||
pub struct IrqInfo {
|
||||
struct IrqInfo {
|
||||
rx_len: usize,
|
||||
rx_idx: usize,
|
||||
irq_cfg: IrqCfg,
|
||||
@@ -196,6 +197,7 @@ pub enum IrqResultMask {
|
||||
Unknown = 7,
|
||||
}
|
||||
|
||||
/// This struct is used to return the default IRQ handler result to the user
|
||||
#[derive(Debug, Default)]
|
||||
pub struct IrqResult {
|
||||
raw_res: u32,
|
||||
@@ -276,32 +278,36 @@ impl IrqResult {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum IrqReceptionMode {
|
||||
enum IrqReceptionMode {
|
||||
Idle,
|
||||
FixedLen,
|
||||
VarLen,
|
||||
Pending,
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// UART implementation
|
||||
//==================================================================================================
|
||||
|
||||
/// Type erased variant of a UART. Can be created with the [`Uart::downgrade`] function.
|
||||
pub struct UartBase<UART> {
|
||||
uart: UART,
|
||||
tx: Tx<UART>,
|
||||
rx: Rx<UART>,
|
||||
}
|
||||
/// Serial abstraction
|
||||
/// Serial abstraction. Entry point to create a new UART
|
||||
pub struct Uart<UART, PINS> {
|
||||
uart_base: UartBase<UART>,
|
||||
pins: PINS,
|
||||
}
|
||||
|
||||
/// UART using the IRQ capabilities of the peripheral. Can be created with the
|
||||
/// [`Uart::into_uart_with_irq`] function.
|
||||
pub struct UartWithIrq<UART, PINS> {
|
||||
irq_base: UartWithIrqBase<UART>,
|
||||
pins: PINS,
|
||||
}
|
||||
|
||||
/// Type-erased UART using the IRQ capabilities of the peripheral. Can be created with the
|
||||
/// [`UartWithIrq::downgrade`] function.
|
||||
pub struct UartWithIrqBase<UART> {
|
||||
pub uart: UartBase<UART>,
|
||||
irq_info: IrqInfo,
|
||||
@@ -477,6 +483,8 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// If the IRQ capabilities of the peripheral are used, the UART needs to be converted
|
||||
/// with this function
|
||||
pub fn into_uart_with_irq(
|
||||
self,
|
||||
irq_cfg: IrqCfg,
|
||||
@@ -631,6 +639,14 @@ impl<UART: Instance> UartWithIrqBase<UART> {
|
||||
self
|
||||
}
|
||||
|
||||
/// This initializes a non-blocking read transfer using the IRQ capabilities of the UART
|
||||
/// peripheral.
|
||||
///
|
||||
/// The only required information is the maximum length for variable sized reception
|
||||
/// or the expected length for fixed length reception. If variable sized packets are expected,
|
||||
/// the timeout functionality of the IRQ should be enabled as well. After calling this function,
|
||||
/// the [`irq_handler`](Self::irq_handler) function should be called in the user interrupt
|
||||
/// handler to read the received packets and reinitiate another transfer if desired.
|
||||
pub fn read_fixed_len_using_irq(
|
||||
&mut self,
|
||||
max_len: usize,
|
||||
@@ -639,6 +655,7 @@ impl<UART: Instance> UartWithIrqBase<UART> {
|
||||
if self.irq_info.mode != IrqReceptionMode::Idle {
|
||||
return Err(Error::TransferPending);
|
||||
}
|
||||
self.irq_info.mode = IrqReceptionMode::Pending;
|
||||
self.irq_info.rx_idx = 0;
|
||||
self.irq_info.rx_len = max_len;
|
||||
self.uart.enable_rx();
|
||||
@@ -689,6 +706,10 @@ impl<UART: Instance> UartWithIrqBase<UART> {
|
||||
self.irq_info.rx_len = 0;
|
||||
}
|
||||
|
||||
/// Default IRQ handler which can be used to read the packets arriving on the UART peripheral.
|
||||
///
|
||||
/// If passed buffer is equal to or larger than the specified maximum length, an
|
||||
/// [`Error::BufferTooShort`] will be returned
|
||||
pub fn irq_handler(&mut self, res: &mut IrqResult, buf: &mut [u8]) -> Result<(), Error> {
|
||||
if buf.len() < self.irq_info.rx_len {
|
||||
return Err(Error::BufferTooShort);
|
||||
@@ -799,6 +820,7 @@ impl<UART: Instance> UartWithIrqBase<UART> {
|
||||
res.bytes_read = self.irq_info.rx_idx;
|
||||
res.clear_result();
|
||||
res.set_result(IrqResultMask::Complete);
|
||||
self.irq_info.mode = IrqReceptionMode::Idle;
|
||||
self.irq_info.rx_idx = 0;
|
||||
self.irq_info.rx_len = 0;
|
||||
}
|
||||
@@ -809,6 +831,7 @@ impl<UART: Instance> UartWithIrqBase<UART> {
|
||||
}
|
||||
|
||||
impl<UART: Instance, PINS> UartWithIrq<UART, PINS> {
|
||||
/// See [`UartWithIrqBase::read_fixed_len_using_irq`] doc
|
||||
pub fn read_fixed_len_using_irq(
|
||||
&mut self,
|
||||
max_len: usize,
|
||||
@@ -822,6 +845,7 @@ impl<UART: Instance, PINS> UartWithIrq<UART, PINS> {
|
||||
self.irq_base.cancel_transfer()
|
||||
}
|
||||
|
||||
/// See [`UartWithIrqBase::irq_handler`] doc
|
||||
pub fn irq_handler(&mut self, res: &mut IrqResult, buf: &mut [u8]) -> Result<(), Error> {
|
||||
self.irq_base.irq_handler(res, buf)
|
||||
}
|
||||
|
5
test/DueSerialTest/.gitignore
vendored
Normal file
5
test/DueSerialTest/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
7
test/DueSerialTest/.vscode/extensions.json
vendored
Normal file
7
test/DueSerialTest/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
2
test/DueSerialTest/README.md
Normal file
2
test/DueSerialTest/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
This is a Platform IO test script for the Arduino Due which can be used to sent different kind
|
||||
of strings via the serial interface (RX1 and TX1) to the Vorago board.
|
39
test/DueSerialTest/include/README
Normal file
39
test/DueSerialTest/include/README
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
test/DueSerialTest/lib/README
Normal file
46
test/DueSerialTest/lib/README
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
15
test/DueSerialTest/platformio.ini
Normal file
15
test/DueSerialTest/platformio.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:due]
|
||||
platform = atmelsam
|
||||
board = due
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
78
test/DueSerialTest/src/main.cpp
Normal file
78
test/DueSerialTest/src/main.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
enum SendModes {
|
||||
ECHO,
|
||||
ONLY_WRITE,
|
||||
ONLY_READ,
|
||||
WRITE_READ
|
||||
};
|
||||
|
||||
enum StringModes {
|
||||
FIXED,
|
||||
VARIABLE
|
||||
};
|
||||
|
||||
// Configure the test application here
|
||||
SendModes SEND_MODE = SendModes::WRITE_READ;
|
||||
StringModes STRING_MODE = StringModes::VARIABLE;
|
||||
uint8_t STRING_IDX = 0;
|
||||
|
||||
String STRINGS[4] = {
|
||||
"$Hi\n",
|
||||
"$Hello\n",
|
||||
"$Hello World\n",
|
||||
"$Hello and Merry Christmas to all of you!\n"
|
||||
};
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting Arduino Serial Test script..");
|
||||
Serial1.begin(115200);
|
||||
if(STRING_MODE == StringModes::VARIABLE) {
|
||||
STRING_IDX = 0;
|
||||
}
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static byte ICOMING_BYTE = 0;
|
||||
static uint32_t GLOBAL_IDX = 0;
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
// put your main code here, to run repeatedly:
|
||||
// send data only when you receive data:
|
||||
if (SEND_MODE == SendModes::ONLY_WRITE or SEND_MODE == SendModes::WRITE_READ) {
|
||||
Serial.println("Sending string..");
|
||||
Serial1.write(STRINGS[STRING_IDX].c_str());
|
||||
if(STRING_MODE == StringModes::VARIABLE) {
|
||||
STRING_IDX += 1;
|
||||
if(STRING_IDX > 3) {
|
||||
STRING_IDX = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(
|
||||
SEND_MODE == SendModes::WRITE_READ or
|
||||
SEND_MODE == SendModes::ONLY_READ or
|
||||
SEND_MODE == SendModes::ECHO
|
||||
) {
|
||||
if (Serial1.available() > 0) {
|
||||
// read the incoming byte:
|
||||
String readString = Serial1.readStringUntil('\n');
|
||||
|
||||
Serial.print(GLOBAL_IDX);
|
||||
Serial.print(" - ");
|
||||
GLOBAL_IDX++;
|
||||
// say what you got:
|
||||
Serial.print("I received: ");
|
||||
Serial.println(readString);
|
||||
if(SEND_MODE == SendModes::ECHO) {
|
||||
delay(200);
|
||||
Serial.println("Sending back echo message");
|
||||
String sendBack = readString + '\n';
|
||||
Serial1.write(sendBack.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
delay(3000);
|
||||
}
|
11
test/DueSerialTest/test/README
Normal file
11
test/DueSerialTest/test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
Reference in New Issue
Block a user