Update setup and getting-started, add display

This commit is contained in:
Michael Droogleever
2018-07-08 20:51:21 +02:00
parent a7c1fc0c92
commit 2229b2b5a0
20 changed files with 501 additions and 148 deletions

View File

@@ -1,4 +1,6 @@
# MicroRust
# MicroRust
[![Build Status](https://travis-ci.org/droogmic/microrust.svg?branch=master)](https://travis-ci.org/droogmic/microrust)
> Learn embedded software in Rust on the micro:bit

View File

@@ -7,7 +7,7 @@
- [Meet your hardware](hardware/README.md)
- [Development environment setup](setup/README.md)
- [Linux](setup/LINUX.md)
- [Linux](setup/LINUX.md)
- [Windows](setup/WINDOWS.md)
- [macOS](setup/MACOS.md)
- [Verify the installation](setup/VERIFY.md)
@@ -16,15 +16,24 @@
- [Building](getting-started/01.00.PROJECT.md)
- [Flashing](getting-started/02.00.FLASH.md)
- [LED](getting-started/03.00.LED.md)
- [Debugging](getting-started/04.00.DEBUGGING.md)
- [Debugging](getting-started/04.00.DEBUG.md)
- [WIP - Hello world](hello-world/00.00.README.md)
- [Semi-hosting](hello-world/01.00.SEMIHOSTING.md)
- [UART](hello-world/02.00.UART.md)
- [WIP - Choose your own adventure](choice/00.00.README.md)
- [Choose your own adventure](choice/00.00.README.md)
- [WIP - LED display](display/00.00.README.md)
- [LED display](display/00.00.README.md)
- [Theory](display/01.00.THEORY.md)
- [Problem](display/02.00.PROBLEM.md)
- [Layout](display/02.01.LAYOUT.md)
- [Delays](display/02.02.DELAY.md)
- [Multiplexing](display/02.03.MULT.md)
- [WIP - Solution](display/03.00.SOLUTION.md)
- [Layout](display/03.01.LAYOUT.md)
- [Multiplexing](display/03.02.MULT.md)
- [Full](display/03.03.FULL.md)
- [WIP - Sensors and I²C](sensors/00.00.README.md)

View File

@@ -0,0 +1,10 @@
# Choose your own adventure
At this point of the book,
you know the basics to get you started with embedded development with Rust.
The following chapters are all independent of each other.
This means they can be done in any order,
and the only required knowledge is found in the chapters before this.
You can either follow the rest of the boo in order, or choose a chapter based on:
what sounds the most interesting, or contains the information to solve a problem.

View File

@@ -0,0 +1,11 @@
# WIP - LED display
This chapters follows on from the basic LED example from getting started.
The LEDs are wired up in a matrix, as described in [these schematics][schematics].
Only a small proportion of images can be displayed at once with this layout;
it is impossible for example to turn on both LED1 and LED11 without also having LED2 and LED10 turning on.
In this chapter we will be talking through how to achieve the impossible,
displaying any chosen image, and even adjusting the brightness!
[schematics]: https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf

View File

@@ -0,0 +1,26 @@
# Theory
## LED dot matrix display
A dot matrix display is a display containing a two dimensional array of points,
used to represent characters, symbols, or images.
All displays today are dot matrix displays, but vector displays also used to exist,
examples include radar displays and 1980s arcade games.
## Persistence of vision
In order to achieve full control of all LEDs we need to use an optical illusion called the [persistence of vision][pov].
This effect causes light which has ceased entering the eye to still be seen for a little while after it has disappeared.
## Multiplexing
Multiplexing is the combination of multiple signals over shared medium.
In this case, we will be using human vision to multiplex time and space divided signals
## Method
We are able to fully control one (circuit) row of LEDs at a time,
so by quickly looping through the rows lof LEDs,
we can let the brain blur them together into a complete image.
[pov]: https://en.wikipedia.org/wiki/Persistence_of_vision

View File

@@ -0,0 +1,21 @@
# Problem statement
> Display any given image on the micro:bit display.
> The image will be a 5x5 array, where 0 will represent off and 1 will represent on.
The following, for example, should display a heart:
``` rust
let heart = [
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 1],
[1, 0, 0, 0, 1],
[0, 1, 0, 1, 0],
[0, 0, 1, 0, 0],
];
```
At this point, you may know enough to solve the problem yourself.
If you want to jump straight to the solution, you can go to the end of the next section in this chapter.
This section will continue formally breaking this problem down into smaller and more tractable pieces.

View File

@@ -0,0 +1,38 @@
## LED layout
> Convert a 5x5 array into a 3x9 array to match the display's circuitry.
### Schematics
The [schem1] discussed earlier describe the electrical layout of the LEDs,
but they do not describe how it relates to the visual layout.
It would be a mistake to assume that the numbers 1 to 25 have any correlation
to the visual layout of the LEDs on the micro:bit as they do *NOT*.
It just happened to be that ROW0 and COL0 intersect at an LED in the top left corner.
### Reference design
To find the relationship between the electrical array and visual array,
we need to look at the reference design for the micro:bit.
This can be found through a link at the bottom of the [micro:bit hardware page][hw]
By navigating to the github page > PDF > Schematic Print,
you can find a [detailed electrical schematic for the micro:bit][schem2].
In the top right, you will see an array which can be defined in Rust as follows:
``` rust
const LED_LAYOUT: [[(usize, usize); 5]; 5] = [
[(0, 0), (1, 3), (0, 1), (1, 4), (0, 2)],
[(2, 3), (2, 4), (2, 5), (2, 6), (2, 7)],
[(1, 1), (0, 8), (1, 2), (2, 8), (1, 0)],
[(0, 7), (0, 6), (0, 5), (0, 4), (0, 3)],
[(2, 2), (1, 6), (2, 0), (1, 5), (2, 1)],
];
```
[schem1]: https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf
[hw]: http://tech.microbit.org/hardware/#links
[schem2]: https://github.com/microbit-foundation/microbit-reference-design/blob/master/PDF/Schematic%20Print/Schematic%20Prints.PDF

View File

@@ -0,0 +1,50 @@
## Delays
> Create a time delay.
Another piece of information you will need is how to create a time delay before moving to the next row.
we want the time spent switching LED lines on and off to be much shorter than the time spent waiting with LEDs on.
### For loop
A first attempt to implement the `delay` function
without using any peripherals is to implement it as a `for` loop delay:
``` rust
fn delay(ms: u16) {
const K: u16 = 16_000; // 16MHz microprocessor, needs to be tweaked
for _ in 0..(K*ms) {}
}
```
When compiled in release mode however, this is optimized away.
To solve this we could explicitly add an operation inside the loop.
The perfect candidate is the [NOP](https://en.wikipedia.org/wiki/NOP).
``` rust
fn delay(ms: u16) {
const K: u16 = 16_000; // 16MHz microprocessor, needs to be tweaked
for _ in 0..(K*ms) {
cortex_m::asm::nop();
}
}
```
### Timers
A better way of implementing delays is by using timers.
A one-shot timer (also called one pulse mode) works like an alarm clock.
You set it once with the amount of time you want, and then wait until it goes off.
Fortuinately for us, HAL crates usually have already solved this for us.
### Microbit
The microbit has 3 timers, we will use the first: TIMER0.
To use it, do the following:
``` rust
if let Some(p) = microbit::Peripherals::take() {
let mut delay = Delay::new(p.TIMER0);
delay.delay_ms(1000_u32);
}
```

22
src/display/02.03.MULT.md Normal file
View File

@@ -0,0 +1,22 @@
## Multiplexing
> Multiplex the rows of the matrix
The final task is to multiplex the rows of electrical matrix into a full image.
We will be doing this by scanning through the rows in the display.
### Pseudocode
In order to light up an LED,
the row needs to be set high and the column needs to be set low.
We will assume that at the start of a refresh cycle,
that all the rows are set low and all the columns are set high.
The order of operations during a refresh cycle is then, for each row:
1. set the row high
2. for each column
- set low if the LED associated with that row-column pair should be on
3. sleep for a known duration, you should find 2ms is sufficient
4. for each column
- set high
5. set the row low

View File

@@ -2,19 +2,23 @@
Flashing is the process of moving our program into the microcontroller's (persistent) memory. Once flashed, the microcontroller will execute the flashed program every time it is powered on.
In this case, our `rustled` program will be the only program in the microcontroller memory. By this I mean that there's nothing else running on the microcontroller: no OS, no "daemon", nothing. `rustled` has full control over the device. This is what is meant by *bare-metal* programming.
In this case, our `rustled` program will be the only program in the microcontroller memory. By this I mean that there's nothing else running on the microcontroller: no OS, no daemon, nothing. `rustled` has full control over the device. This is what is meant by *bare-metal* programming.
Onto the actual flashing. First thing we need is to do is launch OpenOCD. We did that in the previous section but this time we'll run the command inside a temporary directory (/tmp on *nix; %TEMP% on Windows).
> OS: operating system
> Daemon: program running in the background
<!-- Onto the actual flashing. First thing we need is to do is launch OpenOCD. We did that in the previous section but this time we'll run the command inside a temporary directory (/tmp on *nix; %TEMP% on Windows). -->
Connect the mirco:bit to your computer and run the following commands on a new terminal.
``` console
<!-- ``` console
$ # *nix
$ cd /tmp
$ # Windows
$ cd %TEMP%
```
``` -->
We need to give OCD the name of the interfaces we are using:
@@ -36,8 +40,13 @@ This SWD interface can be used to flash and debug a microcontroller.
It uses the CMSIS-DAP protocol for host debugging of application programs.
It will appear as a USB device when you connect the micro:bit to your laptop.
As for OpenOCD, it's software that provides some services like a *GDB server* on top of USB
devices that expose a debugging protocol like SWD or JTAG.
As for OpenOCD,
it's software that provides some services like a *GDB server*
on top of USB devices that expose a debugging protocol like SWD or JTAG.
> GDB: The **G**NU **d**e**b**ugger will allow us to debug our software
> by controlling the execution of our program.
> We will learn more about this a little bit later.
Onto the actual command: those `.cfg` files we are using instruct OpenOCD to look for
- a CMSIS-DAP USB interface device (`interface/cmsis-dap.cfg`)
@@ -46,32 +55,31 @@ Onto the actual command: those `.cfg` files we are using instruct OpenOCD to loo
The OpenOCD output looks like this:
``` console
Open On-Chip Debugger 0.9.0 (2016-04-27-23:18)
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
cortex_m reset_config sysresetreq
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 2.919073
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : CMSIS-DAP: SWD Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 1.0
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x0bb11477
Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints
```
The "6 breakpoints, 4 watchpoints" part indicates the debugging features the processor has
The "4 breakpoints, 2 watchpoints" part indicates the debugging features the processor has
available.
I mentioned that OpenOCD provides a GDB server so let's connect to that right now:
``` console
$ arm-none-eabi-gdb -q target/thumbv7em-none-eabihf/debug/led-roulette
Reading symbols from target/thumbv7em-none-eabihf/debug/led-roulette...done.
$ arm-none-eabi-gdb -q target/thumbv6m-none-eabi/debug/rustled
Reading symbols from target/thumbv6m-none-eabi/debug/rustled...done.
(gdb)
```
@@ -90,10 +98,9 @@ that port.
After entering this command, you'll see new output in the OpenOCD terminal:
``` diff
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : stm32f3x.cpu: hardware has 4 breakpoints, 2 watchpoints
+Info : accepting 'gdb' connection on tcp/3333
+Info : device id = 0x10036422
+Info : flash size = 256kbytes
+Info : nRF51822-QFAA(build code: H0) 256kB Flash
```
Almost there. To flash the device, we'll use the `load` command inside the GDB shell:
@@ -151,6 +158,7 @@ This will automate the last few steps so we don't need to repeatedly do the same
```
target remote :3333
load
continue
```
## LED
@@ -181,10 +189,10 @@ On the first sheet you should find a diagram with a grid of numbered LEDs.
> the LED at the point that they cross will have a potential difference across it,
> so current will flow and it will light up.
It is worth noting that the 5x5 array of LEDs is wired up as a 9x3 array, with 2 missing.
The 5x5 array of LEDs are actually wired up as a 3x9 array (3 rows by 9 columns), with 2 missing.
This is usually done to make the circuit design easier.
The fifth sheet shows how each row and column correspond to each GPIO pin.
The fifth sheet shows how each row and column correspond to each GPIO pin.
[hw]: http://tech.microbit.org/hardware/
[schematics]: https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf

View File

@@ -38,4 +38,8 @@ fn default_handler(irqn: i16) {
panic!("Unhandled exception (IRQn = {})", irqn);
}
```
It is worth noting that pin4 starts low, so does not need to be explicitly set low.
You now know enough to start playing around with the LED display,
but before you do, you should know to debug your Rust code on the micro:bit.

View File

@@ -0,0 +1,211 @@
# Debugging
We are already inside a debugging session so let's debug our program.
After the `load` command, our program is stopped at its *entry point*. This is indicated by the
"Start address 0x8000XXX" part of GDB's output. The entry point is the part of a program that a
processor / CPU will execute first.
The starter project I've provided to you has some extra code that runs *before* the `main` function.
At this time, we are not interested in that "pre-main" part so let's skip right to the beginning of
the `main` function. We'll do that using a breakpoint:
```
(gdb) break rustled::main
Breakpoint 1 at 0x8000218: file src/main.rs, line 8.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, rustled::main () at src/rustled/src/main.rs:13
13 let x = 42;
```
Breakpoints can be used to stop the normal flow of a program.
The `continue` command will let the program run freely *until* it reaches a breakpoint.
In this case, until it reaches the `main` function because there's a breakpoint there.
Note that GDB output says "Breakpoint 1".
Remember that our processor can only use four of these
breakpoints so it's a good idea to pay attention to these messages.
For a nicer debugging experience, we'll be using GDB's Text User Interface (TUI).
To enter into that mode, on the GDB shell enter the following command:
```
(gdb) layout src
```
> **NOTE** Apologies Windows users.
> The GDB shipped with the GNU ARM Embedded Toolchain doesn't support this TUI mode `:(`.
At any point you can leave the TUI mode using the following command:
```
(gdb) tui disable
```
OK. We are now at the beginning of `main`.
We can advance the program statement by statement using the `step` command.
So let's use that twice to reach the `y = x` statement.
Once you've typed `step` once you can just hit enter to run it again.
```
(gdb) step
14 _y = x;
```
If you are not using the TUI mode,
on each `step` call GDB will print back the current statement along with its line number.
We are now "on" the `y = x` statement; that statement hasn't been executed yet. This means that `x`
is initialized but `y` is not. Let's inspect those stack/local variables using the `print` command:
```
(gdb) print x
$1 = 42
(gdb) print &x
$2 = (i32 *) 0x10001fdc
(gdb) print _y
$3 = 134219052
(gdb) print &_y
$4 = (i32 *) 0x10001fd8
```
As expected, `x` contains the value `42`. `y`, however, contains the value `134219052` (?). Because
`_y` has not been initialized yet, it contains some garbage value.
The command `print &x` prints the address of the variable `x`. The interesting bit here is that GDB
output shows the type of the reference: `i32*`, a pointer to an `i32` value. Another interesting
thing is that the addresses of `x` and `_y` are very close to each other: their addresses are just
`4` bytes apart.
Instead of printing the local variables one by one, you can also use the `info locals` command:
```
(gdb) info locals
x = 42
_y = 134219052
```
OK. With another `step`, we'll be on top of the `loop {}` statement:
```
(gdb) step
17 loop {}
```
And `_y` should now be initialized.
```
(gdb) print _y
$5 = 42
```
If we use `step` again on top of the `loop {}` statement, we'll get stuck because the program will
never pass that statement. Instead, we'll switch to the disassemble view with the `layout asm`
command and advance one instruction at a time using `stepi`.
> **NOTE** If you used the `step` command by mistake and GDB got stuck, you can get unstuck by hitting `Ctrl+C`.
```
(gdb) layout asm
```
If you are not using the TUI mode, you can use the `disassemble /m` command to disassemble the
program around the line you are currently at.
```
(gdb) disassemble /m
Dump of assembler code for function led_roulette::main:
11 fn main() -> ! {
0x08000188 <+0>: sub sp, #8
12 let _y;
13 let x = 42;
0x0800018a <+2>: movs r0, #42 ; 0x2a
0x0800018c <+4>: str r0, [sp, #4]
14 _y = x;
0x0800018e <+6>: ldr r0, [sp, #4]
0x08000190 <+8>: str r0, [sp, #0]
15
16 // infinite loop; just so we don't leave this stack frame
17 loop {}
=> 0x08000192 <+10>: b.n 0x8000194 <led_roulette::main+12>
0x08000194 <+12>: b.n 0x8000194 <led_roulette::main+12>
End of assembler dump.
```
See the fat arrow `=>` on the left side? It shows the instruction the processor will execute next.
If not inside the TUI mode on each `stepi` command GDB will print the statement, the line number
*and* the address of the instruction the processor will execute next.
```
(gdb) stepi
0x08000194 17 loop {}
(gdb) stepi
0x08000194 17 loop {}
```
One last trick before we move to something more interesting. Enter the following commands into GDB:
```
(gdb) monitor reset halt
Unable to match requested speed 1000 kHz, using 950 kHz
Unable to match requested speed 1000 kHz, using 950 kHz
adapter speed: 950 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000188 msp: 0x10002000
(gdb) continue
Continuing.
Breakpoint 1, led_roulette::main () at src/main.rs:8
8 let x = 42;
```
We are now back at the beginning of `main`!
`monitor reset halt` will reset the microcontroller and stop it right at the program entry point.
The following `continue` command will let the program run freely until it reaches the `main`
function that has a breakpoint on it.
This combo is handy when you, by mistake, skipped over a part of the program that you were
interested in inspecting. You can easily roll back the state of your program back to its very
beginning.
> **The fine print**: This `reset` command doesn't clear or touch RAM. That memory will retain its
> values from the previous run. That shouldn't be a problem though, unless your program behavior
> depends of the value of *uninitialized* variables but that's the definition of Undefined Behavior
> (UB).
We are done with this debug session. You can end it with the `quit` command.
```
(gdb) quit
A debugging session is active.
Inferior 1 [Remote target] will be detached.
Quit anyway? (y or n) y
Detaching from program: $PWD/target/thumbv7em-none-eabihf/debug/led-roulette, Remote target
Ending remote debugging.
```
> **NOTE** If the default GDB CLI is not to your liking check out [gdb-dashboard].
> It uses Python to turn the default GDB CLI into a dashboard that shows registers,
> the source view, the assembly view and other things.
[gdb-dashboard]: https://github.com/cyrus-and/gdb-dashboard#gdb-dashboard
Don't close OpenOCD though! We'll use it again and again later on. It's better
just to leave it running.

View File

@@ -1 +0,0 @@
# Debugging

View File

@@ -46,13 +46,21 @@ What does this board contain? For full details see the [microbit hardware page][
- A second microcontroller: NXP/Freescale KL26Z. This microcontroller handles the USB interface,
communication between your computer and the main microcontroller,
and changing the USB's input voltage from 5V to 3.3V.
and converting the USB's input voltage from 5V to 3.3V.
## Micro-USB Cable
This can be any generic cable, and is used to connect the microbit to your computer.
This comes with your microbit but can be any generic cable,
and is used to connect the microbit to your computer.
## External battery pack
The external battery pack that comes with the microbit will not be used explicitly as part of this guide,
but feel free to use it to test your software without being tethered to a computer.
## Plugging it in
You can use the micro-USB cable to power the micro:bit, and to transfer data.
When you power up a new micro:bit you will see the display light up as the factory-installed program is executed.
Otherwise, the last program will automatically be executed.
The black reset button next to the USB input will restart the program being run.

View File

@@ -40,11 +40,12 @@ With other development boards, this text would lose most if not all its beginner
and "easy to follow"-ness, IMO.
There are other similar guides for different hardware. For a full list see [this list][books].
[books]: https://github.com/rust-embedded/awesome-embedded-rust/#books-blogs-and-training-materials
The following are worth a special mention:
- [Discovery](https://japaric.github.io/discovery/) by @japaric: The genesis guide which this is based on. Uses the STM32F3DISCOVERY.
[books]: https://github.com/rust-embedded/awesome-embedded-rust/#books-blogs-and-training-materials
If you have a different cortex-m development board and you don't consider yourself a total beginner, you are
better off starting with the [cortex-m-quickstart] project template.

View File

@@ -49,59 +49,20 @@ Then, use your editor of choice to append to your `PATH` in the appropriate shel
PATH=$PATH:$HOME/local/gcc-arm-none-eabi-7-2017-q4-major/bin
```
## Optional packages
- Ubuntu / Debian
``` console
$ sudo apt-get install \
bluez \
rfkill
```
- Fedora
``` console
$ sudo dnf install \
bluez \
rfkill
```
- Arch Linux
``` console
$ sudo pacman -S \
bluez \
bluez-utils \
rfkill
```
## udev rules
These rules let you use USB devices like the F3 and the Serial module without root privilege, i.e.
`sudo`.
Create these two files in `/etc/udev/rules.d` with the contents shown below.
``` console
$ cat /etc/udev/rules.d/99-ftdi.rules
```
``` text
# FT232 - USB <-> Serial Converter
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", GROUP="uucp"
```
Create this file in `/etc/udev/rules.d` with the contents shown below.
``` console
$ cat /etc/udev/rules.d/99-openocd.rules
```
``` text
# STM32F3DISCOVERY rev A/B - ST-LINK/V2
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", GROUP="uucp"
# STM32F3DISCOVERY rev C+ - ST-LINK/V2-1
ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", GROUP="uucp"
# microbit - CMSIS-DAP
ATTRS{idVendor}=="0d28", ATTRS{idProduct}=="0204", GROUP="uucp"
```
Then reload the udev rules with:
@@ -120,7 +81,7 @@ $ groups $(id -nu)
$ # ^^^^
```
(`$(id -nu)` returns your user name. In my case it's `japaric`.)
(`$(id -nu)` returns your user name.)
If `uucp` appears in the output. You are all set! Go to the [next section]. Otherwise, keep reading:

View File

@@ -1,5 +1,7 @@
# macOS
> UNTESTED: please submit an issue if you can confirm this works.
All the tools can be install using [Homebrew]:
[Homebrew]: http://brew.sh/
@@ -14,4 +16,4 @@ Caskroom/tap` first and try again.
That's all! Go to the [next section].
[next section]: 03-setup/verify.html
[next section]: 03-setup/VERIFY.html

View File

@@ -61,6 +61,6 @@ $ cargo install itm
Now follow the instructions specific to the OS you are using:
- [Linux](setup/linux.html)
- [Windows](setup/windows.html)
- [macOS](setup/macos.html)
- [Linux](setup/LINUX.html)
- [Windows](setup/WINDOWS.html)
- [macOS](setup/MACOS.html)

View File

@@ -6,28 +6,29 @@ Let's verify that all the tools were installed correctly.
### Verify permissions
Connect the F3 to your laptop using an USB cable. Be sure to connect the cable to the "USB ST-LINK"
port, the USB port in the center of the edge of the board.
Connect the micro:bit to your laptop using an USB cable.
The F3 should now appear as a USB device (file) in `/dev/bus/usb`. Let's find out how it got
enumerated:
The micro:bit should now appear as a USB device (file) in `/dev/bus/usb`.
Let's find out how it got enumerated:
``` console
$ lsusb | grep -i stm
Bus 003 Device 004: ID 0483:374b STMicroelectronics ST-LINK/V2.1
$ # ^^^ ^^^
$ lsusb | grep -i NXP
Bus 002 Device 033: ID 0d28:0204 NXP ARM mbed
^^^ ^^^
```
In my case, the F3 got connected to the bus #3 and got enumerated as the device #4. This means the
file `/dev/bus/usb/003/004` *is* the F3. Let's check its permissions:
In my case, the micro:bit got connected to the bus #2 and got enumerated as the device #33.
This means the file `/dev/bus/usb/002/033` *is* the Fmicro:bit3.
Let's check its permissions:
``` console
$ ls -l /dev/bus/usb/003/004
crw-rw-r-- 1 root uucp 189, 262 Oct 27 00:00 /dev/bus/usb/003/004
$ ls -l /dev/bus/usb/002/033
crw-rw---- 1 root uucp 189, 160 Jul 8 14:06 /dev/bus/usb/002/033
^^^^
```
The group should be `uucp`. If it's not ... then check your [udev rules] and try re-loading them
with:
The group should be `uucp`.
If it's not ... then check your [udev rules] and try re-loading them with:
[udev rules]: 03-setup/linux.html#udev%20rules
@@ -35,71 +36,45 @@ with:
$ sudo udevadm control --reload-rules
```
Now let's repeat the procedure for the Serial module.
Unplug the F3 and plug the Serial module. Now, figure out what's its associated file:
``` console
$ lsusb | grep -i ft232
Bus 003 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
```
In my case, it's the `/dev/bus/usb/003/005`. Now, check its permissions:
``` console
$ ls -l /dev/bus/usb/003/005
crw-rw-r--+ 1 root uucp 189, 261 Oct 27 00:00 /dev/bus/usb/003/005
```
As before, the group should be `uucp`.
## All
### First OpenOCD connection
First, connect the F3 to your laptop using an USB cable. Connect the cable to the USB port in the
center of edge of the board, the one that's labeled "USB ST-LINK".
Two *red* LEDs should turn on right after connecting the USB cable to the board.
First, connect the micro:bit to your computer using the micro-USB cable.
The *yellow* LED next to the USB input should turn on right after connecting the USB cable to the board.
Next, run this command:
``` console
$ # *nix
$ openocd -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg
$ openocd-f interface/cmsis-dap.cfg -f target/nrf51.cfg
$ # Windows
$ # NOTE cygwin users have reported problems with the -s flag. If you run into
$ # that you can call openocd from the `C:\OpenOCD\share\scripts` directory
$ openocd -s C:\OpenOCD\share\scripts -f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg
$ openocd -s C:\OpenOCD\share\scripts -f interface/cmsis-dap.cfg -f target/nrf51.cfg
```
> **NOTE** Windows users: `C:\OpenOCD` is the directory where you installed OpenOCD to.
> **IMPORTANT** There is more than one hardware revision of the STM32F3DISCOVERY board. For older
> revisions, you'll need to change the "interface" argument to `-f interface/stlink-v2.cfg` (note:
> no `-1` at the end). Alternatively, older revisions can use `-f board/stm32f3discovery.cfg`
> instead of `-f interface/stlink-v2-1.cfg -f target/stm32f3x.cfg`.
You should see output like this:
``` console
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
cortex_m reset_config sysresetreq
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v27 API v2 SWIM v15 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 2.915608
Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : CMSIS-DAP: SWD Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 1.0
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 0 TDO = 0 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x0bb11477
Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints
```
(If you don't ... then check the [general troubleshooting] instructions.)
@@ -108,7 +83,7 @@ Info : stm32f3x.cpu: hardware has 6 breakpoints, 4 watchpoints
`openocd` will block the terminal. That's fine.
Also, one of the red LEDs, the one closest to the USB port, should start oscillating between red
light and green light.
Also, the `yellow` LED should start blinking very fast.
It may seem concerning, but it is a good sign.
That's it! It works. You can now close/kill `openocd`.

View File

@@ -1,5 +1,7 @@
# Windows
> UNTESTED: please submit an issue if you can confirm this works.
## `arm-none-eabi-*`
ARM provides `.exe` installers for Windows. Grab one from [here][gcc], and follow the instructions.
@@ -38,13 +40,6 @@ Download the latest `putty.exe` from [this site] and place it somewhere in your
[this site]: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
## ST-LINK USB driver
You'll also need to install [this USB driver] or OpenOCD won't work. Follow the installer
instructions and make sure you install the right (32-bit or 64-bit) version of the driver.
[this USB driver]: http://www.st.com/en/embedded-software/stsw-link009.html
That's all! Go to the [next section].
[next section]: 03-setup/verify.html
[next section]: 03-setup/VERIFY.html