Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions _posts/2019-05-14-zero-to-main-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ francois-mba:zero-to-main francois$ xxd build/minimal/minimal.bin | head
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
```

If I'm reading this correctly, our inital SP is `0x20002000`, and our start
If I'm reading this correctly, our initial SP is `0x20002000`, and our start
address pointer is `0x000000c1`.

Let's dump our symbols to see which one is at `0x000000c1`.
Expand Down Expand Up @@ -323,7 +323,7 @@ More complex programs often require a more complicated `Reset_Handler`. For
example:
1. Relocatable code must be copied over
2. If our program relies on libc, we must initialize it
_EDIT: Post written!_ - [From Zero to main(): Bootstrapping libc with Newlib]({% post_url 2019-11-12-boostrapping-libc-with-newlib %})
_EDIT: Post written!_ - [From Zero to main(): Bootstrapping libc with Newlib]({% post_url 2019-11-12-bootstrapping-libc-with-newlib %})
3. More complex memory layouts can add a few copy / zero loops

We'll cover all of them in future posts. But before that,
Expand Down
2 changes: 1 addition & 1 deletion _posts/2019-06-06-best-firmware-size-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ $ arm-none-eabi-size build/with-libc.elf
So in this program we have:

- 10800 bytes of `text`, which is code
- 104 bytes of `data`, which is statically initalized memory
- 104 bytes of `data`, which is statically initialized memory
- 8272 bytes of `bss`, which is zero-initialized memory

Unfortunately, the output of this tool is a little misleading. You may think
Expand Down
2 changes: 1 addition & 1 deletion _posts/2019-07-30-bluetooth-low-energy-a-primer.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Every technology has its own benefits and limitations, and BLE is no exception.

### Benefits
- Lower power consumption even when compared to other low power technologies.
This is achived by keeping the radio off as much as possible and sending small amounts of data at low transfer speeds.
This is achieved by keeping the radio off as much as possible and sending small amounts of data at low transfer speeds.
- No cost to access the official specification documents. With most other wireless protocols and technologies, you would have to be a member of the official group or consortium for that technology in order to access the specification.
- Lower cost of modules and chipsets, even when compared to other similar technologies.
- Most importantly, its existence in most smartphones in the market.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ When selecting the software to use, the other item you want to look at is its bo

The actual GDB server used is usually based on the debug probe selected. Some of the common choices are:

- **pyOCD**[^10] A Python-based open source implementation compatible wth **CMSIS-DAP** and **ST-Link** debug probes. The project is maintained by ARM. This is my favorite gdbserver at the moment. If you want to understand more about the ARM Coresight internals, reading through the code itself is actually a great reference and being open source the framework can be easily extended to support a variety of use cases.
- **pyOCD**[^10] A Python-based open source implementation compatible with **CMSIS-DAP** and **ST-Link** debug probes. The project is maintained by ARM. This is my favorite gdbserver at the moment. If you want to understand more about the ARM Coresight internals, reading through the code itself is actually a great reference and being open source the framework can be easily extended to support a variety of use cases.
- **openOCD**[^11] A C-based open source `gdbserver` implementation for a wide array of debug probes. The project probably supports the widest array of debug probes out of any project available (you can run `openocd -c interface_list` to see) including **FTDI**, **CMSIS-DAP**, **J-Link** and about 17 other adapters. The project dates back to 2005 and while it has support for a wide array of parts I have found it to be a bit flaky to use for projects over the years.
- **SEGGER JLinkGDBServer**[^12] A proprietary `gdbserver` distributed as a binary. Has support for an impressive amount of devices. (You can find the list at `<SEGGER JLink install path>/JLinkDevices.xml`). I've found it to be quite reliable for debugging but when there are issues, things can be quite painful to fix without being able to see the source
- **texane/stlink**[^13] An open source implementation of the ST-Link Debug Probe protocol. This project is independently maintained and not affiliated with ST.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ or at [interrupt@memfault.com](mailto:interrupt@memfault.com).

Next time in the series, we'll talk about bootstrapping the C library!

_EDIT: Post written!_ - [Bootstrapping libc with Newlib]({% post_url 2019-11-12-boostrapping-libc-with-newlib %})
_EDIT: Post written!_ - [Bootstrapping libc with Newlib]({% post_url 2019-11-12-bootstrapping-libc-with-newlib %})

> Interested in learning more device firmware update best practices? [Watch this webinar recording](https://hubs.la/Q02hgRrk0)

Expand Down
6 changes: 3 additions & 3 deletions _posts/2019-09-24-ble-throughput-primer.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ to fit in one LL packet) but the size can be negotiated via the _Exchange MTU Re

Per the Bluetooth Core Specification, the maximum allowed length of an attribute value (the ATT payload) is 512
bytes[^11]. While this technically means the MTU size can be slightly larger than 512 bytes (to
accomodate for the ATT protocol overhead), most bluetooth stacks support a maximum MTU value of 512 bytes.
accommodate for the ATT protocol overhead), most bluetooth stacks support a maximum MTU value of 512 bytes.

The packet looks like this:

Expand Down Expand Up @@ -170,7 +170,7 @@ As part of the 5.0 Bluetooth Core Specification revision, a new feature known as

![]({% img_url ble-throughput/ble-throughput-dple-and-2m-phy.png %})

We can calculate this throughput and see the modification yields almost a _4x_ improvement over the original maximal raw data speed that could be achived with BLE 4.0:
We can calculate this throughput and see the modification yields almost a _4x_ improvement over the original maximal raw data speed that could be achieved with BLE 4.0:

`251 bytes / 1400μs = 179.3 kBytes/sec = ~1.434 Mbps`

Expand Down Expand Up @@ -241,7 +241,7 @@ Many devices only support a subset of the valid connection parameter range (7.5m

> ![]({% img_url ble-throughput/apple-connection-parameters.png %})

A longer connection event in itself isn't necessarily a problem for throughput. Some devices will send and recieve data for an entire connection event so if you are streaming data continuously the same throughput can be realized even if you are using a 30ms interval instead of a 15ms interval.
A longer connection event in itself isn't necessarily a problem for throughput. Some devices will send and receive data for an entire connection event so if you are streaming data continuously the same throughput can be realized even if you are using a 30ms interval instead of a 15ms interval.

What the connection interval _does_ impact is latency. Many higher layer protocols have messages which need to be acknowledged by higher level software components. The longer the connection interval, the longer it will take for these round trips to complete

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ functions being used by that thread.

Some standard library functions depend on global memory which would not make
sense to hold in the `_reent` struct. This is especially important when using
`malloc` to allocate memory out of the heap. If mutliple threads try modifying
`malloc` to allocate memory out of the heap. If multiple threads try modifying
the heap at the same time, they risk corrupting it.

To allow multiple threads to call `malloc`, Newlib provides the `__malloc_lock`
Expand Down
2 changes: 1 addition & 1 deletion _posts/2019-11-20-cortex-m-hardfault-debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ Furthermore, we now have a variable we can read stack info from and a C function

#### Instrumenting the code

Many Real Time Operating Systems (**RTOS**) targetting Cortex-M devices will add options to dump
Many Real Time Operating Systems (**RTOS**) targeting Cortex-M devices will add options to dump
verbose fault register information to the console upon crash. Some examples include Arm Mbed OS[^2]
and Zephyr[^3]. For example, with Zephyr, the `illegal_instruction_execution()` crash looks like:

Expand Down
6 changes: 3 additions & 3 deletions _posts/2020-01-22-i2c-in-a-nutshell.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ signalling).
2. It supports up to 127 devices on a bus with only two pins.
3. It has transfer rates up to 400Kbps, which is fast enough for many human
interfaces as well as fan control, temperature sensing and other low-speed
contol loops.
control loops.
4. Historically, it has been less onerous for manufacturers to include than
competing protocols like Maxim's 1-wire protocol[^4].

Expand Down Expand Up @@ -242,7 +242,7 @@ device attempts to hold the clock down.

## Debugging I2C

While I2C is a robust and simple protocol, firmware engineers find themslves
While I2C is a robust and simple protocol, firmware engineers find themselves
debugging unresponsive devices on most projects.

Consider the following scenario: you just received a new board and are doing
Expand Down Expand Up @@ -408,7 +408,7 @@ below!

[^1]: [TotalPhase: 10-bit vs 7-bit I2C](https://www.totalphase.com/support/articles/200349176)
[^2]: [Salae: How to Analyze I2C](https://support.saleae.com/tutorials/example-projects/how-to-analyze-i2c)
[^3]: [StackExchange: What happens if I omit the pullup resitors?](https://electronics.stackexchange.com/questions/102611/what-happens-if-i-omit-the-pullup-resistors-on-i2c-line://electronics.stackexchange.com/questions/102611/what-happens-if-i-omit-the-pullup-resistors-on-i2c-lines)
[^3]: [StackExchange: What happens if I omit the pullup resistors?](https://electronics.stackexchange.com/questions/102611/what-happens-if-i-omit-the-pullup-resistors-on-i2c-line://electronics.stackexchange.com/questions/102611/what-happens-if-i-omit-the-pullup-resistors-on-i2c-lines)
[^4]: [Wikipedia: 1-Wire](https://en.wikipedia.org/wiki/1-Wire)
[^5]: [Wikipedia: SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface)
[^6]: [Wikipedia: CAN](https://en.wikipedia.org/wiki/Controller_area_network)
Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-02-04-rust-for-digital-signal-processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ As a C programmer, I was tempted to write the Rust code using an imperative
style. Instead, I decided to leverage Rust's syntax for functional programming,
as it maps neatly to digital signal processing concepts. While this is beyond
the scope of this article, I found that using a functional rather than
itterative approach yielded a ~2x improvement in performance in this case.
iterative approach yielded a ~2x improvement in performance in this case.

We filled in `src/lib.rs`, the file cargo auto-generated for us. It creates a
function `dsp_process_rs` which we will expose to our C code.
Expand Down
6 changes: 3 additions & 3 deletions _posts/2020-04-08-gnu-binutils.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ my_library_function lib_v2.c:6: Version 1
The behavior we observed above is because `ar`, unlike other Binutil commands, _appends_ to a
pre-existing file if it exists. With embedded software, since creating a new archive is very fast,
I recommend just deleting any pre-existing archive when a new one gets generated. For example, we
achieve this in the Make fule below by adding `rm -f $@` before the `ar` invocation:
achieve this in the Make rule below by adding `rm -f $@` before the `ar` invocation:

```bash
$(MYLIB_TARGET): $(MYLIB_OBJ_FILES)
Expand Down Expand Up @@ -779,7 +779,7 @@ $ arm-none-eabi-readelf -S nrf52_example/build/nrf52.elf | grep debug

`objcopy` is most commonly used as the last stage of a build to generate the `.bin` or `.hex` file which
can be flashed onto a device. Unlike an operating system where there is a "dynamic loader" that
resolves addresses and loads libaries at runtime, on embedded devices all of the memory locations
resolves addresses and loads libraries at runtime, on embedded devices all of the memory locations
are typically resolved at link time.

```bash
Expand Down Expand Up @@ -824,7 +824,7 @@ arm-none-eabi-nm -S -l my_binary.o
- `-a` To show the address which was decoded. This can be useful when decoding multiple addresses
at once or using `addr2line` in a batch processing mode.
- `-f` To display the function name the address is in
- `-e <ELF>` To specify the excutable to decode. (Otherwise, `addr2line` checks for `a.out` in the
- `-e <ELF>` To specify the executable to decode. (Otherwise, `addr2line` checks for `a.out` in the
working directory and uses that.)

#### Example Usage
Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-05-20-arm-cortexm-with-llvm-clang.md
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ are responsible for providing locations of the standard libraries in this scenar
implemented but Clang makes every effort to match the exact subset required by GCC.

Fortunately, for ARM Cortex-M development, the official GNU Arm toolchain[^1] bundles pre-compiled
variants of [Newlib's libc and libm]({% post_url 2019-11-12-boostrapping-libc-with-newlib %}).
variants of [Newlib's libc and libm]({% post_url 2019-11-12-bootstrapping-libc-with-newlib %}).

When you compile a project with the GNU Arm toolchain, `libc.a` & `libm.a` from the pre-compiled
Newlib as well as GCC's `libgcc.a` will be linked into your project automatically.
Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-06-23-device-firmware-update-cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ const image_hdr_t *image_get_header(image_slot_t slot) {
To validate the image, we compute its CRC and compare it with the value written
in the header. This will allow you to catch data corruption or bit errors, and
save you some trouble down the line. Note that verifying CRC on boot is not
appropriate for every applicaton, as it can slow down boot significantly.
appropriate for every application, as it can slow down boot significantly.

```c
int image_validate(image_slot_t slot, const image_hdr_t *hdr) {
Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-07-29-cortex-m-debug-monitor.md
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ Dump of assembler code for function dummy_function_4:
End of assembler dump.
```

We will install a breakpoint at address `0x270`, so if we single step after that we shold see, `0x272`,
We will install a breakpoint at address `0x270`, so if we single step after that we should see, `0x272`,
`0x274` and then a branch to `0x6c0` executed by the processor.

```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ static void prv_sha256(const void *buf, uint32_t size, uint8_t *hash_out)
}
```

Note that `cf_sha256_update` can be called mutliple times, so if you are
Note that `cf_sha256_update` can be called multiple times, so if you are
validating a binary that isn't memory mapped you can calculate the hash
iteratively rather than all at once. For example, here's an implementation that
reads from a POSIX file:
Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-10-06-separating-unique-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ them to binaries that can be flashed to the correct addresses. Instead, we
settled on creating IHEX files since they exactly meet our requirements, are
simple to generate and come with lots of great tooling.

### Building HEX File Programatically
### Building HEX File Programmatically

Hex files consist of lines of hexadecimal data, called records, that specify
both an address and the data to write at this address. The
Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-10-20-advanced-gdb.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ end
document xxd
Runs xxd on a memory ADDR and LENGTH

xxd ADDR LENTH
xxd ADDR LENGTH
end
```

Expand Down
4 changes: 2 additions & 2 deletions _posts/2020-11-04-mcuboot-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ Compile a new application with some kind of change so you can easily confirm it
--- a/example/mcuboot/application/src/main.c
+++ b/example/mcuboot/application/src/main.c
@@ -39,7 +39,8 @@ int main(void) {
// succesfully completed init, mark image as stable
// successfully completed init, mark image as stable
boot_set_confirmed();

EXAMPLE_LOG("==Main Application Booted==");
Expand Down Expand Up @@ -679,7 +679,7 @@ make 2>&1 | rg ": undefined.*" -o | sort -u

Examining the missing symbols we have three classes:

1. Missing Newlib platform dependency implementations. (We've seen these before in [our post about porting newlib]({% post_url 2019-11-12-boostrapping-libc-with-newlib %})).
1. Missing Newlib platform dependency implementations. (We've seen these before in [our post about porting newlib]({% post_url 2019-11-12-bootstrapping-libc-with-newlib %})).
2. The `tc_sha256_*` are missing implementations for the Tincrypt backend we are using.
3. The `flash_*` dependency functions defined in `flash_map_backend.h` need to be filled in.

Expand Down
2 changes: 1 addition & 1 deletion _posts/2020-12-08-seamless-firmware-with-platformio.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ embedded that is the best I've seen yet. I hope you will give it a whirl!

## What is PlatformIO?

<a href="https://platformio.org/" target="_blank">PlatformIO</a> is a set of open source tools targetted at professional embedded
<a href="https://platformio.org/" target="_blank">PlatformIO</a> is a set of open source tools targeted at professional embedded
developers. Foremost of those tools is the PlatformIO Plugin for VSCode which
is used by hundreds of thousands of embedded developers to create, compile,
debug, and test embedded projects.
Expand Down
4 changes: 2 additions & 2 deletions _posts/2020-12-15-defensive-and-offensive-programming.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ track down those 1 in 1,000-hour bugs, efficiently root cause them, and keep
your end-users happy. And, as a bonus, keep your sanity.

> To learn more about offensive and defensive programming best practices and ask
> me questions live, register for our [webinar on Febraury 24, 2022](https://hubs.la/Q013SXmN0).
> me questions live, register for our [webinar on February 24, 2022](https://hubs.la/Q013SXmN0).

{% include newsletter.html %}

Expand Down Expand Up @@ -581,7 +581,7 @@ I'd love to hear about any other strategies that you all take to surface bugs
that are hidden in your firmware! Come find me in the
[Interrupt Slack](https://interrupt-slack.herokuapp.com/).

> Interested in learning more offensive and defensive programming best practices? Register for our [webinar on Febraury 24, 2022](https://hubs.la/Q013SXmN0).
> Interested in learning more offensive and defensive programming best practices? Register for our [webinar on February 24, 2022](https://hubs.la/Q013SXmN0).

<!-- Interrupt Keep START -->

Expand Down
4 changes: 2 additions & 2 deletions _posts/2020-12-23-instruction-tracing-mtb-m33.md
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ infinite_loop () at ./main.c:157
157 __asm("bkpt 6");
```

We can dump the dissasembly of this loop to get a sense of what we expect to be recorded by the MTB:
We can dump the disassembly of this loop to get a sense of what we expect to be recorded by the MTB:

```
(gdb) disassemble infinite_loop
Expand Down Expand Up @@ -450,7 +450,7 @@ Begin Trace Session

Neat, what we are looking at here is a trace of the entire instruction flow up to the breakpoint.

If we want to view the exact instructions executed we can take the destination address from the previous packet and the source from the next packet and dissasemble the range with gdb. We see the `0x20000348` we identified above has been recorded in the trace.
If we want to view the exact instructions executed we can take the destination address from the previous packet and the source from the next packet and disassemble the range with gdb. We see the `0x20000348` we identified above has been recorded in the trace.

For example for the first `D` -> `S` transition we have above:

Expand Down
2 changes: 1 addition & 1 deletion _posts/2021-01-19-release-versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Example: 1.0.0 → 2.0.0

For most firmware projects, the MAJOR field might *never* be incremented. If I'm writing firmware for an nRF52, and it is the only MCU in my hardware product, it doesn't have to interact or communicate with many other pieces of software or hardware, so there shouldn't be any incompatible API changes!

There is one occassion where I would seriously consider incrementing the MAJOR field, and that is when our firmware becomes **incompatible with a version of itself**. Let me explain.
There is one occasion where I would seriously consider incrementing the MAJOR field, and that is when our firmware becomes **incompatible with a version of itself**. Let me explain.

Normal software packages can be updated at any time, with almost no repercussions. If incompatibility arises, just revert the change and continue. However, on firmware devices, the firmware updates itself. If there is an incompatibility, it might require a re-install, a factory reset, or in the worst of cases, the device might be bricked!

Expand Down
Loading
Loading