Skip to content
Snippets Groups Projects
Commit ab54bad0 authored by Joakim Lundberg's avatar Joakim Lundberg
Browse files

RTFM v2 'working'

parent e5591027
No related branches found
No related tags found
No related merge requests found
target remote :3333
target remote 192.168.1.4:3333
monitor reset init
monitor arm semihosting enable
monitor tpiu config internal /tmp/itm.log uart off 84000000
monitor itm port 0 on
load
load target/thumbv7em-none-eabihf/debug/d7018e_coap
monitor reset init
{
// 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": [
{
"type": "gdb",
"request": "attach",
"name": "Debug embedded",
"usewsl": true,
"gdbpath": "arm-none-eabi-gdb",
"executable": "./target/thumbv7em-none-eabihf/debug/d7018e_coap",
"target": "192.168.1.4:3333",
"remote": true,
"autorun": [
"monitor reset init",
"load",
"monitor reset init"
],
"cwd": "${workspaceRoot}"
},
]
}
\ No newline at end of file
......@@ -15,9 +15,10 @@ cortex-m-semihosting = "0.2.0"
static-ref = "0.2.0"
volatile-register = "0.2.0"
m = "0.1.1"
heapless = "0.2.1"
heapless = "0.2.4"
f4 = {git = "https://github.com/jsjolund/f4"}
xoap = { path = "../projects/xoap", version = "0.1.0", default-features = false, features = ["baremetal"] }#git = "https://github.com/Shawnshank/xoap", version = "0.1.0"}
stm32f40x = "0.2.0"
#xoap = { path = "../projects/xoap", version = "0.1.0", default-features = false, features = ["baremetal"] }# git = "https://github.com/Shawnshank/xoap"
[dependencies.cast]
default-features = false
......
......@@ -2,8 +2,8 @@ MEMORY
{
/* NOTE K = KiBi = 1024 bytes */
/* TODO Adjust these memory regions to match your device memory layout */
FLASH : ORIGIN = 0x08000000, LENGTH = 512K
RAM : ORIGIN = 0x20000000, LENGTH = 96K
FLASH : ORIGIN = 0x08000000, LENGTH = 511K
RAM : ORIGIN = 0x20000000, LENGTH = 128K
}
/* This is where the call stack will be allocated. */
......
//! Prints "Hello" and then "World" in the OpenOCD console
//! Test sending messages and receiving commands using the DMA
#![deny(unsafe_code)]
#![deny(warnings)]
#![allow(dead_code)]
#![allow(non_snake_case)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![feature(lang_items)]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
//extern crate cortex_m_semihosting as semihosting;
#[macro_use]
extern crate f4;
extern crate heapless;
extern crate xoap;
extern crate stm32f40x;
use core::fmt::Write;
use core::ops::Deref;
......@@ -20,22 +22,38 @@ use f4::U8Writer;
use f4::prelude::*;
use f4::dma::{Buffer, Dma1Stream5, Dma1Stream6};
use f4::time::Hertz;
//use f4::Timer;
use f4::clock;
use f4::I2c;
use heapless::Vec;
use rtfm::{app, Threshold};
//use semihosting::hio::{self, HStdout};
//use core::result::Result;
//use f4::stm32f40x::I2C1;
// Max length of a command to be parsed.
const MAX_CMD_LEN: usize = 10;
// Max length of an output string that can be sent.
const MAX_TX_LEN: usize = 100;
// Max length of input buffer. Since we are parsing for commands, we need to check each received character.
const MAX_RX_LEN: usize = 100;
const BAUD_RATE: Hertz = Hertz(115_200);
const MAX_RX_LEN: usize = 1;
// Baud rate of the serial interface
const BAUD_RATE: Hertz = Hertz(9_600);
// Temperature and humidity update frequency
const SENSOR_READ_TIME: Hertz = Hertz(1);
//const DATA_RECIEVE_SIZE: usize = 4;
const RX_BUFFER_SIZE: usize = core::mem::size_of::<u32>();
// Errors from the HIH6030-021-001
#[derive(Debug)]
pub enum Error {
StaleData,
CommandMode,
Unknown,
}
// Command types from the serial interface
enum CmdType {
Greeting,
Data,
Unknown,
None,
}
......@@ -48,22 +66,62 @@ app! {
static RX_BUFFER: Buffer<[u8; MAX_RX_LEN], Dma1Stream5> = Buffer::new([0; MAX_RX_LEN]);
static TX_BUFFER: Buffer<[u8; MAX_TX_LEN], Dma1Stream6> = Buffer::new([0; MAX_TX_LEN]);
static CNT: u8 = 0;
// static CMD: CmdType = CmdType::None;
static TEMPERATURE: f32 = 0.0;
static HUMIDITY: f32 = 0.0;
},
tasks: {
DMA1_STREAM5: {
path: rx_done,
priority: 1,
resources: [CMD_BUFFER, RX_BUFFER, TX_BUFFER, DMA1, USART2, CNT],
resources: [CMD_BUFFER, RX_BUFFER, TX_BUFFER, DMA1, USART2, CNT, TEMPERATURE, HUMIDITY], // include CMD
},
DMA1_STREAM6: {
path: tx_done,
priority: 2,
resources: [TX_BUFFER, DMA1],
},
/*TIM2: {
path: read_sensor,
priority: 3,
resources: [TIM2, I2C1, TEMPERATURE, HUMIDITY],
},*/
},
}
fn init(p: init::Peripherals, r: init::Resources) {
// Set clock to higher than default in order to test that it works
clock::set_84_mhz(&p.RCC, &p.FLASH);
// Start the serial port
let serial = Serial(p.USART2);
serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
// Start the I2C peripheral
let i2c = I2c(p.I2C1);
i2c.init(p.GPIOA, p.GPIOB, p.RCC);
i2c.enable();
// Start the timer for the update of the Temp/RH sensor.
/*let timer = Timer(&*p.TIM2);
timer.init(SENSOR_READ_TIME.invert(), p.RCC);
timer.resume();
*/
// FIXME: We cannot use the uprint macro in the init since it needs Resources
// and Threshold...
// Send a welcome message by borrowing a slice of the transmit buffer and
// writing a formatted string into it.
write!(
U8Writer::new(&mut r.TX_BUFFER.borrow_mut()[..MAX_TX_LEN]),
"Hello, world! Say hi to me!\r\n",
).unwrap();
serial.write_all(p.DMA1, r.TX_BUFFER).unwrap();
// Listen to serial input on the receive DMA
serial.read_exact(p.DMA1, r.RX_BUFFER).unwrap();
}
// Interrupt for serial receive DMA
fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
use rtfm::Resource;
......@@ -81,7 +139,7 @@ fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
r.USART2.claim(t, |usart, t| {
let serial = Serial(&**usart);
if serial.write(byte).is_err() {
rtfm::bkpt();
//rtfm::bkpt();
}
if byte == b'\r' {
// If we got carrige return, send new line as well
......@@ -101,6 +159,7 @@ fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
// End of command
cmd_type = match &***cmd {
b"hi" | b"Hi" => CmdType::Greeting,
b"data" => CmdType::Data,
_ => {
if cmd.len() == 0 {
CmdType::None // Empty string
......@@ -127,6 +186,11 @@ fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
// Print a response using DMA
uprint!(t, r.USART2, r.DMA1, r.TX_BUFFER, "Hi counter {}!\r\n", cnt);
}
CmdType::Data => {
//let test: u8 = **r.TEMPERATURE;
uprint!(t, r.USART2, r.DMA1, r.TX_BUFFER, "Temp:!\r\n");
}
CmdType::Unknown => {
// Unknown command
uprint!(t, r.USART2, r.DMA1, r.TX_BUFFER, "That's no greeting.\r\n");
......@@ -149,27 +213,64 @@ fn tx_done(t: &mut Threshold, r: DMA1_STREAM6::Resources) {
});
}
fn init(_p: init::Peripherals, r: init::Resources) {
// Set clock to higher than default in order to test that it works
clock::set_84_mhz(&_p.RCC, &_p.FLASH);
/*
// Interrupt for the timer for the update of the Temp/RH sensor
fn read_sensor(_t: &mut Threshold, r: TIM2::Resources) {
// Clear the interrupt flag
r.TIM2.sr.modify(|_, w| w.uif().clear_bit());
// I2C interface.
let i2c = I2c(&**r.I2C1);
// Read back to check that it worked
let mut rx: [u8; RX_BUFFER_SIZE] = [0; RX_BUFFER_SIZE];
match get_data(&i2c, &mut rx) {
Err(_) => {}
Ok(_) => {
// Calculate temperature and store the value in the resources
let mut _temp: f32 = (((rx[2] << 6) | (rx[3] >> 2)) as f32) * 100.0 / 16382.0;
//let mut _temp: f32 = (_T as f32) * 100.0 / 16382.0;
**r.TEMPERATURE = _temp;
// Calculate humidity and store the value in the resources
let mut _RH: f32 = (((rx[2] << 6) | (rx[3] >> 2)) as f32) * 165.0 / 16382.0 - 40.0;
**r.HUMIDITY = _RH;
}
}
}
// Start the serial port
let serial = Serial(_p.USART2);
serial.init(BAUD_RATE.invert(), Some(_p.DMA1), _p.GPIOA, _p.RCC);
// Gets the data from the Temp/RH sensor over the I2C bus
fn get_data(i2c: &I2c<I2C1>, rx_buffer: &mut [u8; RX_BUFFER_SIZE]) -> Result<(), Error> {
while i2c.start(0x4E).is_err() {} // 0x4E - write (2*27), 0x4F - Read (2*27)+1
//while i2c.write(0).is_err() {}
while i2c.stop().is_err() {}
// FIXME: We cannot use the uprint macro in the init since it needs Resources
// and Threshold...
// Send a welcome message by borrowing a slice of the transmit buffer and
// writing a formatted string into it.
write!(
U8Writer::new(&mut r.TX_BUFFER.borrow_mut()[..MAX_TX_LEN]),
"Hello, world! Say hi to me!\r\n",
).unwrap();
serial.write_all(_p.DMA1, r.TX_BUFFER).unwrap();
// Read incoming bytes and ACK them
while i2c.start(0x4F).is_err() {}
for i in 0..RX_BUFFER_SIZE {
rx_buffer[i] = loop {
if i == RX_BUFFER_SIZE - 1 {
// Do not ACK the last byte received and send STOP
if let Ok(byte) = i2c.read_nack() {
break byte;
}
} else {
// ACK the byte after receiving
if let Ok(byte) = i2c.read_ack() {
break byte;
}
}
}
}
while i2c.stop().is_err() {}
// Listen to serial input on the receive DMA
serial.read_exact(_p.DMA1, r.RX_BUFFER).unwrap();
let status: u8 = (rx_buffer[0] & 0xC0) >> 6;
match status {
0 => Ok(()),
1 => Err(Error::StaleData),
2 => Err(Error::CommandMode),
3 => Err(Error::Unknown),
_ => Err(Error::Unknown),
}
}
*/
fn idle() -> ! {
loop {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment