Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
F
f4
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Per Lindgren
f4
Commits
9933bf67
Commit
9933bf67
authored
7 years ago
by
Johannes Sjölund
Browse files
Options
Downloads
Patches
Plain Diff
Add macro for usart dma formatted print
parent
126193ea
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
examples/usart2-dma.rs
+61
-61
61 additions, 61 deletions
examples/usart2-dma.rs
src/lib.rs
+1
-1
1 addition, 1 deletion
src/lib.rs
src/serial.rs
+81
-33
81 additions, 33 deletions
src/serial.rs
with
143 additions
and
95 deletions
examples/usart2-dma.rs
+
61
−
61
View file @
9933bf67
...
@@ -7,13 +7,14 @@
...
@@ -7,13 +7,14 @@
#![no_std]
#![no_std]
extern
crate
cortex_m_rtfm
as
rtfm
;
extern
crate
cortex_m_rtfm
as
rtfm
;
#[macro_use]
extern
crate
f4
;
extern
crate
f4
;
extern
crate
heapless
;
extern
crate
heapless
;
use
core
::
fmt
::
Write
;
use
core
::
fmt
::
Write
;
use
core
::
ops
::
Deref
;
use
core
::
ops
::
Deref
;
use
f4
::
Serial
;
use
f4
::
Serial
;
use
f4
::
Writer
as
w
;
use
f4
::
U8
Writer
;
use
f4
::
prelude
::
*
;
use
f4
::
prelude
::
*
;
use
f4
::
dma
::{
Buffer
,
Dma1Channel5
,
Dma1Channel6
};
use
f4
::
dma
::{
Buffer
,
Dma1Channel5
,
Dma1Channel6
};
use
f4
::
time
::
Hertz
;
use
f4
::
time
::
Hertz
;
...
@@ -30,6 +31,12 @@ const MAX_RX_LEN: usize = 1;
...
@@ -30,6 +31,12 @@ const MAX_RX_LEN: usize = 1;
const
BAUD_RATE
:
Hertz
=
Hertz
(
115_200
);
const
BAUD_RATE
:
Hertz
=
Hertz
(
115_200
);
enum
CmdType
{
Greeting
,
Unknown
,
None
,
}
app!
{
app!
{
device
:
f4
::
stm32f40x
,
device
:
f4
::
stm32f40x
,
...
@@ -37,7 +44,7 @@ app! {
...
@@ -37,7 +44,7 @@ app! {
static
CMD_BUFFER
:
Vec
<
u8
,
[
u8
;
MAX_CMD_LEN
]
>
=
Vec
::
new
([
0
;
MAX_CMD_LEN
]);
static
CMD_BUFFER
:
Vec
<
u8
,
[
u8
;
MAX_CMD_LEN
]
>
=
Vec
::
new
([
0
;
MAX_CMD_LEN
]);
static
RX_BUFFER
:
Buffer
<
[
u8
;
MAX_RX_LEN
],
Dma1Channel5
>
=
Buffer
::
new
([
0
;
MAX_RX_LEN
]);
static
RX_BUFFER
:
Buffer
<
[
u8
;
MAX_RX_LEN
],
Dma1Channel5
>
=
Buffer
::
new
([
0
;
MAX_RX_LEN
]);
static
TX_BUFFER
:
Buffer
<
[
u8
;
MAX_TX_LEN
],
Dma1Channel6
>
=
Buffer
::
new
([
0
;
MAX_TX_LEN
]);
static
TX_BUFFER
:
Buffer
<
[
u8
;
MAX_TX_LEN
],
Dma1Channel6
>
=
Buffer
::
new
([
0
;
MAX_TX_LEN
]);
static
CNT
:
u8
=
1
;
static
CNT
:
u8
=
0
;
},
},
tasks
:
{
tasks
:
{
...
@@ -54,40 +61,12 @@ app! {
...
@@ -54,40 +61,12 @@ app! {
},
},
}
}
fn
init
(
p
:
init
::
Peripherals
,
r
:
init
::
Resources
)
{
// Set clock to higher than default in order to test it works
clock
::
set_84_mhz
(
&
p
.RCC
,
&
p
.FLASH
);
// There is no need to claim() resources in the init.
// Start the serial port
let
serial
=
Serial
(
p
.USART2
);
serial
.init
(
BAUD_RATE
.invert
(),
Some
(
p
.DMA1
),
p
.GPIOA
,
p
.RCC
);
// Send a welcome message by borrowing transmit buffer and writing a formatted string into it
let
x
=
1.0
;
write!
(
w
::
out
(
&
mut
r
.TX_BUFFER
.borrow_mut
()[
..
MAX_TX_LEN
]),
"Hello, world! {}
\r\n
"
,
x
)
.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
();
}
fn
idle
()
->
!
{
loop
{
rtfm
::
wfi
();
}
}
// Interrupt for serial receive DMA
// Interrupt for serial receive DMA
fn
rx_done
(
t
:
&
mut
Threshold
,
mut
r
:
DMA1_STREAM5
::
Resources
)
{
fn
rx_done
(
t
:
&
mut
Threshold
,
mut
r
:
DMA1_STREAM5
::
Resources
)
{
use
rtfm
::
Resource
;
use
rtfm
::
Resource
;
let
mut
byte
:
u8
=
0
;
let
mut
byte
:
u8
=
0
;
let
mut
say_hello
=
fals
e
;
let
mut
cmd_type
:
CmdType
=
CmdType
::
Non
e
;
r
.RX_BUFFER
.claim
(
t
,
|
rx
,
t
|
{
r
.RX_BUFFER
.claim
(
t
,
|
rx
,
t
|
{
// We need to unlock the DMA to use it again in the future
// We need to unlock the DMA to use it again in the future
...
@@ -117,45 +96,38 @@ fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
...
@@ -117,45 +96,38 @@ fn rx_done(t: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
r
.CMD_BUFFER
.claim_mut
(
t
,
|
cmd
,
_
|
{
r
.CMD_BUFFER
.claim_mut
(
t
,
|
cmd
,
_
|
{
if
byte
==
b'\r'
{
if
byte
==
b'\r'
{
// End of command
// End of command
match
&***
cmd
{
cmd_type
=
match
&***
cmd
{
b"hi"
|
b"Hi"
=>
{
b"hi"
|
b"Hi"
=>
CmdType
::
Greeting
,
say_hello
=
true
;
_
=>
{
if
cmd
.len
()
==
0
{
CmdType
::
None
// Empty string
}
else
{
CmdType
::
Unknown
// Unknown string
}
}
_
=>
{}
}
}
};
cmd
.clear
();
cmd
.clear
();
}
else
{
}
else
{
if
cmd
.push
(
byte
)
.is_err
()
{
if
cmd
.push
(
byte
)
.is_err
()
{
// Error: buffer full
// Error: command buffer is full
// KISS: we just clear the buffer when it gets full
cmd
.clear
();
cmd
.clear
();
}
}
}
}
});
});
// If user wrote 'hi' and pressed enter, respond appropriately
// If user wrote 'hi' and pressed enter, respond appropriately
if
say_hello
{
match
cmd_type
{
CmdType
::
Greeting
=>
{
// Increment 'hi' counter
// Increment 'hi' counter
**
r
.CNT
=
**
r
.CNT
+
1
;
**
r
.CNT
=
(
**
r
.CNT
)
.wrapping_add
(
1
)
;
let
cnt
:
u8
=
**
r
.CNT
;
let
cnt
:
u8
=
**
r
.CNT
;
// Claim the transmit buffer and write a formatted string into it
// Print a response using DMA
r
.TX_BUFFER
.claim_mut
(
t
,
|
tx
,
_
|
{
uprint!
(
t
,
r
.USART2
,
r
.DMA1
,
r
.TX_BUFFER
,
"Hi counter {}!
\r\n
"
,
cnt
);
write!
(
}
w
::
out
(
&
mut
(
*
tx
)
.deref
()
.borrow_mut
()[
..
MAX_TX_LEN
]),
CmdType
::
Unknown
=>
{
"Hello, there! {}
\r\n
"
,
// Unknown command
cnt
uprint!
(
t
,
r
.USART2
,
r
.DMA1
,
r
.TX_BUFFER
,
"That's no greeting.
\r\n
"
);
)
.unwrap
();
}
});
_
=>
{}
// Transmit the response
r
.TX_BUFFER
.claim
(
t
,
|
tx
,
t
|
{
r
.DMA1
.claim
(
t
,
|
dma
,
t
|
{
r
.USART2
.claim
(
t
,
|
usart
,
_
|
{
let
serial
=
Serial
(
&**
usart
);
serial
.write_all
(
dma
,
tx
)
.unwrap
();
});
});
});
// r.CNT.claim_mut(t, |cnt,_| cnt.wrapping_add(1));
}
}
}
}
...
@@ -172,3 +144,31 @@ fn tx_done(t: &mut Threshold, r: DMA1_STREAM6::Resources) {
...
@@ -172,3 +144,31 @@ fn tx_done(t: &mut Threshold, r: DMA1_STREAM6::Resources) {
array
.borrow_mut
()[
..
MAX_TX_LEN
]
.clone_from_slice
(
&
[
0
;
MAX_TX_LEN
]);
array
.borrow_mut
()[
..
MAX_TX_LEN
]
.clone_from_slice
(
&
[
0
;
MAX_TX_LEN
]);
});
});
}
}
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
);
// 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
();
}
fn
idle
()
->
!
{
loop
{
rtfm
::
wfi
();
}
}
This diff is collapsed.
Click to expand it.
src/lib.rs
+
1
−
1
View file @
9933bf67
...
@@ -50,7 +50,7 @@ use frequency::*;
...
@@ -50,7 +50,7 @@ use frequency::*;
pub
use
hal
::
prelude
;
pub
use
hal
::
prelude
;
pub
use
serial
::
Serial
;
pub
use
serial
::
Serial
;
pub
use
serial
::
Writer
;
pub
use
serial
::
U8
Writer
;
pub
use
timer
::{
Channel
,
Timer
};
pub
use
timer
::{
Channel
,
Timer
};
pub
use
pwm
::
Pwm
;
pub
use
pwm
::
Pwm
;
pub
use
capture
::
Capture
;
pub
use
capture
::
Capture
;
...
...
This diff is collapsed.
Click to expand it.
src/serial.rs
+
81
−
33
View file @
9933bf67
...
@@ -23,37 +23,6 @@ use dma::{self, Buffer, Dma1Channel5, Dma1Channel6};
...
@@ -23,37 +23,6 @@ use dma::{self, Buffer, Dma1Channel5, Dma1Channel6};
use
core
::
fmt
;
use
core
::
fmt
;
///
pub
struct
Writer
<
'a
>
{
buf
:
&
'a
mut
[
u8
],
offset
:
usize
,
}
impl
<
'a
>
Writer
<
'a
>
{
///
pub
fn
out
(
buf
:
&
'a
mut
[
u8
])
->
Self
{
Writer
{
buf
:
buf
,
offset
:
0
,
}
}
}
impl
<
'a
>
fmt
::
Write
for
Writer
<
'a
>
{
fn
write_str
(
&
mut
self
,
s
:
&
str
)
->
fmt
::
Result
{
let
bytes
=
s
.as_bytes
();
// Skip over already-copied data
let
remainder
=
&
mut
self
.buf
[
self
.offset
..
];
// Make the two slices the same length
let
remainder
=
&
mut
remainder
[
..
bytes
.len
()];
// Copy
remainder
.copy_from_slice
(
bytes
);
// Increment offset by number of copied bytes
self
.offset
+=
bytes
.len
();
Ok
(())
}
}
/// Specialized `Result` type
/// Specialized `Result` type
pub
type
Result
<
T
>
=
::
core
::
result
::
Result
<
T
,
nb
::
Error
<
Error
>>
;
pub
type
Result
<
T
>
=
::
core
::
result
::
Result
<
T
,
nb
::
Error
<
Error
>>
;
...
@@ -153,9 +122,13 @@ where
...
@@ -153,9 +122,13 @@ where
if
usart
.get_type_id
()
==
TypeId
::
of
::
<
USART2
>
()
{
if
usart
.get_type_id
()
==
TypeId
::
of
::
<
USART2
>
()
{
// we don't care about the speed register atm
// we don't care about the speed register atm
// DM00102166
// DM00102166
// AF7, Table 9
// PA2 and PA3 is connected to USART2 TX and RX respectively
// PA2 and PA3 is connected to USART2 TX and RX respectively
// Alternate function AF7, Table 9
gpio
.afrl
.modify
(|
_
,
w
|
w
.afrl2
()
.bits
(
7
)
.afrl3
()
.bits
(
7
));
gpio
.afrl
.modify
(|
_
,
w
|
w
.afrl2
()
.bits
(
7
)
.afrl3
()
.bits
(
7
));
// Highest output speed
gpio
.ospeedr
.modify
(|
_
,
w
|
w
.ospeedr2
()
.bits
(
0b11
)
.ospeedr3
()
.bits
(
0b11
));
// RM0368 8.3 Table 23
gpio
.moder
gpio
.moder
.modify
(|
_
,
w
|
w
.moder2
()
.bits
(
2
)
.moder3
()
.bits
(
2
));
.modify
(|
_
,
w
|
w
.moder2
()
.bits
(
2
)
.moder3
()
.bits
(
2
));
}
}
...
@@ -322,7 +295,9 @@ where
...
@@ -322,7 +295,9 @@ where
}
else
if
sr
.rxne
()
.bit_is_set
()
{
}
else
if
sr
.rxne
()
.bit_is_set
()
{
// NOTE(read_volatile) the register is 9 bits big but we'll only
// NOTE(read_volatile) the register is 9 bits big but we'll only
// work with the first 8 bits
// work with the first 8 bits
Ok
(
unsafe
{
ptr
::
read_volatile
(
&
usart2
.dr
as
*
const
_
as
*
const
u8
)
})
Ok
(
unsafe
{
ptr
::
read_volatile
(
&
usart2
.dr
as
*
const
_
as
*
const
u8
)
})
}
else
{
}
else
{
Err
(
nb
::
Error
::
WouldBlock
)
Err
(
nb
::
Error
::
WouldBlock
)
}
}
...
@@ -421,3 +396,76 @@ impl<'a> Serial<'a, USART2> {
...
@@ -421,3 +396,76 @@ impl<'a> Serial<'a, USART2> {
Ok
(())
Ok
(())
}
}
}
}
///
pub
struct
U8Writer
<
'a
>
{
buf
:
&
'a
mut
[
u8
],
offset
:
usize
,
}
impl
<
'a
>
U8Writer
<
'a
>
{
///
pub
fn
new
(
buf
:
&
'a
mut
[
u8
])
->
Self
{
U8Writer
{
buf
:
buf
,
offset
:
0
,
}
}
}
impl
<
'a
>
fmt
::
Write
for
U8Writer
<
'a
>
{
fn
write_str
(
&
mut
self
,
s
:
&
str
)
->
fmt
::
Result
{
let
bytes
=
s
.as_bytes
();
// Skip over already-copied data
let
remainder
=
&
mut
self
.buf
[
self
.offset
..
];
// Make the two slices the same length
let
remainder
=
&
mut
remainder
[
..
bytes
.len
()];
// Copy
remainder
.copy_from_slice
(
bytes
);
// Increment offset by number of copied bytes
self
.offset
+=
bytes
.len
();
Ok
(())
}
}
/// Macro for printing formatted strings over serial through DMA.
/// Uses the corted-m-rtfm resource model and can thus not be used
/// outside rtfm tasks.
#[macro_export]
macro_rules!
uprint
{
(
$T:ident
,
$USART:expr
,
$DMA:expr
,
$TX_BUFFER:expr
,
$s:expr
)
=>
{
use
core
::
fmt
::
Write
;
// Claim the transmit buffer and write a string literal into it
$TX_BUFFER
.claim_mut
(
$T
,
|
tx
,
_
|
{
let
len
=
(
*
tx
)
.deref
()
.borrow
()
.len
();
let
buf
=
&
mut
(
*
tx
)
.deref
()
.borrow_mut
();
write!
(
U8Writer
::
new
(
&
mut
buf
[
..
len
]),
$s
)
.unwrap
();
});
// Transmit the contents of the buffer using DMA
$TX_BUFFER
.claim
(
$T
,
|
tx
,
t
|
{
$DMA
.claim
(
t
,
|
dma
,
t
|
{
$USART
.claim
(
t
,
|
usart
,
_
|
{
let
serial
=
Serial
(
&**
usart
);
serial
.write_all
(
dma
,
tx
)
.unwrap
();
});
});
});
};
(
$T:ident
,
$USART:expr
,
$DMA:expr
,
$TX_BUFFER:expr
,
$
(
$arg:tt
)
*
)
=>
{
use
core
::
fmt
::
Write
;
// Claim the transmit buffer and write a formatted string into it
$TX_BUFFER
.claim_mut
(
$T
,
|
tx
,
_
|
{
let
len
=
(
*
tx
)
.deref
()
.borrow
()
.len
();
let
buf
=
&
mut
(
*
tx
)
.deref
()
.borrow_mut
();
write!
(
U8Writer
::
new
(
&
mut
buf
[
..
len
]),
$
(
$arg
)
*
)
.unwrap
();
});
// Transmit the contents of the buffer using DMA
$TX_BUFFER
.claim
(
$T
,
|
tx
,
t
|
{
$DMA
.claim
(
t
,
|
dma
,
t
|
{
$USART
.claim
(
t
,
|
usart
,
_
|
{
let
serial
=
Serial
(
&**
usart
);
serial
.write_all
(
dma
,
tx
)
.unwrap
();
});
});
});
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment