Skip to content
Open
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
2 changes: 1 addition & 1 deletion mdbook/src/09-registers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This chapter is a technical deep-dive. You can safely [skip it] for now and come back to it later if
you like. That said, there's a lot of good stuff in here, so I'd recommend you dive in.

[skip it]: ../10-serial-communication/index.html
[skip it]: ../10-serial-port/index.html

-----

Expand Down
65 changes: 0 additions & 65 deletions mdbook/src/10-serial-communication/README.md

This file was deleted.

95 changes: 0 additions & 95 deletions mdbook/src/10-serial-communication/nix-tooling.md

This file was deleted.

40 changes: 40 additions & 0 deletions mdbook/src/10-serial-port/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Serial Port

<a href="https://en.wikipedia.org/wiki/File:Serial_port.jpg">
<p align="center">
<img height="240" title="Standard serial port connector DE-9" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Serial_port.jpg/800px-Serial_port.jpg" />
</p>
</a>

<p align="center">
<em>This is what we'll be using. I hope your computer has one!</em>
</p>

Nah, don't worry. This connector, the DE-9 (often referred to as DB-9), went out of fashion on PCs quite some time ago; it got replaced by the Universal Serial Bus (USB). We won't be dealing with the DE-9 connector itself but with the communication protocol that this cable is/was usually used for.

Copy link
Contributor

@iampi31415 iampi31415 Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a question rather, but I don't quite get the point of the chapter? What we as learners do here is:

  1. Connect through USB
  2. echo a string to the /dev/tty file
  3. use minicom to send data at a baud-rate.

For 1. it is unclear which protocol we would be using? Is echo to a tty file implying that the communication is using RS-232 ?

For number 2 I again guess it is RS-232, which is the one used by DE9 or a Serial Port (which is a Serial Communication Interface, hence a physical thing.) but through an emulated port (the tty file, I think, represents the UART hardware ?)

But the protocol isn't named anywhere, I think would be clearer if it is literally stated which protocol we would be using, and what the point of it is?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overall point of the chapter is twofold: provide some background and explanation of the complex world that is async serial, and make sure that you can talk to the nRF52833 serial port from your host computer.

I know of no standard name for the protocol itself. It is commonly referred to as just "async serial", which is how the chapter used to refer to it. minicom works exactly like echoing to a TTY device, except that it both reads and writes there as needed to present a terminal interface.

Again, I'll try another reword at some point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know of no standard name for the protocol itself. It is commonly referred to as just "async serial", which is how the chapter used to refer to it.

That makes sense now! That is why it was confusing to me, because without knowing it has no name, I assumed it was the name for a family of protocols with concrete names.

So sending bytes through a /dev/tty* device at a specified baud rate, is the asynchronous serial protocol, without any more specific name.

Suggestion: It seems to me that making this lack of a more concrete name explicit (does not have one to our knowledge) would make it easier.

So what's this [serial port]? It's a communication channel where two devices exchange data *serially*, as in one bit at a time, using two data lines (plus a common ground). Communication is asynchronous, in the sense that neither of the shared lines carries a clock signal. Instead, both parties must agree on approximately how fast data will be sent along the wire *before* the communication occurs. A peripheral called a Universal Asynchronous Receiver/Transmitter (UART) sends bits at the specified rate on its output wire, and watches for the start of bits on its input wire. This protocol channel thus allows *duplex* communication: data can be sent from A to B on one wire, while data is also being sent from B to A on the other wire.

(Old school-serial ports also include a number of other wires for "out-of-band signalling", to tell the hardware when the connection is active, when the other end is ready to receive, etc. These wires are rarely used today, and are often not implemented in serial port hardware.)

We'll be using a serial port to exchange data between the microcontroller and your computer. Now you might be asking yourself why exactly we aren't using RTT for this like we did before. RTT is a protocol that is meant to be used solely for debugging. You will most definitely not be able to find a device that actually uses RTT to communicate with some other device in production. However, serial communication is used quite often. For example some GPS receivers send the positioning information they receive via serial communication. In addition RTT, like many debugging protocols, is slow even compared to serial transfer rates.
Copy link
Contributor

@iampi31415 iampi31415 Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to be annoying but we are not using a serial port (that is a physical thingy); as Wikipedia says, that would be using a the physical interface.

Why not to say that we will use a USB port / interface, but communicate using RS-232, which seems to be what the minicom config file does?
Maybe that's not fully correct but seems more understandable to me.
Maybe the USB opens a way to have the emulated serial device under /dev/tty/, so we communicate as if there was a Serial Port?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not using RS-232, which is an electrical standard that specifies -12V for a "high" state and +12V for a low state, among other things. The "serial port" we are using is on the nRF52833 itself; the USB interface is a convenience / detail.

I will try to further clarify the wording, I guess.


The next practical question you probably want to ask is: How fast can we send data through this protocol?

The serial-port communications protocol works with frames, each carrying a byte of data. Each frame has one *start* bit, 5 to 9 bits of payload (data: modern applications very rarely send a 9-bit byte, and 7 or fewer bits in a frame will be left-padded to an 8-bit byte with zeros) and 1 to 2 *stop bits*.

The speed of the protocol is known as *baud rate* and it's quoted in bits per second (bps). (If you're thinking that this sounds wrong — it is. "Baud" is supposed to be *symbols* per second; a symbol should correspond to a frame; even if a data bit is regarded as the "symbol" they aren't sent at this rate because of the rest of the protocol. It's a convention, and doesn't have to make sense.) Historically common baud rates are: 9600, 19200, 38400, 57600 and 115200, but it is not uncommon in our modern world to send data at 921,600 baud.

To actually answer the question: With a common configuration of 1 start bit, 8 bits of data, 1 stop bit and a bit rate of 921.6K bps we can send and receive 92.16K bytes per second — fast enough to transmit single-channel uncompressed CD audio. At the bit rate of 115,200 bps that we'll be using, we can send and receive 11.52K bytes per second. This is fine for most purposes.

Today's computers don't usually have a serial port, and even if they do the voltage they use (+5V on a modern serial port, ±12V on an ancient RS-232 port) is outside the range that the MB2 hardware will accept and may result in damaging it. *You can't directly connect your computer to the microcontroller.* You *can* buy very inexpensive (typically under US$5) USB←→serial converters that will support the +3.3V inputs of most modern microcontroller boards. We will be talking to the MB2 serial port through its built-in USB port. However, if you want to connect directly to a hardware serial port, on the MB2 or some other board, a serial converter is the way to go.

A separate USB channel on the MB2's USB port can be used to talk to the MB2's built-in USB←→serial converter. This means that the converter sits between the MB2 USB port and the microcontroller serial port, exposing a serial interface to the microcontroller and a virtual USB serial interface to your computer. The computer presents a virtual serial interface via the USB CDC-ACM ("Communications Device Class - Abstract Control Model", ugh) device class. The MB2 microcontroller will see your computer as a device connected to its hardware serial port; your computer will see the MB2 serial port as a virtual serial device.

Now, let's get familiar with the USB serial port interface that your OS offers. Pick a route:

- [Linux/UNIX](nix-tooling.md)
- [Windows](windows-tooling.md)

For MacOS check out the Linux documentation, although your experience may differ somewhat.

[serial port]: https://en.wikipedia.org/wiki/Serial_port
69 changes: 69 additions & 0 deletions mdbook/src/10-serial-port/nix-tooling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Linux USB←→serial tooling

The MB2's USB emulated serial device shows up in Linux when you connect the MB2 to a Linux USB
port.

## Connecting the MB2 board

If you connect the MB2 board to your computer you should see a new TTY device appear in
`/dev`.

``` console
$ sudo dmesg -T | tail | grep -i tty
[63712.446286] cdc_acm 1-1.7:1.1: ttyACM0: USB ACM device
```

This is the USB←→serial device. On Linux, it's named `tty` (for "TeleTYpe", believe it or not). It
should show up as `ttyACM0`, or maybe `ttyUSB0`. If other "ACM" devices are plugged in, the number
will be higher. (On Mac OS `ls /dev/cu.usbmodem*` will show the serial device.)

But what exactly is `ttyACM0`? It's a file of course! Everything is a file in Unix:

```
$ ls -l /dev/ttyACM0
crw-rw----+ 1 root plugdev 166, 0 Jan 21 11:56 /dev/ttyACM0
```

Note that you will need to be either running as `root` (not advised) or a member of the group that
appears in the `ls` output (usually `plugdev` or `dialout`) to read and write this device. You can
then send out data by simply writing to this file:

``` console
$ echo 'Hello, world!' > /dev/ttyACM0
```

You should see the orange LED on the MB2, right next to the USB port, blink for a moment,
whenever you enter this command.

## minicom

We'll use the program `minicom` to interact with the serial device using the keyboard. We will use
the default settings of modern `minicom`: 115200 bps, 8 data bits, one stop bit, no parity bits, no
flow control. (115200 bps happens to be a rate that will work with the MB2.)

``` console
$ minicom -D /dev/ttyACM0
```

This tells `minicom` to open the serial device at `/dev/ttyACM0`. A text-based user interface
(TUI) will pop out.

<p align="center">
<img title="minicom" src="../assets/minicom.png" />
</p>

You can now send data using the keyboard! Go ahead and type something. Note that
the text UI will *not* echo back what you type. If you pay attention to the yellow LED
on top of the MB2 though, you will notice that it blinks whenever you type something.

## `minicom` commands

`minicom` exposes commands via keyboard shortcuts. On Linux, the shortcuts start with `Ctrl+A`. (On
Mac, the shortcuts start with the `Meta` key.) Some useful commands below:

- `Ctrl+A` + `Z`. Minicom Command Summary
- `Ctrl+A` + `C`. Clear the screen
- `Ctrl+A` + `X`. Exit and reset
- `Ctrl+A` + `Q`. Quit with no reset

> **NOTE** Mac users: In the above commands, replace `Ctrl+A` with `Meta`.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Windows tooling

Start by unplugging your micro:bit.
Start by unplugging your MB2.

Before plugging the micro:bit back in, run the following command on the terminal:
Before plugging the MB2 back in, run the following command on the terminal:

``` console
$ mode
Expand All @@ -12,9 +12,9 @@ It will print a list of devices that are connected to your computer. The ones th
in their names are serial devices. This is the kind of device we'll be working with. Take note of
all the `COM` ports' `mode` outputs *before* plugging the serial module.

Now, plug in the micro:bit and run the `mode` command again. If you see a new
Now, plug in the MB2 and run the `mode` command again. If you see a new
`COM` port appear on the list, then that's the COM port assigned to the
serial functionality on the micro:bit.
serial functionality on the MB2.

Now launch `putty`. A GUI will pop out.

Expand All @@ -41,6 +41,6 @@ Finally, click the Open button. A console will show up now:
<img title="PuTTY console" src="../assets/putty-console.png" width="500" />
</p>

If you type on this console, the yellow LED on top of the micro:bit will blink. Each keystroke
If you type on this console, the yellow LED on top of the MB2 will blink. Each keystroke
should make the LED blink once. Note that the console won't echo back what you type so the screen
will remain blank.
8 changes: 4 additions & 4 deletions mdbook/src/11-uart/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# UART

Our microcontroller (like most) has a peripheral called a UART (for "Universal Asynchronous
Receiver/Transmitter). This peripheral can be configured to work with several serial communication
protocols. The peripheral we will be working with is named UARTE (for "UART with Easy DMA", a topic
outside the scope of this chapter).
Our microcontroller (like most) has UART ("Universal Asynchronous Receiver/Transmitter)
peripherals. There are two kinds of UART peripheral on the MB2: the older `UART` and the newer
`UARTE` ("UART with Easy DMA"). We will use a `UARTE` peripheral to talk to our hardware serial
port.

Throughout this chapter, we'll use serial communication to exchange information between the
microcontroller and your computer.
23 changes: 12 additions & 11 deletions mdbook/src/11-uart/send-a-single-byte.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,26 @@ uarte::Uarte::new(
This function takes ownership of the UARTE peripheral representation in Rust (`board.UARTE0`) and
the TX/RX pins on the board (`board.uart.into()`) so nobody else can mess with either the UARTE
peripheral or our pins while we are using them. After that we pass two configuration options to the
constructor: the baud rate (that one should be familiar) as well as an option called "parity". Parity
is a way to allow serial communication lines to check whether the data they received was corrupted
during transmission. We don't want to use that here so we simply exclude it. Then we wrap it up in
the `UartePort` type so we can use it.
constructor: the baud rate (that one should be familiar) as well as an option called
"parity". Parity is a way to allow serial communication lines to check whether the data they
received was corrupted during transmission. We don't want to use that here so we simply exclude it.
Then we wrap it up in the `UartePort` type so we can use it.

After the initialization, we send our `X` via the newly created uart instance. These serial
functions are "blocking": they wait for the data to be sent before returning. This is not always
what is wanted: the microcontroller can do a lot of work while waiting for the byte to go out on the
wire. However, in our case it is convenient and we didn't have other work to do anyway.
After the initialization, we send our `X` (as ASCII byte value 88) via the newly created uart
instance. These serial functions are "blocking": they wait for the data to be sent before
returning. This is not always what is wanted: the microcontroller can do a lot of work while
waiting for the byte to go out on the wire. However, in our case it is convenient and we didn't
have other work to do anyway.

Last but not least, we `flush()` the serial port. This is because the UARTE may decide to buffer
output until it has received a certain number of bytes to send. Calling `flush()` forces it to
write the bytes it currently has right now instead of waiting for more.

## Testing it

Before flashing this you should make sure to start your minicom/PuTTY as the data we receive via our
serial communication is not backed up or anything: we have to view it live. Once your serial monitor
is up you can flash the program just like in chapter 5:
Before flashing this you should make sure to start your minicom/PuTTY as the data we receive via
our serial communication is not backed up or anything: we have to view it live. Once your serial
monitor is up you can flash the program just like in chapter 5:

```
$ cargo embed --example send-byte
Expand Down
Loading