mirror of
https://github.com/rfivet/stm32bringup.git
synced 2025-10-16 16:04:01 -04:00
Documentation: Replace ambiguous unicode by corresponding ANSI.
Typo it's/its. Introduce Section 4.
This commit is contained in:
@@ -98,7 +98,7 @@ defining <b>GCCDIR</b> as some sub-processes called by <b><i>gmake</i></b> may
|
|||||||
have issues with <b>~</b> expansion (in this case <i>ld</i>). This way
|
have issues with <b>~</b> expansion (in this case <i>ld</i>). This way
|
||||||
<b><i>gmake</i></b> will handle the expansion before calling the sub-processes.
|
<b><i>gmake</i></b> will handle the expansion before calling the sub-processes.
|
||||||
|
|
||||||
<h2>Toolchain’s chain of events</h2>
|
<h2>Toolchain's chain of events</h2>
|
||||||
In order to generate a file that can be loaded in the micro-controller, I
|
In order to generate a file that can be loaded in the micro-controller, I
|
||||||
need to sketch the chain of events that will take place.
|
need to sketch the chain of events that will take place.
|
||||||
<ol>
|
<ol>
|
||||||
|
@@ -73,7 +73,7 @@ SECTIONS
|
|||||||
From this snippet I can see that not only flash and ram parameters but also
|
From this snippet I can see that not only flash and ram parameters but also
|
||||||
the entry point for code execution, <b>Reset_Handler</b>, needs to be provided.
|
the entry point for code execution, <b>Reset_Handler</b>, needs to be provided.
|
||||||
<p>
|
<p>
|
||||||
As a check, let’s change the link script to <b>nokeep.ld</b> in <b>Makefile</b>
|
As a check, let's change the link script to <b>nokeep.ld</b> in <b>Makefile</b>
|
||||||
and generate an executable <b>.elf</b> from the empty source code file
|
and generate an executable <b>.elf</b> from the empty source code file
|
||||||
<b>empty.c</b>:
|
<b>empty.c</b>:
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ rm empty.o
|
|||||||
|
|
||||||
The linker gives a warning and fallback on a default address as entry point.
|
The linker gives a warning and fallback on a default address as entry point.
|
||||||
<p>
|
<p>
|
||||||
So let’s create <b>boot.c</b> with an idle loop as <b>Reset_Handler</b>:
|
So let's create <b>boot.c</b> with an idle loop as <b>Reset_Handler</b>:
|
||||||
<pre>
|
<pre>
|
||||||
void Reset_Handler( void) {
|
void Reset_Handler( void) {
|
||||||
for( ;;) ;
|
for( ;;) ;
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>1.3 Flash – Boot – Debug</title>
|
<title>1.3 Flash - Boot - Debug</title>
|
||||||
<link type="text/css" rel="stylesheet" href="style.css">
|
<link type="text/css" rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>1.3 Flash – Boot – Debug</h1>
|
<h1>1.3 Flash - Boot - Debug</h1>
|
||||||
|
|
||||||
Now that I have an executable bootstrap, I need to flash an actual board
|
Now that I have an executable bootstrap, I need to flash an actual board
|
||||||
with it to check if it works as expected. On a member of the STM32F030
|
with it to check if it works as expected. On a member of the STM32F030
|
||||||
@@ -48,7 +48,7 @@ Referenced as
|
|||||||
<a href="https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stm32cubeprog.html">
|
<a href="https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stm32cubeprog.html">
|
||||||
STM32CubeProg</a>
|
STM32CubeProg</a>
|
||||||
on STMicroelectronics website, the STM32 Cube Programmer comes with USB
|
on STMicroelectronics website, the STM32 Cube Programmer comes with USB
|
||||||
drivers and a firmware upgrade utility for the ST-Link. It’s a java
|
drivers and a firmware upgrade utility for the ST-Link. It's a java
|
||||||
based application with available distribution for Win32, Win64, Mac and Linux.
|
based application with available distribution for Win32, Win64, Mac and Linux.
|
||||||
There are regular updates to support the latest chipsets. I am currently
|
There are regular updates to support the latest chipsets. I am currently
|
||||||
using version v2.17.0.
|
using version v2.17.0.
|
||||||
|
@@ -88,7 +88,7 @@ through the frames gives me a better estimation.
|
|||||||
|
|
||||||
<h2>Checkpoint</h2>
|
<h2>Checkpoint</h2>
|
||||||
|
|
||||||
This is just a small increment on my previous step, but that’s iterative
|
This is just a small increment on my previous step, but that's iterative
|
||||||
development in a nutshell. Also I didn't come with a reasonable value
|
development in a nutshell. Also I didn't come with a reasonable value
|
||||||
for the delay counter at first, it's easy to underestimate how fast
|
for the delay counter at first, it's easy to underestimate how fast
|
||||||
micro-controllers are.
|
micro-controllers are.
|
||||||
|
@@ -8,12 +8,12 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>1.6 The Tick</h1>
|
<h1>1.6 The Tick</h1>
|
||||||
|
|
||||||
<img alt="It’s blue! It blinks! It’s the Tick!" src="img/16_tick.png">
|
<img alt="It's blue! It blinks! It's the Tick!" src="img/16_tick.png">
|
||||||
<p>
|
<p>
|
||||||
In previous iteration, I made the user LED blink using an active delay
|
In previous iteration, I made the user LED blink using an active delay
|
||||||
loop. I have two issues with this implementation:
|
loop. I have two issues with this implementation:
|
||||||
<ul>
|
<ul>
|
||||||
<li> It’s hard to control the delay timing accurately
|
<li> It's hard to control the delay timing accurately
|
||||||
</ul><ul>
|
</ul><ul>
|
||||||
<li> Active loops are not cool
|
<li> Active loops are not cool
|
||||||
</ul>
|
</ul>
|
||||||
@@ -34,7 +34,7 @@ while( enabled) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
It’s an auto decremented counter that reloads and sets a flag when
|
It's an auto decremented counter that reloads and sets a flag when
|
||||||
reaching zero. It can trigger a system interrupt if requested to. Its
|
reaching zero. It can trigger a system interrupt if requested to. Its
|
||||||
default clock is the processor clock and can be switched to external
|
default clock is the processor clock and can be switched to external
|
||||||
clock. Details can be found in the Programming Manual as this is part of
|
clock. Details can be found in the Programming Manual as this is part of
|
||||||
@@ -50,7 +50,7 @@ from <b>Reset_Handler</b> to <b>SysTick_Handler</b>.
|
|||||||
</ul><ul>
|
</ul><ul>
|
||||||
<li> Introduce the <b>SysTick</b> core peripheral to the compiler, using
|
<li> Introduce the <b>SysTick</b> core peripheral to the compiler, using
|
||||||
pre-processor macroes to give the location of SysTick registers. As this
|
pre-processor macroes to give the location of SysTick registers. As this
|
||||||
is a core peripheral, it’s in a different address space than the
|
is a core peripheral, it's in a different address space than the
|
||||||
peripherals I have seen so far.
|
peripherals I have seen so far.
|
||||||
</ul><ul>
|
</ul><ul>
|
||||||
<li> Start the <b>Reset_Handler</b> by initializing and enabling the System
|
<li> Start the <b>Reset_Handler</b> by initializing and enabling the System
|
||||||
@@ -126,7 +126,7 @@ void SysTick_Handler( void) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
I didn’t initialize the GPIO B before enabling the SysTick as I have a
|
I didn't initialize the GPIO B before enabling the SysTick as I have a
|
||||||
whole second before the first interrupt will tick in.
|
whole second before the first interrupt will tick in.
|
||||||
<p>
|
<p>
|
||||||
Build is straightforward.
|
Build is straightforward.
|
||||||
|
@@ -205,8 +205,8 @@ If I look further in the <b>cstartup.map</b> generated by the linker.
|
|||||||
|
|
||||||
<li> <code>i</code> is located in <b>.bss</b> at 0x20000008
|
<li> <code>i</code> is located in <b>.bss</b> at 0x20000008
|
||||||
|
|
||||||
<li> <code>c</code> is not listed as it doesn’t have global scope, but I can
|
<li> <code>c</code> is not listed as it doesn't have global scope, but I can
|
||||||
guess it’s located at 0x20000000.
|
guess it's located at 0x20000000.
|
||||||
|
|
||||||
<li> Initial values for the <b>.data</b> section are located at 0x0800007c.
|
<li> Initial values for the <b>.data</b> section are located at 0x0800007c.
|
||||||
</ul>
|
</ul>
|
||||||
|
@@ -251,7 +251,7 @@ Building shows an increase in code, still no data.
|
|||||||
<p>
|
<p>
|
||||||
Once <b>f030f4.hex</b> is loaded into the board, the behavior is the same
|
Once <b>f030f4.hex</b> is loaded into the board, the behavior is the same
|
||||||
as <b>ledtick.hex</b>. The new file structure and data initialization
|
as <b>ledtick.hex</b>. The new file structure and data initialization
|
||||||
didn’t introduce any <del>bugs</del> changes, just code overhead.
|
didn't introduce any <del>bugs</del> changes, just code overhead.
|
||||||
|
|
||||||
<h2>Checkpoint</h2>
|
<h2>Checkpoint</h2>
|
||||||
|
|
||||||
|
@@ -15,13 +15,13 @@ to validate that I have working hardware and software tools.
|
|||||||
<h2>Board Connectivity</h2>
|
<h2>Board Connectivity</h2>
|
||||||
|
|
||||||
Even if the peripheral is capable of doing synchronous communication
|
Even if the peripheral is capable of doing synchronous communication
|
||||||
(that’s the S in USART), asynchronous communication (that’s the A) which
|
(that's the S in USART), asynchronous communication (that’s the A) which
|
||||||
only needs 3 wires (GND, TX, RX, (no clock)) is usually what is needed
|
only needs 3 wires (GND, TX, RX, (no clock)) is usually what is needed
|
||||||
in non specialized cases.
|
in non specialized cases.
|
||||||
<p>
|
<p>
|
||||||
Boards sold online often have dedicated pre-soldered pins for UART
|
Boards sold online often have dedicated pre-soldered pins for UART
|
||||||
connectivity similar to what I have seen before for the SWD interface.
|
connectivity similar to what I have seen before for the SWD interface.
|
||||||
The VCC-GND board I used previously doesn’t have such dedicated pins but the
|
The VCC-GND board I used previously doesn't have such dedicated pins but the
|
||||||
functionality is wired on the pins PA9 (<b>TX</b>) and PA10 (<b>RX</b>).
|
functionality is wired on the pins PA9 (<b>TX</b>) and PA10 (<b>RX</b>).
|
||||||
<p>
|
<p>
|
||||||
I will use a board with dedicated pins (GND, TX, RX, VCC 3.3V). Board
|
I will use a board with dedicated pins (GND, TX, RX, VCC 3.3V). Board
|
||||||
|
@@ -58,7 +58,7 @@ refer directly to <code>GPIO( LED_IOP)[ MODER]</code>.
|
|||||||
I use conditional compilation based on <code>LED_ON</code>. If
|
I use conditional compilation based on <code>LED_ON</code>. If
|
||||||
<code>LED_ON</code> is high, I need an extra step during initialization
|
<code>LED_ON</code> is high, I need an extra step during initialization
|
||||||
compare to <code>LED_ON</code> low. On the other hand, if <code>LED_ON</code>
|
compare to <code>LED_ON</code> low. On the other hand, if <code>LED_ON</code>
|
||||||
is undefined, the code would be removed for a board that doesn’t have a user
|
is undefined, the code would be removed for a board that doesn't have a user
|
||||||
LED.
|
LED.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>2.3 Hello There!</h1>
|
<h1>2.3 Hello There!</h1>
|
||||||
|
|
||||||
Looking for a <i>“you had me at hello”</i> moment? Let’s see how serial
|
Looking for a <i>“you had me at hello”</i> moment? Let's see how serial
|
||||||
transmission works for you.
|
transmission works for you.
|
||||||
|
|
||||||
<h2>Implementation</h2>
|
<h2>Implementation</h2>
|
||||||
@@ -55,11 +55,11 @@ To check if it is ready for transmission you must check the state of the
|
|||||||
TX Empty (<b>TXE</b>) bit in the Interrupt & Status Register (<b>ISR</b>).
|
TX Empty (<b>TXE</b>) bit in the Interrupt & Status Register (<b>ISR</b>).
|
||||||
<p>
|
<p>
|
||||||
I write a basic <code>kputc()</code> function that does busy waiting if the
|
I write a basic <code>kputc()</code> function that does busy waiting if the
|
||||||
<b>TDR</b> is not empty and insures that LF are mapped to CR LF. The ‘k’ in
|
<b>TDR</b> is not empty and insures that LF are mapped to CR LF. The 'k' in
|
||||||
kputc refer to ‘kernel’, as kputc is a low level function that will be used
|
kputc refer to 'kernel', as kputc is a low level function that will be used
|
||||||
mostly for debugging. With the busy wait and the recursive code this
|
mostly for debugging. With the busy wait and the recursive code this
|
||||||
implementation is definitively not optimal, but it’s functional and
|
implementation is definitively not optimal, but it's functional and
|
||||||
that’s what matter most at this stage.
|
that's what matter most at this stage.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
void kputc( unsigned char c) {
|
void kputc( unsigned char c) {
|
||||||
@@ -131,8 +131,8 @@ as usual but I can see the RX LED on the USB to UART adapter flash
|
|||||||
briefly when I release the reset button.
|
briefly when I release the reset button.
|
||||||
<p>
|
<p>
|
||||||
On Windows PC, if I use PuTTY or Arduino IDE to open <b>COM4</b> at 9600
|
On Windows PC, if I use PuTTY or Arduino IDE to open <b>COM4</b> at 9600
|
||||||
baud, every time I press and release the reset button I can see ‘hello,
|
baud, every time I press and release the reset button I can see 'hello, world'
|
||||||
world’ displayed on a new line in the terminal window.
|
displayed on a new line in the terminal window.
|
||||||
<p>
|
<p>
|
||||||
On Linux, when I plug in the USB to UART adapter, it enumerates as
|
On Linux, when I plug in the USB to UART adapter, it enumerates as
|
||||||
<b>/dev/ttyUSB0</b>, so it is compatible with the USB driver for serial
|
<b>/dev/ttyUSB0</b>, so it is compatible with the USB driver for serial
|
||||||
@@ -144,7 +144,7 @@ writing.
|
|||||||
|
|
||||||
Once added to <b>dialout</b>, I can open <b>/dev/ttyUSB0</b> at 9600 baud in
|
Once added to <b>dialout</b>, I can open <b>/dev/ttyUSB0</b> at 9600 baud in
|
||||||
Arduino IDE, each time I press and release the board RESET button, I can see
|
Arduino IDE, each time I press and release the board RESET button, I can see
|
||||||
‘hello, world’ displayed on a new line in the Serial Monitor window.
|
'hello, world' displayed on a new line in the Serial Monitor window.
|
||||||
|
|
||||||
<h2>Checkpoint</h2>
|
<h2>Checkpoint</h2>
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ Receiving objects: 100% (1357/1357), 1.04 MiB | 74.00 KiB/s, done.
|
|||||||
Resolving deltas: 100% (912/912), done.
|
Resolving deltas: 100% (912/912), done.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Build on Linux doesn’t show any warnings.
|
Build on Linux doesn't show any warnings.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
$ cd stm32flash-code
|
$ cd stm32flash-code
|
||||||
@@ -130,7 +130,7 @@ case <b>COM4</b> instead of <b>/dev/ttyUSB0</b>.
|
|||||||
There is several other Windows applications available on ST.com for
|
There is several other Windows applications available on ST.com for
|
||||||
flashing STM32 chipsets: STM32 ST-Link Utility, STM32 Flash Loader
|
flashing STM32 chipsets: STM32 ST-Link Utility, STM32 Flash Loader
|
||||||
Demonstrator, ST Visual Programmer STM32. They have been marked as <b>NRND</b>
|
Demonstrator, ST Visual Programmer STM32. They have been marked as <b>NRND</b>
|
||||||
(Not Recommended for New Design), which means they won’t support latest
|
(Not Recommended for New Design), which means they won't support latest
|
||||||
chipsets as they are replaced by STM32 Cube Programmer.
|
chipsets as they are replaced by STM32 Cube Programmer.
|
||||||
<p>
|
<p>
|
||||||
<a href="25_prototype.html">Next</a>, I will write an application which make
|
<a href="25_prototype.html">Next</a>, I will write an application which make
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>2.6 uptime</h1>
|
<h1>2.6 uptime</h1>
|
||||||
|
|
||||||
It’s time to throw away the prototype and write a production version of
|
It's time to throw away the prototype and write a production version of
|
||||||
<code>uptime</code>. There is several things I want to straighten up in
|
<code>uptime</code>. There is several things I want to straighten up in
|
||||||
<b>uptime.1.c</b>:
|
<b>uptime.1.c</b>:
|
||||||
<ul>
|
<ul>
|
||||||
@@ -50,13 +50,13 @@ Next, I make a revision of <b>uplow.1.c</b> by making a copy into
|
|||||||
I include <b>system.h</b> which is the interface that <b>uplow.2.c</b>
|
I include <b>system.h</b> which is the interface that <b>uplow.2.c</b>
|
||||||
implements. I will have several implementations of the same interface,
|
implements. I will have several implementations of the same interface,
|
||||||
so <b>system.h</b> is not just the interface published by <b>uplow.2.c</b>,
|
so <b>system.h</b> is not just the interface published by <b>uplow.2.c</b>,
|
||||||
it’s <b>uplow.2.c</b> which is an implementation of <b>system.h</b>.
|
it's <b>uplow.2.c</b> which is an implementation of <b>system.h</b>.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
#include "system.h" /* implements system.h */
|
#include "system.h" /* implements system.h */
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
I extract the code for <b>puts()</b> as it is a library function that doesn’t
|
I extract the code for <b>puts()</b> as it is a library function that doesn't
|
||||||
really belong to the system.
|
really belong to the system.
|
||||||
<p>
|
<p>
|
||||||
I add the implementation of <b>kputs()</b> and <b>yield()</b>.
|
I add the implementation of <b>kputs()</b> and <b>yield()</b>.
|
||||||
@@ -90,7 +90,7 @@ version by adding characters at the beginning of a string.
|
|||||||
|
|
||||||
<li> <code>kputu()</code> takes one additional divider parameter, so it can be
|
<li> <code>kputu()</code> takes one additional divider parameter, so it can be
|
||||||
used to print unsigned integer in various format like octal, decimal and
|
used to print unsigned integer in various format like octal, decimal and
|
||||||
hexadecimal. Current implementation will work for base 8 to 16, it won’t
|
hexadecimal. Current implementation will work for base 8 to 16, it won't
|
||||||
work for binary or base 36.
|
work for binary or base 36.
|
||||||
|
|
||||||
<li> <code>kputi()</code> outputs signed integer.
|
<li> <code>kputi()</code> outputs signed integer.
|
||||||
@@ -256,7 +256,7 @@ The linker found a reference to <code>putchar()</code> at line 41 of
|
|||||||
printf( "\n") ;
|
printf( "\n") ;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
I haven’t used <code>putchar()</code> in my code and line 41 is a
|
I haven't used <code>putchar()</code> in my code and line 41 is a
|
||||||
<code>printf( "\n")</code> that can be optimized to a
|
<code>printf( "\n")</code> that can be optimized to a
|
||||||
<code>putchar( '\n')</code>. This must be some high level C optimization of gcc.
|
<code>putchar( '\n')</code>. This must be some high level C optimization of gcc.
|
||||||
<p>
|
<p>
|
||||||
@@ -324,7 +324,7 @@ I flash the board and start execution, the output works as expected.
|
|||||||
<img alt="uptime" src="img/26_uptime.png">
|
<img alt="uptime" src="img/26_uptime.png">
|
||||||
<p>
|
<p>
|
||||||
It will take a while to see the days and weeks counts appear, so I will
|
It will take a while to see the days and weeks counts appear, so I will
|
||||||
need to power the board independently from it’s serial interface. For
|
need to power the board independently from its serial interface. For
|
||||||
test purpose I fast forward the execution by using a bigger value for
|
test purpose I fast forward the execution by using a bigger value for
|
||||||
the increment of <code>uptime</code> in <code>SysTick_handler()</code>.
|
the increment of <code>uptime</code> in <code>SysTick_handler()</code>.
|
||||||
|
|
||||||
@@ -332,11 +332,11 @@ the increment of <code>uptime</code> in <code>SysTick_handler()</code>.
|
|||||||
|
|
||||||
Rereading the code while writing this web page, I found a typo in the
|
Rereading the code while writing this web page, I found a typo in the
|
||||||
week calculation. After that I retested with a bigger time increment to
|
week calculation. After that I retested with a bigger time increment to
|
||||||
make sure days and weeks values are correct. It’s also clear that the
|
make sure days and weeks values are correct. It's also clear that the
|
||||||
test coverage for the printf format interpreter is not sufficient as I have
|
test coverage for the printf format interpreter is not sufficient as I have
|
||||||
coded more than is necessary to implement <b>uptime</b>.
|
coded more than is necessary to implement <b>uptime</b>.
|
||||||
<p>
|
<p>
|
||||||
I didn’t expect gcc to optimize calls to high level C functions,
|
I didn't expect gcc to optimize calls to high level C functions,
|
||||||
replacing some <code>printf()</code> by <code>putchar()</code>, thus forcing me
|
replacing some <code>printf()</code> by <code>putchar()</code>, thus forcing me
|
||||||
to write additional code. So far I am not concerned by execution speed, so this
|
to write additional code. So far I am not concerned by execution speed, so this
|
||||||
type of optimization is a bit counter productive.
|
type of optimization is a bit counter productive.
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<h1>2.7: C Library</h1>
|
<h1>2.7: C Library</h1>
|
||||||
|
|
||||||
So far I have used three Standard C library functions for output:
|
So far I have used three Standard C library functions for output:
|
||||||
<code>printf()</code>, <code>putchar()</code> and <code>puts()</code>. It’s
|
<code>printf()</code>, <code>putchar()</code> and <code>puts()</code>. It's
|
||||||
time to bundle them as a library. This will give me more flexibility as I will
|
time to bundle them as a library. This will give me more flexibility as I will
|
||||||
not have to give a full list of the modules to link, the linker will handle
|
not have to give a full list of the modules to link, the linker will handle
|
||||||
the missing dependencies by looking into the libraries.
|
the missing dependencies by looking into the libraries.
|
||||||
@@ -38,7 +38,7 @@ int puts( const char *s) {
|
|||||||
I need to tell <b>GNU make</b> how to manage and use the library, which
|
I need to tell <b>GNU make</b> how to manage and use the library, which
|
||||||
means updating <b>Makefile</b> with the following informations:
|
means updating <b>Makefile</b> with the following informations:
|
||||||
<p>
|
<p>
|
||||||
What’s the name, the content and the rule to maintain the library:
|
What's the name, the content and the rule to maintain the library:
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
AR = $(BINPFX)ar
|
AR = $(BINPFX)ar
|
||||||
@@ -63,7 +63,7 @@ $(PROJECT).elf: $(OBJS) lib$(LIBSTEM).a
|
|||||||
$(OBJDUMP) -hS $@ > $(PROJECT).lst
|
$(OBJDUMP) -hS $@ > $(PROJECT).lst
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Library modules are implicitly part of the composition, so it’s not
|
Library modules are implicitly part of the composition, so it's not
|
||||||
necessary to list them anymore.
|
necessary to list them anymore.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<h1>2.8 Baud Rate and Clocks</h1>
|
<h1>2.8 Baud Rate and Clocks</h1>
|
||||||
|
|
||||||
<blockquote> “The time has come,” the walrus said, “to talk of many things: Of baud
|
<blockquote> “The time has come,” the walrus said, “to talk of many things: Of baud
|
||||||
rates – and clocks – and quartz.”<br>
|
rates - and clocks - and quartz.”<br>
|
||||||
-- Les huit scaroles --
|
-- Les huit scaroles --
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ so how fast is that?
|
|||||||
|
|
||||||
<h2>A bit of theory</h2>
|
<h2>A bit of theory</h2>
|
||||||
|
|
||||||
Let’s interpret asynchronous serial transmission, 9600 baud, 8 bits, no
|
Let's interpret asynchronous serial transmission, 9600 baud, 8 bits, no
|
||||||
parity, 1 stop bit.
|
parity, 1 stop bit.
|
||||||
<ul>
|
<ul>
|
||||||
<li> Serial transmission means transmission on one wire, with each bit sent
|
<li> Serial transmission means transmission on one wire, with each bit sent
|
||||||
@@ -40,17 +40,17 @@ the change in the wire state.
|
|||||||
</ul>
|
</ul>
|
||||||
In my case, <b>8N1</b> means that, because of the framing pattern, for
|
In my case, <b>8N1</b> means that, because of the framing pattern, for
|
||||||
every byte of data sent, there is one extra start bit and one extra stop
|
every byte of data sent, there is one extra start bit and one extra stop
|
||||||
bit sent, it’s ten bits per byte of data. At 9600 bauds that means 960
|
bit sent, it's ten bits per byte of data. At 9600 bauds that means 960
|
||||||
bytes per second, fast enough to transmit every characters of a 80×24
|
bytes per second, fast enough to transmit every characters of a 80x24
|
||||||
terminal screen in two seconds.
|
terminal screen in two seconds.
|
||||||
|
|
||||||
<h2>Baud rate accuracy</h2>
|
<h2>Baud rate accuracy</h2>
|
||||||
|
|
||||||
It sounds like a pretty robust transmission scheme, sampling at 16 times
|
It sounds like a pretty robust transmission scheme, sampling at 16 times
|
||||||
the transmission clock isn’t call oversampling for nothing. Am I
|
the transmission clock isn't call oversampling for nothing. Am I
|
||||||
overdoing something here or just compensating for something I missed?
|
overdoing something here or just compensating for something I missed?
|
||||||
<p>
|
<p>
|
||||||
The thing is, I didn’t program USART1 to transmit at 9600 baud. As my
|
The thing is, I didn't program USART1 to transmit at 9600 baud. As my
|
||||||
default clock is 8MHz, I had to write in USART1 baud rate register a
|
default clock is 8MHz, I had to write in USART1 baud rate register a
|
||||||
value close to 8000000/9600 or 2500/3, 833 is close enough but my actual
|
value close to 8000000/9600 or 2500/3, 833 is close enough but my actual
|
||||||
transmission speed is closer to 9604, slightly faster than 9600 baud.
|
transmission speed is closer to 9604, slightly faster than 9600 baud.
|
||||||
@@ -62,7 +62,7 @@ want to work at higher baud rate.
|
|||||||
|
|
||||||
<h2>Clocks</h2>
|
<h2>Clocks</h2>
|
||||||
|
|
||||||
Looking at the clock tree in the datasheet can be intimidating, it’s
|
Looking at the clock tree in the datasheet can be intimidating, it's
|
||||||
definitively about several clocks.
|
definitively about several clocks.
|
||||||
<p>
|
<p>
|
||||||
<img alt="Clock Tree" src="img/28_clocktree.png">
|
<img alt="Clock Tree" src="img/28_clocktree.png">
|
||||||
@@ -115,7 +115,7 @@ I will use 24 MHz.
|
|||||||
<h2>Quartz</h2>
|
<h2>Quartz</h2>
|
||||||
|
|
||||||
I can also activate the quartz if there is one soldered on the board.
|
I can also activate the quartz if there is one soldered on the board.
|
||||||
It’s usually the case but specially for STM32F030F4 which has only 20
|
It's usually the case but specially for STM32F030F4 which has only 20
|
||||||
pins, a quartz less design that free up two GPIO pins can be a day
|
pins, a quartz less design that free up two GPIO pins can be a day
|
||||||
saver. Quartz value from 4 to 32 MHz are supported and most design use 8
|
saver. Quartz value from 4 to 32 MHz are supported and most design use 8
|
||||||
MHz.
|
MHz.
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>2.9 Interrupt Driven Transmission</h1>
|
<h1>2.9 Interrupt Driven Transmission</h1>
|
||||||
|
|
||||||
It’s time to revise the implementation of <code>kputc()</code>, remove the
|
It's time to revise the implementation of <code>kputc()</code>, remove the
|
||||||
recursive call to handle CR LF transmission and avoid the busy wait
|
recursive call to handle CR LF transmission and avoid the busy wait
|
||||||
loop. USART1 can trigger an interrupt when the Transmit Data Register
|
loop. USART1 can trigger an interrupt when the Transmit Data Register
|
||||||
(<b>TDR</b>) is empty which is all I need to implement interrupt driven
|
(<b>TDR</b>) is empty which is all I need to implement interrupt driven
|
||||||
@@ -128,7 +128,7 @@ Configuration Register of USART1:
|
|||||||
<pre>#define USART_CR1_TXEIE (1 << 7) /* 7: TDR Empty Interrupt Enable */</pre>
|
<pre>#define USART_CR1_TXEIE (1 << 7) /* 7: TDR Empty Interrupt Enable */</pre>
|
||||||
|
|
||||||
I use a Round Robin buffer to synchronize <code>kputc()</code> and
|
I use a Round Robin buffer to synchronize <code>kputc()</code> and
|
||||||
<code>USART1_Handler()</code> making sure they don’t write to the same location.
|
<code>USART1_Handler()</code> making sure they don't write to the same location.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
static unsigned char txbuf[ 8] ; // best if size is a power of 2 for cortex-M0
|
static unsigned char txbuf[ 8] ; // best if size is a power of 2 for cortex-M0
|
||||||
@@ -141,11 +141,11 @@ static volatile unsigned char txbufout ;
|
|||||||
<code>USART1_Handler()</code> only read from it.
|
<code>USART1_Handler()</code> only read from it.
|
||||||
|
|
||||||
<li> <code>txbufin</code> is the index of the position where
|
<li> <code>txbufin</code> is the index of the position where
|
||||||
<code>kputc()</code> will insert a character, it’s written by
|
<code>kputc()</code> will insert a character, it's written by
|
||||||
<code>kputc()</code> and read by <code>USART1_Handler()</code>.
|
<code>kputc()</code> and read by <code>USART1_Handler()</code>.
|
||||||
|
|
||||||
<li> <code>txbufout</code> is the index of the position where
|
<li> <code>txbufout</code> is the index of the position where
|
||||||
<code>USART1_Handler()</code> will fetch a character, it’s written by
|
<code>USART1_Handler()</code> will fetch a character, it's written by
|
||||||
<code>USART1_Handler()</code> and read by <code>kputc()</code>. The value of
|
<code>USART1_Handler()</code> and read by <code>kputc()</code>. The value of
|
||||||
<code>txbufout</code> will change under interrupt, so it is marked as
|
<code>txbufout</code> will change under interrupt, so it is marked as
|
||||||
<code>volatile</code> to make sure the compiler will not optimize the code in a
|
<code>volatile</code> to make sure the compiler will not optimize the code in a
|
||||||
@@ -260,7 +260,7 @@ to hold lastc (1 byte). The new version uses 12 bytes to hold the round robin
|
|||||||
buffer (8 bytes), its in and out indexes (2 bytes) and lastc (1 byte).
|
buffer (8 bytes), its in and out indexes (2 bytes) and lastc (1 byte).
|
||||||
|
|
||||||
<li> The compiler optimizes the modulo instruction in <code>% size</code> to
|
<li> The compiler optimizes the modulo instruction in <code>% size</code> to
|
||||||
bit masking <code>& (size – 1)</code> as the size 8 is a power of 2.
|
bit masking <code>& (size - 1)</code> as the size 8 is a power of 2.
|
||||||
</ul>
|
</ul>
|
||||||
Flashing a device with the new executable, <b>uptime</b> works as the previous
|
Flashing a device with the new executable, <b>uptime</b> works as the previous
|
||||||
version.
|
version.
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
The DHT11 is a low cost humidity and temperature sensor from Aosong
|
The DHT11 is a low cost humidity and temperature sensor from Aosong
|
||||||
which is easy to buy online. It is not popular as it has a non standard
|
which is easy to buy online. It is not popular as it has a non standard
|
||||||
communication protocol and its precision is ±5% for humidity and ±2°C
|
communication protocol and its precision is ±5% for humidity and ±2°C
|
||||||
for temperature so it’s often overlooked for more expensive solution.
|
for temperature so it's often overlooked for more expensive solution.
|
||||||
|
|
||||||
<h2>Hardware consideration</h2>
|
<h2>Hardware consideration</h2>
|
||||||
|
|
||||||
@@ -142,11 +142,11 @@ iolvl_t gpioa_read( int pin) { /* Read level of GPIOA pin */
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
I didn’t use the GPIO Input Data Register (<b>IDR</b>) until now, so I add it
|
I didn't use the GPIO Input Data Register (<b>IDR</b>) until now, so I add it
|
||||||
to the registers description.
|
to the registers description.
|
||||||
<p>
|
<p>
|
||||||
<code>gpioa_output()</code> implementation is minimal. I know I am switching
|
<code>gpioa_output()</code> implementation is minimal. I know I am switching
|
||||||
only between input and output mode, so I don’t need to mask the bit field
|
only between input and output mode, so I don't need to mask the bit field
|
||||||
first.
|
first.
|
||||||
<p>
|
<p>
|
||||||
I use the System Tick to implement <code>usleep()</code>.
|
I use the System Tick to implement <code>usleep()</code>.
|
||||||
@@ -165,7 +165,7 @@ The System Tick generates an interrupt every second but I can read the
|
|||||||
Current Value Register (<b>CVR</b>) to pause for smaller time period.
|
Current Value Register (<b>CVR</b>) to pause for smaller time period.
|
||||||
<p>
|
<p>
|
||||||
As I will read the sensor just after a new second count, I know that the
|
As I will read the sensor just after a new second count, I know that the
|
||||||
<b>CVR</b> value is close to maximum and I don’t need to care for a roll
|
<b>CVR</b> value is close to maximum and I don't need to care for a roll
|
||||||
over.
|
over.
|
||||||
<p>
|
<p>
|
||||||
SysTick input clock is <b>HCLK/8</b>, this implementation will work for
|
SysTick input clock is <b>HCLK/8</b>, this implementation will work for
|
||||||
@@ -331,7 +331,7 @@ can measure 80µs in retries unit. This is all I need to calibrate the timing
|
|||||||
measurement.
|
measurement.
|
||||||
<p>
|
<p>
|
||||||
I can do this calibration every time the DHT11 starts transmission, this
|
I can do this calibration every time the DHT11 starts transmission, this
|
||||||
way I don’t need to update some constant if I change the frequency of my
|
way I don't need to update some constant if I change the frequency of my
|
||||||
system clock.
|
system clock.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -418,7 +418,7 @@ two seconds.
|
|||||||
<p>
|
<p>
|
||||||
<img alt="DHT11 output" src="img/31_output.png">
|
<img alt="DHT11 output" src="img/31_output.png">
|
||||||
<p>
|
<p>
|
||||||
The humidity value seems off the mark. So I need to investigate what’s
|
The humidity value seems off the mark. So I need to investigate what's
|
||||||
the issue.
|
the issue.
|
||||||
|
|
||||||
<h2>Checkpoint</h2>
|
<h2>Checkpoint</h2>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<h1>3.2 DHT11 Errata</h2>
|
<h1>3.2 DHT11 Errata</h2>
|
||||||
|
|
||||||
I only did basic testing so far, checking that the values read were
|
I only did basic testing so far, checking that the values read were
|
||||||
displayed properly. But the humidity values didn’t seem correct, so I
|
displayed properly. But the humidity values didn't seem correct, so I
|
||||||
need to do some extra verifications. There are many possible causes and
|
need to do some extra verifications. There are many possible causes and
|
||||||
they can combine, bugs like humans are social animals, when you find
|
they can combine, bugs like humans are social animals, when you find
|
||||||
one, look for its mates.
|
one, look for its mates.
|
||||||
@@ -55,7 +55,7 @@ the previous version v1.3 branded AOSONG which seems identical except a
|
|||||||
revision page.
|
revision page.
|
||||||
<p>
|
<p>
|
||||||
I also have an English Aosong DHT11 datasheet that seems outdated.
|
I also have an English Aosong DHT11 datasheet that seems outdated.
|
||||||
Aosong doesn’t seem to allow redistribution of their datasheet so most
|
Aosong doesn't seem to allow redistribution of their datasheet so most
|
||||||
online vendor have made their own based on that English version.
|
online vendor have made their own based on that English version.
|
||||||
<p>
|
<p>
|
||||||
The English datasheet states the temperature range as 0~50℃, the
|
The English datasheet states the temperature range as 0~50℃, the
|
||||||
@@ -80,7 +80,7 @@ around 25~26%RH. As I have changed both interval and setup time, I need
|
|||||||
confirm that it is the interval time that matters.
|
confirm that it is the interval time that matters.
|
||||||
<p>
|
<p>
|
||||||
With intervals of 5 and 6 seconds, the reading jumps above 37%RH. So
|
With intervals of 5 and 6 seconds, the reading jumps above 37%RH. So
|
||||||
it’s clearly a problem with the interval.
|
it's clearly a problem with the interval.
|
||||||
<p>
|
<p>
|
||||||
I want to make a round number of samples per minute, so I need retest to
|
I want to make a round number of samples per minute, so I need retest to
|
||||||
check if 10 and 12 seconds work the same as 15, but before I do fine
|
check if 10 and 12 seconds work the same as 15, but before I do fine
|
||||||
@@ -89,7 +89,7 @@ particular DHT11.
|
|||||||
|
|
||||||
<h2>Product quality</h2>
|
<h2>Product quality</h2>
|
||||||
|
|
||||||
It’s clear that the DHT11 I am testing is not behaving according to old
|
It's clear that the DHT11 I am testing is not behaving according to old
|
||||||
or new specifications for the sampling interval.
|
or new specifications for the sampling interval.
|
||||||
<p>
|
<p>
|
||||||
Defects happen! No production line output is 100% perfect, so I may just
|
Defects happen! No production line output is 100% perfect, so I may just
|
||||||
@@ -205,14 +205,14 @@ And retest after the following modification.
|
|||||||
|
|
||||||
<h2>Stability</h2>
|
<h2>Stability</h2>
|
||||||
|
|
||||||
During my test I didn’t noticed big surges in measurements but the time
|
During my test I didn't noticed big surges in measurements but the time
|
||||||
to get to actual value is quite long. The interval between readings
|
to get to actual value is quite long. The interval between readings
|
||||||
affects the measurement and initially it takes a long time for the
|
affects the measurement and initially it takes a long time for the
|
||||||
readings to converge to actual temperature or humidity.
|
readings to converge to actual temperature or humidity.
|
||||||
|
|
||||||
<h2>Conclusions</h2>
|
<h2>Conclusions</h2>
|
||||||
|
|
||||||
I didn’t find any English version of the latest version of the
|
I didn't find any English version of the latest version of the
|
||||||
datasheet.
|
datasheet.
|
||||||
<p>
|
<p>
|
||||||
I found some difference between the Chinese datasheet and the behavior
|
I found some difference between the Chinese datasheet and the behavior
|
||||||
|
@@ -24,7 +24,7 @@ resistor between vcc and io data.
|
|||||||
<img alt="DS18B20 Board" src="img/33_ds18b20.png">
|
<img alt="DS18B20 Board" src="img/33_ds18b20.png">
|
||||||
</p>
|
</p>
|
||||||
It is possible to power the chip using data io and gnd only (no vcc) in
|
It is possible to power the chip using data io and gnd only (no vcc) in
|
||||||
Parasitic Power Mode if a two wire only interface is needed. I won’t use
|
Parasitic Power Mode if a two wire only interface is needed. I won't use
|
||||||
this feature for now.
|
this feature for now.
|
||||||
|
|
||||||
<h2>Communication protocol</h2>
|
<h2>Communication protocol</h2>
|
||||||
|
@@ -81,7 +81,7 @@ The ADC characteristics in the STM32F030 datasheet states that the
|
|||||||
maximum ADC sampling clock is 14MHz. It is possible to select either an
|
maximum ADC sampling clock is 14MHz. It is possible to select either an
|
||||||
internal 14 MHz clock (HSI14) or PCLK divided by 2 or 4. I want to check
|
internal 14 MHz clock (HSI14) or PCLK divided by 2 or 4. I want to check
|
||||||
how the clock affects the readings (HSI14, 28/2, 24/2, 48/4). At first I
|
how the clock affects the readings (HSI14, 28/2, 24/2, 48/4). At first I
|
||||||
couldn’t manage to make PCLK/4 work until I found the note on ADC
|
couldn't manage to make PCLK/4 work until I found the note on ADC
|
||||||
calibration work around in the errata
|
calibration work around in the errata
|
||||||
<a href="https://www.st.com/content/st_com/en/search.html#q=%20ES0219-t=resources-page=1"
|
<a href="https://www.st.com/content/st_com/en/search.html#q=%20ES0219-t=resources-page=1"
|
||||||
>ES0219 2.5.3</a>
|
>ES0219 2.5.3</a>
|
||||||
@@ -117,7 +117,7 @@ The raw data readings are relative to the analog operative voltage VDDA.
|
|||||||
<b>Vmeasured = VDDA * VRAW / 4095</b>
|
<b>Vmeasured = VDDA * VRAW / 4095</b>
|
||||||
<p>
|
<p>
|
||||||
This is why I measure both voltage and temperature. Ideally, VDDA should
|
This is why I measure both voltage and temperature. Ideally, VDDA should
|
||||||
be 3.3V, in practice it’s highly dependent of the power supply.
|
be 3.3V, in practice it's highly dependent of the power supply.
|
||||||
<p>
|
<p>
|
||||||
Every chip is calibrated in factory during production, ADC conversion is
|
Every chip is calibrated in factory during production, ADC conversion is
|
||||||
done at 3.3V and 30℃ and the resulting values are stored in system
|
done at 3.3V and 30℃ and the resulting values are stored in system
|
||||||
|
@@ -17,13 +17,13 @@ reading at 3.3V (±10mV) and 30℃ (±5℃).
|
|||||||
<img alt="TS_CAL1" src="img/34_tscal1.png">
|
<img alt="TS_CAL1" src="img/34_tscal1.png">
|
||||||
<p>
|
<p>
|
||||||
There is only one point calibration documented and its reference
|
There is only one point calibration documented and its reference
|
||||||
temperature is known with a precision of ±5℃. That’s not enough to
|
temperature is known with a precision of ±5℃. That's not enough to
|
||||||
calculate temperature but it shows that the sensor was tested in
|
calculate temperature but it shows that the sensor was tested in
|
||||||
production.
|
production.
|
||||||
<p>
|
<p>
|
||||||
Notice that the calibration value name is <b>TS_CAL1</b>, some other STM32
|
Notice that the calibration value name is <b>TS_CAL1</b>, some other STM32
|
||||||
chipset families do have a second temperature factory calibration point
|
chipset families do have a second temperature factory calibration point
|
||||||
<b>TS_CAL2</b>. Also some don’t have any factory calibration stored at all.
|
<b>TS_CAL2</b>. Also some don't have any factory calibration stored at all.
|
||||||
So you have to refer to the datasheet that matches the chip you are
|
So you have to refer to the datasheet that matches the chip you are
|
||||||
targeting when you port your code to a new chipset.
|
targeting when you port your code to a new chipset.
|
||||||
<p>
|
<p>
|
||||||
@@ -37,7 +37,7 @@ typical average slope of <b>4.3 mV/℃</b> and was calibrated in factory at
|
|||||||
exactly <b>3.3V</b> and <b>30℃</b>, then you could use the following formula
|
exactly <b>3.3V</b> and <b>30℃</b>, then you could use the following formula
|
||||||
to calculate the temperature.
|
to calculate the temperature.
|
||||||
<p>
|
<p>
|
||||||
<b>T = 30 + (TS_CAL1 * 3.3 – TS_RAW * VDDA) / 4095 / 0.0043</b>
|
<b>T = 30 + (TS_CAL1 * 3.3 - TS_RAW * VDDA) / 4095 / 0.0043</b>
|
||||||
<p>
|
<p>
|
||||||
with
|
with
|
||||||
<p>
|
<p>
|
||||||
@@ -45,7 +45,7 @@ with
|
|||||||
<p>
|
<p>
|
||||||
that gives
|
that gives
|
||||||
<p>
|
<p>
|
||||||
<b>T = 30 + 3.3 * (TS_CAL1 – TS_RAW * V_CAL / V_RAW) / 4095 / 0.0043</b>
|
<b>T = 30 + 3.3 * (TS_CAL1 - TS_RAW * V_CAL / V_RAW) / 4095 / 0.0043</b>
|
||||||
<p>
|
<p>
|
||||||
If I express the average slope in raw ADC units per ℃ instead of mV/℃
|
If I express the average slope in raw ADC units per ℃ instead of mV/℃
|
||||||
<p>
|
<p>
|
||||||
@@ -53,7 +53,7 @@ If I express the average slope in raw ADC units per ℃ instead of mV/℃
|
|||||||
<p>
|
<p>
|
||||||
the final formula is
|
the final formula is
|
||||||
<p>
|
<p>
|
||||||
<b>T = 30 + (TS_CAL1 – TS_RAW * V_CAL / V_RAW) * 1000 / 5336</b>
|
<b>T = 30 + (TS_CAL1 - TS_RAW * V_CAL / V_RAW) * 1000 / 5336</b>
|
||||||
<p>
|
<p>
|
||||||
which matches the sample code for temperature computation given in the
|
which matches the sample code for temperature computation given in the
|
||||||
reference manual (RM0360 A.7.16).
|
reference manual (RM0360 A.7.16).
|
||||||
@@ -76,7 +76,7 @@ If I use the raw ADC readings from my last run
|
|||||||
<p>
|
<p>
|
||||||
<b>VDDA = 3.3 * 1526 / 1538 = 3.274V</b>
|
<b>VDDA = 3.3 * 1526 / 1538 = 3.274V</b>
|
||||||
<p>
|
<p>
|
||||||
<b>t = 30 + (1721 – 1718 * 1526 / 1538) * 1000 / 5336 = 33.07℃</b>
|
<b>t = 30 + (1721 - 1718 * 1526 / 1538) * 1000 / 5336 = 33.07℃</b>
|
||||||
<p>
|
<p>
|
||||||
I confirm the voltage with a voltmeter (measured 3.282V versus 3.274V
|
I confirm the voltage with a voltmeter (measured 3.282V versus 3.274V
|
||||||
computed). The computed internal temperature value is roughly 5℃ higher
|
computed). The computed internal temperature value is roughly 5℃ higher
|
||||||
@@ -94,7 +94,7 @@ Memory (3KB) and the option bytes.
|
|||||||
| RAM Memory | 0x20000000 | 4KB |
|
| RAM Memory | 0x20000000 | 4KB |
|
||||||
</pre>
|
</pre>
|
||||||
The calibration data are saved in the last 96 bytes of the System
|
The calibration data are saved in the last 96 bytes of the System
|
||||||
Memory, starting at address 0x1FFFF7A0. So it’s simple to dump the
|
Memory, starting at address 0x1FFFF7A0. So it's simple to dump the
|
||||||
content of that zone and compare the values for multiple chips.
|
content of that zone and compare the values for multiple chips.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -136,7 +136,7 @@ temperature += 30;
|
|||||||
|
|
||||||
Factoring in the actual measured voltage, this gives
|
Factoring in the actual measured voltage, this gives
|
||||||
<p>
|
<p>
|
||||||
<b>T = 30 + (TS_CAL1 – TS_RAW * V_CAL / V_RAW) * 80 / (TS_CAL1 – TS_CAL2)</b>
|
<b>T = 30 + (TS_CAL1 - TS_RAW * V_CAL / V_RAW) * 80 / (TS_CAL1 - TS_CAL2)</b>
|
||||||
<p>
|
<p>
|
||||||
If I use the raw ADC readings from my last run
|
If I use the raw ADC readings from my last run
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ TSCAL2_SLOPE = (1721 - 1297) / 80 = 5.3 ADC step/℃
|
|||||||
= 3.3 * 5.3 / 4095 = 4.271 mV/℃
|
= 3.3 * 5.3 / 4095 = 4.271 mV/℃
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<b>t = 30 + (1721 – 1718 * 1526 / 1538) * 80 / (1721 – 1297) = 33.09℃</b>
|
<b>t = 30 + (1721 - 1718 * 1526 / 1538) * 80 / (1721 - 1297) = 33.09℃</b>
|
||||||
<p>
|
<p>
|
||||||
Which is only 0.02℃ higher than the previous result based on the more
|
Which is only 0.02℃ higher than the previous result based on the more
|
||||||
generic formula. Because the temperature measured is close to the
|
generic formula. Because the temperature measured is close to the
|
||||||
|
@@ -61,7 +61,7 @@ f030f4.elf from startup.txeie.o adc.o adcmain.o
|
|||||||
2644 0 16 2660 a64 f030f4.elf
|
2644 0 16 2660 a64 f030f4.elf
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
As I don’t want to turn off size optimization and I am not willing to
|
As I don't want to turn off size optimization and I am not willing to
|
||||||
always pay the full 180 bytes for a production ready <code>memset()</code>
|
always pay the full 180 bytes for a production ready <code>memset()</code>
|
||||||
when it is called only once at startup to clear a few bytes, I ended up adding
|
when it is called only once at startup to clear a few bytes, I ended up adding
|
||||||
my own version of <code>memset()</code> to my local library.
|
my own version of <code>memset()</code> to my local library.
|
||||||
|
@@ -17,7 +17,7 @@ the code in flash memory.
|
|||||||
|
|
||||||
<pre>stm32flash -g 0 COM6</pre>
|
<pre>stm32flash -g 0 COM6</pre>
|
||||||
|
|
||||||
With my current code, this works fine as far as I don’t use interrupt
|
With my current code, this works fine as far as I don't use interrupt
|
||||||
subroutine. <b>ledon</b> and <b>blink</b> both work, but <b>ledtick</b> will
|
subroutine. <b>ledon</b> and <b>blink</b> both work, but <b>ledtick</b> will
|
||||||
reset once the <code>SysTick_Handler()</code> interrupt routine is triggered
|
reset once the <code>SysTick_Handler()</code> interrupt routine is triggered
|
||||||
for the first time. This is due to the fact that the system memory is still
|
for the first time. This is due to the fact that the system memory is still
|
||||||
@@ -87,7 +87,7 @@ the resulting <b>f030f4.map</b> file.
|
|||||||
|
|
||||||
<li> .data and .bss are located from 0x20000000.
|
<li> .data and .bss are located from 0x20000000.
|
||||||
</ul>
|
</ul>
|
||||||
Let’s write this code in RAM and execute it!
|
Let's write this code in RAM and execute it!
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
stm32flash -w blink.bin -S 0x20000800 COM6
|
stm32flash -w blink.bin -S 0x20000800 COM6
|
||||||
@@ -95,7 +95,7 @@ stm32flash -g 0x20000800 COM6
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
This work just fine but of course the executable of <b>ledon</b> or
|
This work just fine but of course the executable of <b>ledon</b> or
|
||||||
<b>blink</b> doesn’t use interrupt routines.
|
<b>blink</b> doesn't use interrupt routines.
|
||||||
|
|
||||||
<h2>ISR Vector in RAM</h2>
|
<h2>ISR Vector in RAM</h2>
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>3.9 Reading a Resistor Value</h1>
|
<h1>3.9 Reading a Resistor Value</h1>
|
||||||
|
|
||||||
I used the ADC previously to read the internal sensors, so it’s simple
|
I used the ADC previously to read the internal sensors, so it's simple
|
||||||
to move on to external ones. Once you can read the value of a resistor,
|
to move on to external ones. Once you can read the value of a resistor,
|
||||||
there is a wide choice of analog applications: thermistors, photocells,
|
there is a wide choice of analog applications: thermistors, photocells,
|
||||||
potentiometers, sliders, joysticks …
|
potentiometers, sliders, joysticks …
|
||||||
@@ -35,11 +35,11 @@ in the range [0 … 4095], I can express the two voltages in terms of ADC values
|
|||||||
<p>The voltage divider relationship now becomes<br>
|
<p>The voltage divider relationship now becomes<br>
|
||||||
<b><i>VDDA</i> * ADCraw / 4095 = <i>VDDA</i> * Rref / (Rref + Rmeasured)</b>
|
<b><i>VDDA</i> * ADCraw / 4095 = <i>VDDA</i> * Rref / (Rref + Rmeasured)</b>
|
||||||
<p>which can be further simplified as<br>
|
<p>which can be further simplified as<br>
|
||||||
<b>ADCraw * Rmeasured = Rref * (4095 – ADCraw)</b>
|
<b>ADCraw * Rmeasured = Rref * (4095 - ADCraw)</b>
|
||||||
<p>The resistor value is then given by<br>
|
<p>The resistor value is then given by<br>
|
||||||
<b>Rmeasured = Rref * (4095 – ADCraw) / ADCraw</b><br>
|
<b>Rmeasured = Rref * (4095 - ADCraw) / ADCraw</b><br>
|
||||||
or<br>
|
or<br>
|
||||||
<b>Rmeasured = Rref * (4095 / ADCraw – 1)</b>
|
<b>Rmeasured = Rref * (4095 / ADCraw - 1)</b>
|
||||||
|
|
||||||
<h2>Devil in the whatnots</h2>
|
<h2>Devil in the whatnots</h2>
|
||||||
Some of the things to pay attention to while coding
|
Some of the things to pay attention to while coding
|
||||||
@@ -121,6 +121,10 @@ I add the composition in <b>Makefile</b>
|
|||||||
<p>
|
<p>
|
||||||
Building up on the previous ADC reading of internal sensors, sampling of
|
Building up on the previous ADC reading of internal sensors, sampling of
|
||||||
an external resistor pair connected to one of the IO pin is straightforward.
|
an external resistor pair connected to one of the IO pin is straightforward.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="index.html#part4">Next</a>, I will show the temperature readings on a
|
||||||
|
display.
|
||||||
</p>
|
</p>
|
||||||
<hr>© 2020-2025 Renaud Fivet
|
<hr>© 2020-2025 Renaud Fivet
|
||||||
</body>
|
</body>
|
||||||
|
@@ -39,21 +39,21 @@ $ stm32flash -r - -S 0x1FFFF7a0:96 COM6 2>/dev/null | hexdump -C
|
|||||||
<pre>
|
<pre>
|
||||||
| BootID | X | Y | Wafer | Lot | TS_CAL1 | VREFINT_CAL | TS_CAL2 | Flash | TBD |
|
| BootID | X | Y | Wafer | Lot | TS_CAL1 | VREFINT_CAL | TS_CAL2 | Flash | TBD |
|
||||||
|--------|-------|-----|-------|-----------|---------|-------------|---------|-------|---------|
|
|--------|-------|-----|-------|-----------|---------|-------------|---------|-------|---------|
|
||||||
| x10 | x800A | x41 | x08 | ‘QMY687 ‘ | x6E6 | x5F1 | x53E | 16 | hZE? |
|
| x10 | x800A | x41 | x08 | 'QMY687 ' | x6E6 | x5F1 | x53E | 16 | hZE? |
|
||||||
| x10 | x800C | x18 | x01 | ‘QRR259 ‘ | x6E3 | x5F2 | x532 | 16 | h\E? |
|
| x10 | x800C | x18 | x01 | 'QRR259 ' | x6E3 | x5F2 | x532 | 16 | h\E? |
|
||||||
| x10 | x8011 | x49 | x0E | ‘W3U795 ‘ | x6D1 | x5F0 | x523 | 16 | hbF? |
|
| x10 | x8011 | x49 | x0E | 'W3U795 ' | x6D1 | x5F0 | x523 | 16 | hbF? |
|
||||||
| x10 | x8014 | x20 | x13 | ‘W3R171 ‘ | x6CE | x5F5 | x527 | 16 | hd<? |
|
| x10 | x8014 | x20 | x13 | 'W3R171 ' | x6CE | x5F5 | x527 | 16 | hd<? |
|
||||||
| x10 | x8015 | x21 | x13 | ‘W4A195 ‘ | x6DA | x5EE | x52A | 16 | h^D? |
|
| x10 | x8015 | x21 | x13 | 'W4A195 ' | x6DA | x5EE | x52A | 16 | h^D? |
|
||||||
| x10 | x1C | x3A | x12 | ‘W4A820 ‘ | x6B9 | x5F6 | x511 | 16 | hR;? |
|
| x10 | x1C | x3A | x12 | 'W4A820 ' | x6B9 | x5F6 | x511 | 16 | hR;? |
|
||||||
| x10 | x09 | x4D | x0B | ‘W4C593 ‘ | x6E6 | x5F4 | x53C | 16 | haG? |
|
| x10 | x09 | x4D | x0B | 'W4C593 ' | x6E6 | x5F4 | x53C | 16 | haG? |
|
||||||
| x10 | x1D | x41 | x12 | ‘W4R342 ‘ | x6E4 | x5F1 | x535 | 16 | hZJ? |
|
| x10 | x1D | x41 | x12 | 'W4R342 ' | x6E4 | x5F1 | x535 | 16 | hZJ? |
|
||||||
| x10 | x10 | x17 | x05 | ‘WAA390 ‘ | x6E9 | x5F8 | x523 | 16 | hY=? |
|
| x10 | x10 | x17 | x05 | 'WAA390 ' | x6E9 | x5F8 | x523 | 16 | hY=? |
|
||||||
| x10 | xDDC1 |xDDC1| x0D | ‘ ‘ | x703 | x5E9 | x535 | 32 | hNb\xFF |
|
| x10 | xDDC1 |xDDC1| x0D | ' ' | x703 | x5E9 | x535 | 32 | hNb\xFF |
|
||||||
| x10 | xDDC1 |xDDC1| x0F | ‘ ‘ | x70B | x5EF | x537 | 32 | hHX\xFF |
|
| x10 | xDDC1 |xDDC1| x0F | ' ' | x70B | x5EF | x537 | 32 | hHX\xFF |
|
||||||
| x10 | xDDC1 |xDDC1| x10 | ‘ ‘ | x6FE | x5E9 | x539 | 32 | hZa\xFF |
|
| x10 | xDDC1 |xDDC1| x10 | ' ' | x6FE | x5E9 | x539 | 32 | hZa\xFF |
|
||||||
| x21 | x4D | x47 | x0C | ‘QMT476 ‘ | x6D8 | x5F3 | x52D | 64 | hlR\xBF |
|
| x21 | x4D | x47 | x0C | 'QMT476 ' | x6D8 | x5F3 | x52D | 64 | hlR\xBF |
|
||||||
| x21 | x36 | x47 | x0A | ‘QRW813 ‘ | x6DF | x5F3 | x539 | 64 | hhF\xFF |
|
| x21 | x36 | x47 | x0A | 'QRW813 ' | x6DF | x5F3 | x539 | 64 | hhF\xFF |
|
||||||
| x21 | x41 | x1E | x12 | ‘SNG712 ‘ | x6EB | x5F0 | x526 | 64 | hjS\xFF |
|
| x21 | x41 | x1E | x12 | 'SNG712 ' | x6EB | x5F0 | x526 | 64 | hjS\xFF |
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<hr>© 2020-2025 Renaud Fivet
|
<hr>© 2020-2025 Renaud Fivet
|
||||||
|
@@ -13,7 +13,7 @@ Getting started with a micro-controller usually means picking up a board,
|
|||||||
an IDE, some RTOS or a set of libraries. Depending of your level of experience,
|
an IDE, some RTOS or a set of libraries. Depending of your level of experience,
|
||||||
your budget and the solutions you select, the learning curve may be a steep
|
your budget and the solutions you select, the learning curve may be a steep
|
||||||
one and what you will learn could be very limited if you end up cornered in a
|
one and what you will learn could be very limited if you end up cornered in a
|
||||||
sandbox with no understanding of what’s going on under the hood.
|
sandbox with no understanding of what's going on under the hood.
|
||||||
<p>
|
<p>
|
||||||
Commercial solutions and mature open source projects are a must if you want to
|
Commercial solutions and mature open source projects are a must if you want to
|
||||||
develop products with some level of quality. Unfortunately their complexity is
|
develop products with some level of quality. Unfortunately their complexity is
|
||||||
@@ -24,7 +24,7 @@ not addressing what you need to learn.
|
|||||||
Starting from scratch, on the other hand, is not something often documented and
|
Starting from scratch, on the other hand, is not something often documented and
|
||||||
when it is, it is usually after the fact. So if you want to learn how to do it
|
when it is, it is usually after the fact. So if you want to learn how to do it
|
||||||
you need to catch the opportunity to watch someone going through the steps and
|
you need to catch the opportunity to watch someone going through the steps and
|
||||||
explaining what’s going on.
|
explaining what's going on.
|
||||||
<p>
|
<p>
|
||||||
I will try to capture here my own “STM32 bring up” journey using a step by step
|
I will try to capture here my own “STM32 bring up” journey using a step by step
|
||||||
approach, writing down the problems faced and decisions taken while evolving
|
approach, writing down the problems faced and decisions taken while evolving
|
||||||
@@ -62,7 +62,7 @@ for further evolution.
|
|||||||
|
|
||||||
<h2><a id="part2">Part II: Let's talk!</a></h2>
|
<h2><a id="part2">Part II: Let's talk!</a></h2>
|
||||||
|
|
||||||
It’s time to move to a more talkative interface so that the board not
|
It's time to move to a more talkative interface so that the board not
|
||||||
only winks but also speaks. Again I will go through several steps to get
|
only winks but also speaks. Again I will go through several steps to get
|
||||||
to a working interrupt driven asynchronous serial communication.
|
to a working interrupt driven asynchronous serial communication.
|
||||||
<ul>
|
<ul>
|
||||||
@@ -117,8 +117,12 @@ during startup.
|
|||||||
<li> Read a <a href="39_resistor.html">Resistor</a> Value.
|
<li> Read a <a href="39_resistor.html">Resistor</a> Value.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Appendices</h2>
|
<h2><a id="part4">Part IV: What You See Is What You Get!</a></h2>
|
||||||
|
<ul>
|
||||||
|
<li> Display temperature readings on a quad 7 segment LED display.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Appendices</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li> <a href="AA_factory.html">Factory-programmed</a> values.
|
<li> <a href="AA_factory.html">Factory-programmed</a> values.
|
||||||
</ul>
|
</ul>
|
||||||
|
Reference in New Issue
Block a user