Bare-metal blinky on the SAMD20

I’ve been curious about the SAMD20 processors for a while now. They were originally produced by Atmel who have since been bought by Microchip. The SamD20 MCU’s are Cortex M0+ parts with the usual sorts of onboard peripherals. I was interested in programming this part from the ground up with my own header files, linker scripts and so on. Initially I had no success with OpenOCD (version 0.10 supplied with Ubuntu) so I went and downloaded a slightly more recent source code snapshot (0.10.0+dev-00382-gbe87994d). This mostly works. I can reset the chip, halt it, examine registers and program it using a slightly out of the way syntax. Single step debugging and breakpoints work too. The main problem is with the load command in arm-none-eabi-gdb: it just won’t program it. There is a workaround however as shown below. Note: I’m using an ST-Link-V2 clone to program the chip. The openocd configuration file is in the git archive for this project (see below).

samd20e16tqfp32pinout

In one terminal window type:
openocd -f samd20.cfg
In another type:
arm-none-eabi-gdb
Once inside gdb

target remote :3333
monitor reset halt
monitor at91samd chip-erase
monitor reset halt
monitor load_image /home/frank/Documents/samd/Baremetal/Blinky/main.elf 0
monitor reset

The debugger connects via SWCLK, SWDIO. VDDIN and VDDANA are connected to 3.3V and the various GND pins go back to 0V. The Reset pin is pulled up to 3.3V using a 10k resistor.
samd20e16_blinky_breadboard
Higher resolution image
The blinky code is as follows:

/* User LED is on PA0 */
#include 
#include "../samd20e16.h"
void delay(uint32_t dly)
{
    while(dly--);
}
int main()
{
    PADIRSET = BIT0; // make Port A bit 0 an output
    while(1)
    {
        PAOUTTGL = BIT0; // Toggle Port A bit 0
        delay(100000);   // Wait
    }   
}

The header file samd20e16.h was written using peripheral addresses obtained in the datasheet.
The github repository is available here. I hope to grow this to include the other peripherals over the next week or two.

Controlling SK9822 (“dotstar”) LED’s using the STM32F030

dotstar_stm32f030_circuit
The SK9822 LED (also known as the “dotstar” LED) is a smart RGB LED similar to the WS2812B. It has some advantages however: It is controlled using a standard SPI interface which means it does not rely on the sort of critical timing the WS2812 needed. It also allows you separately control the brightness and the colour mix of the internal LED’s. The LED’s can be strung together; the data and clock output from one feeding the next. The LED’s require use two pins of the host microcontroller: MOSI and SCK as shown in the figure above. Power should be supplied from a separate source to the microcontroller. The SK9822’s are 5V devices but seem to accept 3V logic signals on their control inputs.

The LED’s I got came in the 50/50 surface mount format which makes them a little difficult to use with a breadboard. A TSSOP-20 adapter came in very handy however and I was able to mount 3 on the same board as shown below.
dotstar_stm32f030

The LED’s are controlled using a data frame that begins with a sequence of the following form
0x00 0x00 0x00 0x00 ii bb gg rr 0xff 0xff 0xff 0xff
The leading 4 zeros are a start of data frame delimiter.
These are followed by a 1 byte intensity or brightness value which ranges from
0 to 31. The most significant 3 bits of the brightness field must be 1
Values in the range 0 to 255 follow for blue green and red
Finally an end of frame consisting of 4 bytes of 0xff is sent.
The test program below outputs signals that cycle 3 LED’s through a range of colours
The program was developed using an STM32F030F4P6 breakout board and ST-Link V2
SWD interface.
Code is available for download from here on github

Solar storm detected?

January21_2018
There is a moderate solar storm going on today and I noticed that there was a deflection of the electronic compass output around the same time. This is about the third time I’ve noticed something like this. Aurorawatch UK (https://aurorawatch.lancs.ac.uk/) showed this deflection around the same time:
samnet_January21_2018
Now, I know, the units are wrong and the signs are opposite but it is nevertheless a change at around the same time. Furthermore, the temperature of the sensor was stable at 16.7 degrees throughout the whole event so I think I can rule out a temperature effect. I need to investigate scaling and measurement direction to see if my results can relate directly to “official” ones.

The STM32L031 with an SSD1306 OLED display

oled1

AliExpress supply a really tiny OLED display driven by an SSD1306 controller.
https://www.aliexpress.com/item/1pcs-0-96-white-0-96-inch-OLED-module-New-128X64-OLED-LCD-LED-Display-Module/32639731302.html

The actual display area is 25mm wide by 14mm high and has 128×64 pixels. Pixels can be white, yellow or black. The display connects to the host microcontroller over an I2C bus which greatly simplifies wiring.
stm32l031_ssd1306_circuit

Pixels are mapped to graphics memory as follows:
SSD1306GRAM

Each graphics memory byte controls a column of 8 pixels. 128 bytes cover a strip of 128×8 pixels or “a page” as its called in the data sheet. This display has 8 pages giving a resolution of 128×64 pixels. To set a particular pixel, you need to identify which page it is on and which byte and bit connects to it within this page. In theory you could then drive this pixel on or off as desired however there is a problem: graphics memory is written in byte-sized chunks so if you want to set a particular pixel, you need to read the byte connected to it, modify the bit in question and then write it back. Unfortunately, the I2C interface for the SSD1306 does not permit reading of graphics memory.
The Adafruit driver for this display gets around this problem by maintaining a copy of the graphics memory in the host MCU. It then updates the whole display when things change. This consumes a fair amount of RAM in the host MCU (128×8 = 1024 bytes) and is slow as the whole display must be updated if a single pixel changes.
My first attempt at controlling this display takes a different approach. The display is treated as a text only device capable of displaying 25×8 characters. Screen updates are carried out at page level i.e. 128 byte chunks are written at a time which corresponds to a single line of text. An I2C driver buffers this data and outputs to the display on an interrupt driven basis. This greatly reduces RAM consumption and speeds updates.

Programming and debugging


Openocd version 0.10 or later is required for the STM32L031. You may get this ready built for your OS or download the source and compile yourself. In my case, I downloaded the source from openocd.org. This was extracted and compiled as follows (as the root user):

apt-get install libusb-1.0-0-dev
./configure –enable-stlink –enable-maintainer-mode
make
make install

The STM32L031 was connected to the host PC using an ST-Link V2 clone and the debug/programming session was started this:

/usr/local/bin/openocd
-f /usr/local/share/openocd/scripts/interface/stlink-v2.cfg
-f /usr/local/share/openocd/scripts/target/stm32l0.cfg

GDB was then used to upload and test the program.

Source code

Source code is evolving and can be found here:
https://github.com/fduignan/stm32l031_examples

Detecting solar storms

I previously used a GY-652 module as the basis for a weather station. The module contains a BMP180 pressure/air sensor and a HMC5983 electronic compass. The weather station ran for about 4 months on 3 AAA batteries which was reasonable enough although the GY-652 had an unexpectedly large quiescent current of around 1mA.
Anyway, the batteries needed recharging and I decided it would be interesting to see if the HMC5983 could be useful in such an environmental monitoring test.
The Earth’s magnetic field varies from around 250 mG to about 650 mG. During solar storms, this can vary by as much as 170 milli-Gauss (source: http://www.spaceweather.gc.ca/svr-en.php). Daily variations in the magnetic field are of the order of 0.4 milli-Gauss. Are these measurable by the HMC5983 I wonder? According to its datasheet, the noise floor for the device is 2 mG so that probably rules out the detection of daily field variation. Storms are another matter however and these should be measurable by the device.
Batteries were recharged and code modified to make use of the HMC5983. The base-station for the weather station is now connected to a Raspberry Pi which relays the data up to Thingspeak. I’m going to leave it for a month or as long as the batteries hold out and, who knows, maybe it will spot a solar storm.
Click here to view the data on Thingspeak.
Update 20 January 2018
After a month or so in operation I think I *may* have seen some correlation between solar activity and magnetic reading variations. There is also some correlation between the magnetic field readings and temperature. The system had been using 3 rechargeable AAA batteries which have been drained twice (need to work on my low power mode :).
To overcome some of these shortcomings I’ve opted to move the sensor out of the attic and placed it under the stairs (unheated area, not too near any big electrical or magnetic fields). I’ve also replaced the AAA batteries with AA ones. Now just have to wait for a big solar storm…