Oto Šťáva
Professional problem solver

Notes

This is a collection of random notes for myself that I thought could be useful for the general public as well. They are in no particular order and the list should grow over time if I can get myself to actually do this.

General

  • # When you need to pull up a color picker quickly, zenity --color-selection is a handy one you probably have already installed.

  • # In optimized binaries, GDB sometimes lies about the content of variables and/or function parameters that are higher in the stack than the actually currently executing function. The reason may be that the particular variable is only stored in a register, which is then overwritten by the logic further down the stack. Such optimizations may not always result in a <optimized out> placeholder, so be wary!

  • # To test a static website quickly, you can use Python’s built-in HTTP server to do it:

    python -m http.server
    

    This will serve the current directory on localhost, port 8000. Don’t use it for production, though, it’s not secure enough for that.

  • # Aggregation over indirection

    Whenever you are designing an API with callbacks, and the API has its own state struct that can be embedded in other structs, you can avoid a void *user_data pointer by just using the offset of the embedded struct, which saves memory:

    /** For @field_ptr pointing to memory that is a field named @field_name
     * from the parent struct of type @parent_type, gets a pointer to the parent
     * struct. */
    #define CONTAINER_OF(field_ptr, parent_type, field_name) \
    	((parent_type *)((char *)field_ptr - offsetof(parent_type, field_name)))
    
  • # Getting the shell script directory

    • Bash (source):
      script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
      
    • POSIX (source):
      script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
      
  • # Killing a hung SSH session

    • Enter ~ . – in this order
  • # Complete reference of standard HTML entities (a.k.a. named characters)

Microchip SAM D5x/E5x series

This is a family of 32-bit ARM microcontrollers by Microchip. You can find some basic info on them on Microchip’s official website if you’re interested. As I work with these at my day job, I am collecting some notes on specific behaviour related to them. Perhaps some other developers using these will find it useful.

Please note that this is not meant to be a comprehensive documentation. For that, you still need to see the official resources. This is only meant as an explainer of things that I personally got wrong at some point.

Also note that all of this is written from the perspective of bare-metal programming of the chip – we are writing our own library from scratch, not using Microchip’s HPL, which may be taking care of some or all of these things by itself.

DMAC

This is the Direct Memory Access Controller peripheral, facilitating DMA, i.e. autonomous operations on memory regions without the intervention of the CPU.

  • # The TCMPL (Transmission Complete) interrupt flag is set after the completion of each and every descriptor with BTCTRL.BLOCKACT set to INT. If you are transferring multiple regions of memory and only wish to interrupt after all of them are complete, only the last descriptor has to have BTCTRL.BLOCKACT set to INT; the others have to have it set to NOACT.
    • Presumably, BTCTRL.EVOSEL would work much the same way, but I have not had a use for that yet.

PORT

This peripheral controls the GPIO pins of the SAM.

  • # A pin may operate in an open-drain mode, but the way we set its value is different to the one we do it with a “classic” totem-pole (push-pull) output.

    Instead of continuous flipping of the OUT register to change the value, we set its OUT=0, PINCFGx.PULLEN=1, and PINCFGx.INEN=1 (the last one is so that we can read the actual pin value while we’re not driving it – useful e.g. for bit-banged I²C to read the ACK signals and clock stretching). Now, to set the pin’s value, we use the DIR register. Note, however, that to drive the pin low, DIR needs to be set; and to keep it floating, DIR needs to be cleared – i.e. the opposite way than may be intuitive.

    • Operation in open-source mode would be the same, just set OUT=1, then set DIR=1 to drive high and clear DIR=0 to keep floating.

SERCOM USART

This is the peripheral for serial communication via UART/USART.

  • # Interrupts while transmitting (TX) work as follows:
    • TL;DR:
      1. Write into DATA.
      2. Wait for DRE interrupt (but ignore TXC for now!).
      3. If you have more data to transmit, go to 1; if not, continue.
      4. Wait for TXC interrupt.
      5. Transmission is finished.
    • Explainer:
      • DRE (Data Register Empty) signals that we can write another character/word into the DATA register (which will then get written into the internal hardware buffer of the SERCOM peripheral). It does not mean the actual transmission on the actual wire has finished – if we turn TX off right after this interrupt, the transmission will not finish.
      • TXC (TX Complete) interrupt signals that everything that has been submitted into the internal buffer so far has been transmitted over the wire.
      • You will probably want to use the DMAC peripheral so as not to hog up the CPU just by transmitting a message and handling the relevant interrupts. This means that you will be handling writes to DATA and the DRE interrupt via the DMAC trigger (steps 1–3 in the TL;DR), but you still absolutely have to handle the TXC separately after the DMAC transmission is finished (steps 4 and 5 in the TL;DR), lest your messages will not be transmitted properly.

ICM

This is the SAM’s SHA hardware accelerator.

  • # To get actually portable SHA hashes, you always need to do padding, even if the message length is SHA block aligned. This is not really specific to SAM, it’s just how SHA works, but I learned it the hard way while dealing with the ICM, so I’m putting it here.

  • # The TRSIZE value in the descriptor is set to the number of SHA blocks minus one

    • The official documentation is not very clear about this.

IRL

  • # Sticker glue residue can be removed from jars and other containers by spreading some lard on it, letting it sit for a bit, then washing it away with a normal dish detergent. Turns out lard dissolves sticker glue pretty well.