From 2229b2b5a0d43dfed30510333b84066c16f8f570 Mon Sep 17 00:00:00 2001 From: Michael Droogleever Date: Sun, 8 Jul 2018 20:51:21 +0200 Subject: [PATCH] Update setup and getting-started, add display --- README.md | 4 +- src/SUMMARY.md | 17 +- src/choice/00.00.README.md | 10 ++ src/display/00.00.README.md | 11 ++ src/display/01.00.THEORY.md | 26 +++ src/display/02.00.PROBLEM.md | 21 +++ src/display/02.01.LAYOUT.md | 38 +++++ src/display/02.02.DELAY.md | 50 ++++++ src/display/02.03.MULT.md | 22 +++ src/getting-started/02.00.FLASH.md | 62 ++++---- src/getting-started/03.00.LED.md | 4 + src/getting-started/04.00.DEBUG.md | 211 +++++++++++++++++++++++++ src/getting-started/04.00.DEBUGGING.md | 1 - src/hardware/README.md | 12 +- src/requirements/README.md | 5 +- src/setup/LINUX.md | 47 +----- src/setup/MACOS.md | 4 +- src/setup/README.md | 6 +- src/setup/VERIFY.md | 87 ++++------ src/setup/WINDOWS.md | 11 +- 20 files changed, 501 insertions(+), 148 deletions(-) create mode 100644 src/choice/00.00.README.md create mode 100644 src/display/00.00.README.md create mode 100644 src/display/01.00.THEORY.md create mode 100644 src/display/02.00.PROBLEM.md create mode 100644 src/display/02.01.LAYOUT.md create mode 100644 src/display/02.02.DELAY.md create mode 100644 src/display/02.03.MULT.md create mode 100644 src/getting-started/04.00.DEBUG.md delete mode 100644 src/getting-started/04.00.DEBUGGING.md diff --git a/README.md b/README.md index e7e0846..ab03d3d 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7c51469..f82f1ee 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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) diff --git a/src/choice/00.00.README.md b/src/choice/00.00.README.md new file mode 100644 index 0000000..610a9f8 --- /dev/null +++ b/src/choice/00.00.README.md @@ -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. diff --git a/src/display/00.00.README.md b/src/display/00.00.README.md new file mode 100644 index 0000000..8c20dee --- /dev/null +++ b/src/display/00.00.README.md @@ -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 diff --git a/src/display/01.00.THEORY.md b/src/display/01.00.THEORY.md new file mode 100644 index 0000000..f2e1277 --- /dev/null +++ b/src/display/01.00.THEORY.md @@ -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 diff --git a/src/display/02.00.PROBLEM.md b/src/display/02.00.PROBLEM.md new file mode 100644 index 0000000..dd0a30d --- /dev/null +++ b/src/display/02.00.PROBLEM.md @@ -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. diff --git a/src/display/02.01.LAYOUT.md b/src/display/02.01.LAYOUT.md new file mode 100644 index 0000000..357334f --- /dev/null +++ b/src/display/02.01.LAYOUT.md @@ -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 diff --git a/src/display/02.02.DELAY.md b/src/display/02.02.DELAY.md new file mode 100644 index 0000000..34e7f9d --- /dev/null +++ b/src/display/02.02.DELAY.md @@ -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); +} +``` diff --git a/src/display/02.03.MULT.md b/src/display/02.03.MULT.md new file mode 100644 index 0000000..6b2fd77 --- /dev/null +++ b/src/display/02.03.MULT.md @@ -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 diff --git a/src/getting-started/02.00.FLASH.md b/src/getting-started/02.00.FLASH.md index 4717cc8..6f79be7 100644 --- a/src/getting-started/02.00.FLASH.md +++ b/src/getting-started/02.00.FLASH.md @@ -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 + + Connect the mirco:bit to your computer and run the following commands on a new terminal. -``` console + 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 '. + http://openocd.org/doc/doxygen/bugs.html +Info : auto-selecting first available session transport "swd". To override use 'transport select '. +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 diff --git a/src/getting-started/03.00.LED.md b/src/getting-started/03.00.LED.md index b4343de..419d543 100644 --- a/src/getting-started/03.00.LED.md +++ b/src/getting-started/03.00.LED.md @@ -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. diff --git a/src/getting-started/04.00.DEBUG.md b/src/getting-started/04.00.DEBUG.md new file mode 100644 index 0000000..b84db3c --- /dev/null +++ b/src/getting-started/04.00.DEBUG.md @@ -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 + 0x08000194 <+12>: b.n 0x8000194 + +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. diff --git a/src/getting-started/04.00.DEBUGGING.md b/src/getting-started/04.00.DEBUGGING.md deleted file mode 100644 index 1e584c9..0000000 --- a/src/getting-started/04.00.DEBUGGING.md +++ /dev/null @@ -1 +0,0 @@ -# Debugging diff --git a/src/hardware/README.md b/src/hardware/README.md index 6646823..a8ae0ee 100644 --- a/src/hardware/README.md +++ b/src/hardware/README.md @@ -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. diff --git a/src/requirements/README.md b/src/requirements/README.md index bf5c398..5bb8782 100644 --- a/src/requirements/README.md +++ b/src/requirements/README.md @@ -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. diff --git a/src/setup/LINUX.md b/src/setup/LINUX.md index fc22c8a..14bc98e 100644 --- a/src/setup/LINUX.md +++ b/src/setup/LINUX.md @@ -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: diff --git a/src/setup/MACOS.md b/src/setup/MACOS.md index fa9935e..fdb090d 100644 --- a/src/setup/MACOS.md +++ b/src/setup/MACOS.md @@ -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 diff --git a/src/setup/README.md b/src/setup/README.md index ad51fca..89f6113 100644 --- a/src/setup/README.md +++ b/src/setup/README.md @@ -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) diff --git a/src/setup/VERIFY.md b/src/setup/VERIFY.md index 0350f5b..9ea1a2a 100644 --- a/src/setup/VERIFY.md +++ b/src/setup/VERIFY.md @@ -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 '. + http://openocd.org/doc/doxygen/bugs.html +Info : auto-selecting first available session transport "swd". To override use 'transport select '. +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`. diff --git a/src/setup/WINDOWS.md b/src/setup/WINDOWS.md index 7da7729..a70d0bb 100644 --- a/src/setup/WINDOWS.md +++ b/src/setup/WINDOWS.md @@ -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