Commit bff90725 authored by Jake Read's avatar Jake Read
Browse files

finish basic notes, can flash w/ pyOCD

parent 6211a2a6
...@@ -2,42 +2,7 @@ ...@@ -2,42 +2,7 @@
[CMSIS-DAP](https://www.keil.com/support/man/docs/dapdebug/dapdebug_introduction.htm) is an *interface firmware* that connects microcontrollers to our PCs over USB, specifically for debugging code running on our microcontrollers, or loading new code onto them. [CMSIS-DAP](https://www.keil.com/support/man/docs/dapdebug/dapdebug_introduction.htm) is an *interface firmware* that connects microcontrollers to our PCs over USB, specifically for debugging code running on our microcontrollers, or loading new code onto them.
If you know how all of this stuff generally works, continue past the next two sections. If this is already confusing, you can check [this out](prog-doc.md).
### Que?
If the above statement doesn't make immediate sense, here's what's up:
Every time our our microcontroller is reset, it starts operating the program that currently resides in its memory. This means that in order to load a new program onto the microcontroller, we need some way of writing into that memory from another device.
This normally means that we write (human readable) code on our PC / Laptop / Whatever, compile it using a *toolchain* that knows how our device is shaped (alignments, bus widths, processor architectures etc) into byte code (machine readable), and then use some device to write that byte-code into the microcontroller's memory. Then, next time it wakes up (or we reset it) the microcontroller starts running our program!
Microcontrollers have pins that are specifically made for loading programs into their memory - these are known as 'debug ports' and ARM chips commonly use [JTAG](https://en.wikipedia.org/wiki/JTAG) or [SWD](https://en.wikipedia.org/wiki/JTAG#Similar_interface_standards). Our programming device (here it's the CMSIS-DAP) communicates to our PC using a USB connection on one side, and to our microcontroller using JTAG or SWD on the other side.
Different microcontrollers have different debug ports: AVR chips have ISP (In System Programming) debug ports, XMEGA chips use PDI, and some ATTINYs use UPDI - these are [well explained here](https://www.kanda.com/blog/microcontrollers/avr-microcontrollers/avr-microcontroller-programming-interfaces-isp-jtag-tpi-pdi-updi/). CMSIS-DAP only talks to JTAG or SWD ports: others need other programmers, i.e. the [ATMEL-ICE](https://www.microchip.com/DevelopmentTools/ProductDetails/ATATMEL-ICE) [AVR ISP](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATAVRISP2) or [FAB ISP](https://fab.cba.mit.edu/classes/863.16/doc/projects/ftsmin/index.html) that you can make yourself.
Here's an abbreviated list of the system layers (not aligned) we're putting together when we do this:
**rows are not aligned**
| Human Codes | Compilers | Byte Code -> Device Port (tool) | Device Debug Ports |
| --- | --- | --- | --- |
| c | avr-gcc | cmsis-dap | jtag |
| c++ | gnu-arm-gcc | atmel-ice | swd |
| | | avr-isp | pdi |
| | | fab-isp | isp |
| | | usb | updi |
| | | | bootloader (self program) |
### What's a bootloader?
Occasionally, we don't need a programming device in order to load code onto microcontrollers, as is the case with Arduino and other development boards. What gives?
These boards have [*bootloaders*](https://learn.adafruit.com/bootloader-basics) already written into their program memory. These are little programs that run *in the microcontroller* when they are reset. They start up, listen for some communication from your computer telling them that a new program is incoming, and if one doesn't exist, continue to the code loaded in the rest of their memory.
Basically, when a bootloader is present, the microcontroller itself takes on the role of the 'byte code -> device port' tool: this is known as 'self-programming' - the microcontroller writes your new program into its own memory.
Trouble is, when we make our own boards, we need to be able to load our own bootloaders (bootstrapping them...) and we need to do this with a tool like a CMSIS-DAP, AVR ISP etc.
## 1: Connect CMSIS-DAP to your Device ## 1: Connect CMSIS-DAP to your Device
...@@ -56,11 +21,23 @@ To connect this to your circuit, you'll want to put a 2x5 header on your circuit ...@@ -56,11 +21,23 @@ To connect this to your circuit, you'll want to put a 2x5 header on your circuit
- connect SWDIO to SWDIO (read the datasheet!) - connect SWDIO to SWDIO (read the datasheet!)
- connect SWDCLK to SWDCLK (consider a pullup on this line as well) - connect SWDCLK to SWDCLK (consider a pullup on this line as well)
Hopefully you already have a circuit with a working debug port (maybe one that someone else designed), if you're starting from scratch, a strategy I often use to make sure I will have programming success is to copy someone else's basic schematic: i.e. the [Adafruit Trinket M0](https://github.com/adafruit/Adafruit-Trinket-M0-PCB) is a good ground-zero for the SAMD21E18 chip, and the [Adafruit Feather M4](https://github.com/adafruit/Adafruit-Feather-M4-Express-PCB) is a good ground-zero for the SAMD51J19. Thanks adafruit! One note: they don't use the 2x5 pin header, instead, they use pogo pins on the board to break out SWDIO and SWDCLK. Just swap in a connector!
**Note** the CMSIS-DAP tool does not *provide* power to your circuit, it merely reads it to check that the device is alive. When you're programming the circuit, be sure to power it as well! For this reason, I often put a USB connector on my circuits to easily supply 5v. **Note** the CMSIS-DAP tool does not *provide* power to your circuit, it merely reads it to check that the device is alive. When you're programming the circuit, be sure to power it as well! For this reason, I often put a USB connector on my circuits to easily supply 5v.
### TODO: example schem for the D51 and D21 ### SAMD51 Example
I built a barebones example for this chip, showing how I connect the 2x5-pin programming header, as well as set up the basic components I'll need (power regulation, USB connection) to get it running. Take note that some of the connections (SWD.. USB..) are not drawn completely: the nets are [named in eagle to connect them](https://electronics.stackexchange.com/questions/104575/how-to-create-wireless-networks-in-eagle-cad).
This schematic will work with the Feather M4 Bootloader. Note that the KHZ Crystal *is necessary* for the bootloader to work, but is not necessary for you to program your own system.
![samd51](samd51-example/schematic.png)
### SAMD21 Example
Here's another, for the SAMD21. This schematic will work with the Trinket M0 Bootloader.
This is all a bit much. A strategy I often use to make sure I will have programming success is to copy someone else's basic schematic: i.e. the [Adafruit Trinket M0](https://github.com/adafruit/Adafruit-Trinket-M0-PCB) is a good ground-zero for the SAMD21E18 chip, and the [Adafruit Feather M4](https://github.com/adafruit/Adafruit-Feather-M4-Express-PCB) is a good ground-zero for the SAMD51J19. Thanks adafruit! One note: they don't use the 2x5 pin header, instead, they use pogo pins on the board to break out SWDIO and SWDCLK. Just swap in a connector! ![samd21](samd21-example/schematic.png)
## 2: Connecting CMSIS-DAP to your Computer ## 2: Connecting CMSIS-DAP to your Computer
...@@ -68,46 +45,76 @@ A CMSIS-DAP tool itself should announce itself to your computer automatically (o ...@@ -68,46 +45,76 @@ A CMSIS-DAP tool itself should announce itself to your computer automatically (o
Now I need to get a software system that will talk to the CMSIS-DAP tool. Now I need to get a software system that will talk to the CMSIS-DAP tool.
## 3a: ARM MDK to CMSIS-DAP ## 3: Flashing .hex or .bin via CMSIS-DAP and pyOCD
To verify I could flash my board using the CMSIS-DAP tool, I first tried operating it with the [ARM MDK](http://www2.keil.com/mdk5) which is an install that will bring with it everything you need to write and flash code onto any ARM microcontroller. Sometimes, the move is to use a tool like CMSIS-DAP to load a bootloader onto our device, and then just use that bootloader routinely to re-program it / develop code.
This can be a little intimidating if you've not experienced big IDEs before, but it's well supported and used commercially, so it's a good ground truth also. Here's what I did: To do this, you'll want to borrow a bootloader from someone who's written lots of them: I use [Adafruit Bootloaders](https://github.com/adafruit/ArduinoCore-samd/tree/master/bootloaders/) fairly often. To ensure that this works, I need to make that my circuit is compatible with the bootloader I'm going to use. The **Trinket M0 Bootloader** is a great, lightweight bootloader for the **SAMD21E18** and the **Feather M4 Express Bootloader** is similar for the **SAMD51J19**. These match the schematics above.
OK, this looks like it works, but our target board is a bit messed up. Of course, the hex you're flashing doesn't have to be a bootloader... any program will compile into .hex or .bin. Forgive me for dawdling:
- had to install package manually, https://packs.download.microchip.com/ find D21 support package, download, rename .atpack to .pack, import in keil package manager
- [pack installer](https://www.keil.com/support/man/docs/uv4/uv4_ca_packinstaller.htm)
- to setup project, bring in core components in keil as well during 'new project' wizard: selections,
- do boilerplate code main.c, int main(void){}, do #include "samd21e17a.h" for HAL
- get your pins right
- atmel-ice, sam port, do device progamming -> memories ...
- load trinket m0 booloader (zero bl uses xtal)
- keil setup,
- cmsis-dap automatically announces itself (on windows)
- keil setup to do
- tools ... setup flash tools ... find tab 'debug'
- 'use' cmsis-dap debugger
- do 'setup' to the right
- do 'port' SW (not JTAG)
confirmed that the cmsis-dap works. need to be able to flash with the cmsis-dap. first, do that, or find some gui (doubt it) for it. CMSIS-DAP is just the tool that *connects* our computer to our microcontroller, we need also a program on our computer to operate the CMSIS-DAP. On this end, I've tested [pyOCD](https://github.com/pyocd/pyOCD) (for Python On Chip Debugger), but other tools exist.
## 3b: Platformio to CMSIS-DAP ### 3.1: Install pyOCD
[Platformio](https://platformio.org/) is a great tool that I've been using to write all of my embedded code lately. It's an extension for [VSCode](https://code.visualstudio.com/), which is essentially Microsoft's fork of [atom](https://atom.io/) (in case you're interested). Their install documentation is better than mine, you can [read it here](https://github.com/pyocd/pyOCD#installing) to complete this step.
I (on windows) had to install python, visualstudio, and had to make sure [python was on my PATH](https://datatofish.com/add-python-to-windows-path/) so that I could invoke it from the command prompt. I also had to add the pyocd scripts to my PATH, they were located at `c\users\<username>\appdata\roaming\python39\scripts`.
### 3.2: Setup pyOCD
pyOCD comes out of the box with support for a bunch of microcontrollers, but not the ones I want (the D21 and D51 series). Target support is [managed well in pyOCD](https://github.com/pyocd/pyOCD/blob/master/docs/target_support.md) but I couldn't find my chips with their 'target find' tools, so I just downloaded them myself.
Downloads for Atmel Chips are at [https://packs.download.microchip.com/](https://packs.download.microchip.com/), you can `ctrl+f` for `D21` etc and get the most recent. **Importantly** you need to rename the `.atpack` to `.pack` - don't ask my why microchip is trying to use different file extensions than anyone else.
To point pyOCD at these packs, they have a great little [yaml config](https://github.com/pyocd/pyOCD/blob/master/docs/configuration.md) tool. I made a new folder this exercise, and added a `pyocd.yaml` file there, like:
```yaml
pack:
- Microchip.SAMD51_DFP.3.3.76.pack
- Microchip.SAMD21_DFP.3.3.98.pack
```
Using CMSIS-DAP for a platformio project is [supported](https://docs.platformio.org/en/latest/plus/debug-tools/cmsis-dap.html), but I still need to figure out how to set it up for use on a custom board... this is on the way. That points pyOCD at these files (which are also in the folder) so that anytime I call a pyOCD script from this folder, it uses this config. Rad. I included that folder in this repo.
### 4: Loading .bin .hex etc directly Now I can do the magic:
- connect the cmsis-dap tool to the circuit
- connect the cmsis-dap tool to my computer
- power on my board (the cmsis-dap tool *measures* voltage, it doesn't provide it)
- open a terminal / command prompt / etc in the pyOCD folder with your config and hex file in it
- run `pyocd flash -t <your target> <your .hex or .bin>`
- i.e. `pyocd flash -t atsamd51j19a bootloader-feather_m4-v3.10.0.bin`
Sometimes, the move is to use a tool like CMSIS-DAP to load a bootloader onto our device, and then just use that bootloader routinely to re-program it / develop code. To find your target name, you can do `pyocd list --targets`
To do this, you'll want to borrow a bootloader from someone who's written lots of them: I use [Adafruit Bootloaders](https://github.com/adafruit/ArduinoCore-samd/tree/master/bootloaders/) fairly often. To ensure that this works, I need to make that my circuit is compatible with the bootloader I'm going to use. The **Trinket M0 Bootloader** is a great, lightweight bootloader for the **SAMD21E18**and the **Feather M4 Express Bootloader** is similar for the **SAMD51J19**. ## 4a: Programming, Debugging in ARM MDK with CMSIS-DAP
**Note** these need to be *very* compatible: i.e. the *E18* and *J19* variants of the D21 and D51 respectively need to be used for those bootloaders to work. Additionally, external crystals (and USB lines) must be connected for these to work, if they're present in the design you're borrowing a bootloader from. If you want to go beyond, and use these tools to program and debug chips, I have also spent *some* time trying to figure out how to set that up.
#### TODO: how to command-line (?) cmsis-dap .hex files? To verify I could flash my board using the CMSIS-DAP tool, I first tried operating it with the [ARM MDK](http://www2.keil.com/mdk5) which is an install that will bring with it everything you need to write and flash code onto any ARM microcontroller.
This can be a little intimidating if you've not experienced big IDEs before, but it's well supported and used commercially, so it's a good ground truth also. Here's what I did:
OK, this looks like it works, but it was a bit messy, here are some brief notes.
- install [the ARM MDK](https://www2.keil.com/mdk5) that includes 'uVision' (IDE)
- this manages device packs, a lot like pyOCD, but:
- had to install package manually, https://packs.download.microchip.com/ find D21 support package, download, rename .atpack to .pack, [import manually](https://www.keil.com/support/man/docs/uv4/uv4_ca_packinst_imp.htm) in keil package manager
- setup a new project in uVision: the wizard is OK.
- add a new `main.c` file to the project, recall boilerplate c code:
- `#include "samde18a.h" // include the hardware definitions`
- `int main(void){<some test code>}`
- setup the project to use cmsis-dap debugger
- tools ... setup flash tools ... find tab 'debug'
- 'use' cmsis-dap debugger
- do 'setup' to the right
- do 'port' SW (not JTAG)
- build your project with `F7`
- flash your board with `F8`
Those are pretty rough notes, but I can testify that this works well on a windows machine.
## 4b: Programming, Debugging in Platformio with CMSIS-DAP
[Platformio](https://platformio.org/) is a great tool that I've been using to write all of my embedded code lately. It's an extension for [VSCode](https://code.visualstudio.com/), which is essentially Microsoft's fork of [atom](https://atom.io/) (in case you're interested).
https://github.com/adafruit/Adafruit-Trinket-M0-PCB Using CMSIS-DAP for a platformio project is [supported](https://docs.platformio.org/en/latest/plus/debug-tools/cmsis-dap.html), but I still need to figure out how to set it up for use on a custom board... this is on the way.
https://github.com/arduino/ArduinoCore-samd/ \ No newline at end of file
https://github.com/adafruit/ArduinoCore-samd/tree/master/bootloaders/trinketm0
### Que?
If the above statement doesn't make immediate sense, here's what's up:
Every time our our microcontroller is reset, it starts operating the program that currently resides in its memory. This means that in order to load a new program onto the microcontroller, we need some way of writing into that memory from another device.
This normally means that we write (human readable) code on our PC / Laptop / Whatever, compile it using a *toolchain* that knows how our device is shaped (alignments, bus widths, processor architectures etc) into byte code (machine readable), and then use some device to write that byte-code into the microcontroller's memory. Then, next time it wakes up (or we reset it) the microcontroller starts running our program!
Microcontrollers have pins that are specifically made for loading programs into their memory - these are known as 'debug ports' and ARM chips commonly use [JTAG](https://en.wikipedia.org/wiki/JTAG) or [SWD](https://en.wikipedia.org/wiki/JTAG#Similar_interface_standards). Our programming device (here it's the CMSIS-DAP) communicates to our PC using a USB connection on one side, and to our microcontroller using JTAG or SWD on the other side.
Different microcontrollers have different debug ports: AVR chips have ISP (In System Programming) debug ports, XMEGA chips use PDI, and some ATTINYs use UPDI - these are [well explained here](https://www.kanda.com/blog/microcontrollers/avr-microcontrollers/avr-microcontroller-programming-interfaces-isp-jtag-tpi-pdi-updi/). CMSIS-DAP only talks to JTAG or SWD ports: others need other programmers, i.e. the [ATMEL-ICE](https://www.microchip.com/DevelopmentTools/ProductDetails/ATATMEL-ICE) [AVR ISP](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATAVRISP2) or [FAB ISP](https://fab.cba.mit.edu/classes/863.16/doc/projects/ftsmin/index.html) that you can make yourself.
Here's an abbreviated list of the system layers (not aligned) we're putting together when we do this:
**rows are not aligned**
| Human Codes | Compilers | Byte Code -> Device Port (tool) | Device Debug Ports |
| --- | --- | --- | --- |
| c | avr-gcc | cmsis-dap | jtag |
| c++ | gnu-arm-gcc | atmel-ice | swd |
| | | avr-isp | pdi |
| | | fab-isp | isp |
| | | usb | updi |
| | | | bootloader (self program) |
### What's a bootloader?
Occasionally, we don't need a programming device in order to load code onto microcontrollers, as is the case with Arduino and other development boards. What gives?
These boards have [*bootloaders*](https://learn.adafruit.com/bootloader-basics) already written into their program memory. These are little programs that run *in the microcontroller* when they are reset. They start up, listen for some communication from your computer telling them that a new program is incoming, and if one doesn't exist, continue to the code loaded in the rest of their memory.
Basically, when a bootloader is present, the microcontroller itself takes on the role of the 'byte code -> device port' tool: this is known as 'self-programming' - the microcontroller writes your new program into its own memory.
Trouble is, when we make our own boards, we need to be able to load our own bootloaders (bootstrapping them...) and we need to do this with a tool like a CMSIS-DAP, AVR ISP etc.
\ No newline at end of file
pack:
- Microchip.SAMD51_DFP.3.3.76.pack
- Microchip.SAMD21_DFP.3.3.98.pack
\ No newline at end of file
[Eagle]
Version="09 06 00"
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[Eagle]
Version="09 06 00"
Platform="Windows"
Globals="Globals"
Desktop="Desktop"
[Globals]
AutoSaveProject=1
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/comm.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/connector.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/dfet.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/fablab.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/lights.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/microcontrollers.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/motors.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/passives.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/power.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/raspberrypi_bastelstube_v13.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/sensor.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/supply1.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/tag-connect-2030.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/tag-connect-2050.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/usbraw.lbr"
UsedLibrary="C:/Dropbox/CBA/circuits/eagle/parts/SparkFun-Eagle-Libraries/SparkFun-Connectors.lbr"
[Win_1]
Type="Control Panel"
Number=0
[Desktop]
Screen="1920 1080"
Window="Win_1"
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment