4. Embedded Programming
This week's assignment tasks are listed below:
- group assignment:
- demonstrate and compare the toolchains and development workflows for available embedded architectures
- individual assignment:
- browse through the data sheet for your microcontroller
- write a program for a microcontroller;
- and simulate its operation
- to interact (with local input &/or output devices)
- and communicate (with remote wired or wireless connections)
- extra credit: test it on a development board
- extra credit: try different languages &/or development environments
Work Plan

Group Assignment
4.1. Comparing Toolchains and Development Workflows of Different Computer Architectures.
We learnt about different toolchains of different microcontrollers from different computer architectures. Along with that we compared our results to Rasberry Pi also, which is a full fledged computer rather than a microcontroller.

For more information, read our group assignment.
Individual Assignment
4.2. Browse through the Data Sheet for your Microcontroller
The official datasheet for the RP2040 has been linked here.

Name of the Chip: RP2040

The chip is called RP2040. It is called so because
- RP: Made by Rasberry Pi Foundation
- 2: Has two processor cores Cortex M0+ processor cores. A core is an independent processor that is built into a CPU. Multiple cores mean that they can operate tasks independant of each other to avoid the heat vs performance issue.
- 0: The cores are Cortex-M0+, which is based on the ARM CPU architecture, which is a family of RISC architectures.
-
4: The expression
floor(log2(RAM / 16KB)) = 4
because the chip has 264KB of RAM, and the floor function takes in a real numberX
and outputs the nearest integer less than or equal toX
. - 0: The number represents on-chip flash memory, which is memory that is stored in the chip even when the chip is powered off. Since the chip has no flash memory, it is represented with the number 0.

Speed: 133MHz
The dual cores can run upto 133 MHz. It has two phase-locked loops (PLLs) that provide a fixed 48MHz clock for USB or for Analog Digital Converter (ADC) , and a flexible system clock up to 133MHz for high power applications.
Memory: 264 kB SRAM & no onboard flash memory
The RP2040 has 264 kB of embedded Static Random Access Memory (SRAM; a type of volatile memory) for temporary memory storage and 0B for flash memory (permanent storage; a type of non-volatile memory)
Pins: 36 GPIO Pins, out of which 30 are digital I/O Pins, which also include 4 Pins that can accept both digital and analogue input.
Among the GPIO pins, GPIO 0-25 accept accept digital inputs, whereas GPIO 26-29 can accept both analogue and digital signal input and output digital signals.

Communication protocols supported: UART, I2C, and SPI

Analog to Digital Converter: The RP2040 has an internal ADC.
It has 5 inputs. 4 inputs are available on the pins shared with GPIO (GPIO 26-29), while one input is connected to an internal temperature sensor

Operating and Logic Voltage: 1.8 to 3.3 V (preferrably 3.3 V)
Along with the previous datasheet, I refered another datasheet from Rasberry Pi called 'Hardware design with RP2040', which states that the RP240 requires 3.3V


Based on this Reddit post a logic voltage of x
means that the microcontroller will read a value equal to or close to x
as 1
or digital HIGH
and any value close to zero Volts as 0
or digital LOW
. Hence the logic voltage of the RP2040 is also 3.3V
Maximum Tolerable Current and Voltage: 3.83V and 100 mA


4.3. Writing a Program for your Microcontroller
Controlling an LED using a Button using a Rasberry Pi Pico
- Language: Micropython
- Microcontroller: RP2040
- Board: Rasberry Pi Pico
- Environment: Wokwi (simulation)
Once I learnt the basic syntax with the help of examples from our instructors, I wrote a simple piece of code written in Mycropython using a Rasberry Pico development board (includes RP2040 chip) to control the LED using a button, using an example Blink program
First we import the required modules. Because we only need to import specific objects, ie. 'Pin' class from 'machine' & 'sleep' function from 'time' we only import using the commmand: from x import y

Then we name a variable led
where we state that Pin 0 wil be an OUTPUT Pin, meaning an voltage will be sent to it, which will be used to light up the LED.
We also name a second variable named button
which is connected to pin 2 on the Rasberry Pi Pico. We set it as an INPUT pin, meaning it will take voltage readings from the push button. Additionally, using the PIN.PULL_UP
method, we set pin to a default 'HIGH' state until the button is pressed.

To make neat connections I used a breadboard, added the components to make an electrical circuit. The following image shows how they are connected internally

I have previously tinkered with simple circuits in the past so I knew how to connect simple devices like LEDs and switch buttons. Since an LED is a diode, it cannot be connected in any manner. The Anode (A) is the bent end that should be connected to the digital I/O pins and the Cathode (C) should be connected to the ground (GND) pin. Also, a 1K resistor should be connected in series with the LED to stop it from drawing too much current.
Once I have placed all the components, I then connect all the devices using wires. You can see which are the GND pins by hovering on top of the board.


I added a While True:
statement to add a loop that goes on infinitely
Make sure to check the file type! When testing the Micropython script will not work in a sketch.ino file. It should be a main.py file

To test the button values, I added a Serial output using the command print(button.value())
. But when running, nothing showed up on the console. I tried commenting different parts of the code to see if an LED lights up using the command led.value(1)
but it did not work

In situations like this, I take a break and come back to the problem with a fresh mind.

And it worked! I realized my error was that I did not connect my resistor to the circuit.Once I changed this, the code started working and the LED starting lighting up

But when I uncommented all the code lines, the code again did not work.
I decided to use the commenting approach again to understand where the problem was, and found out it was a problem with the statement about declaring the variable button

I knew it was a problem with the PIN.PULL_UP
command since it was the code was running without it, even though you would then run into issues with sreading the correct button state due to the problem with floating values

I then realized that I used the wrong syntax PIN
instead of Pin
while writing the command Pin.PULL_UP
.

Once I corrected it, the code is now running
Inside the While True
loop I added an if statement stating that if the button value is 0 (the 'ON' state) using the if button.value()==0
. The ==
operator means to see if 'check if x = y'. If it satisfies that condition, it then goes inside the if
code block and switches on the LED using the command led.value()=1
.We then add a delay of 1 second using the sleep(1)
command. We then repeat the same process for when the button is OFF
But the code did not work again

With the help of my instructor, the error was resolved when the indentation was corrected

I now added a Serial Output using the print
command to state when the LED is on and when it is OFF and commented the print(button.value())
As long as the button is pressed, the LED will remain ON and a message confirming the same will be displayed in the terminal. When the button is not pressed,
the LED remains OFF which is also confirmed by another message in the terminal.
The following is the code I wrote:
from machine import Pin
from utime import sleep
led = Pin(0, Pin.OUT)
button = Pin(2,Pin.IN,Pin.PULL_UP)
while True:
# print(button.value())
if button.value()==0: #Button not pressed
led.value(1) #led remains 'ON'
print ("LED is ON")
sleep(1)
# Repeat for when button is pressed
if button.value()==1: #Button not pressed
led.value(0) #led remains 'OFF'
print ("LED is OFF")
sleep(1) #Add delay for 1
LED Blink using a PIO in the Rasberry Pi Pico
- Language: Micropython
- Microcontroller: RP2040
- Board: Rasberry Pi Pico
- Environment: Wokwi (simulation)
A PIO (Programmable Input/Output) is a programmable piece of hardware that can be customized to perform high speed but non-complex programming tasks in the background independant of the cores, which means the main processor core is free to take on more tasks that take more computing power.
They are especially useful for communicating with serial devices with no hardware support, for pulse width modulation, etc. To know more check this web article that provides an overview of what a PIO is and its potential usefullness.
The RP2040 has two identical PIOs, each containing 4 state machines that share memory, ie. you can send 32 'words' or instructions to it a time.


- Output Shift Register (OSR): Holds data before sending the data via FIFO or pins.
- Inputs shift register:Stores incoming data before sending it FIFO
- X & Y register: General-purpose registers. A single general purpose register (X only) may be limiting, in which case we usa an additional Y register.
State Machine: An automatic system that follows certain rules to transition between different states. They can work independantly without needing constant instructions from the main processor, so they use very little processing power. Also they run very fast, which is very useful in communicating to different hardware device. Each state corresponds to a specific instruction that is being executed.
Each state machine has four types of registers
FIFO: It stands for First In, First Out. It is a type of buffer(ie. temporary memory storage) that is capable of transfering data between the CPU and a state machine. Each state machine has a TX (Transmitter) FIFO (to sen) and an RX (receiver) FIFO to (to receive dazta)
IO Mapping: This refers to how the physical pins are assigned to the state machines Each state machines can control 32 of the RP2040 GPIO pins, but not all of them they are physically mapped to the Pico.
Instruction Memory: Since the PIO runs independantly from the CPU, it requires its own memory to store the program.The instruction memory refers to the memory that all 4 of the state machines can access. It can store 32 instructions, where each instruction is 16 bytes(2 bits)
Programming: Each instruction is written in one clock cycle, ie., 32 instructions can be sent in 32 clock cycle. This frequency can be adjusted to adjust the clock cycle, like I have done in my program.
I used the Digikey tutorial to program using the PIO, along with referring to the RP2040 Datasheet and Raspberry Pi Pico-series Python SDK documentation for reference.



I also used ChatGPT to simplify the meanings of many of the technical terms that were being used in the tutorial and documentation. List of all prompts used have been added (check References)


This is the github documentation that describes how each insruction is programmed.
In Wokwi simulation
This is the code for the same
import rp2
from machine import Pin
import utime
@rp2.asm_pio(set_init=(rp2.PIO.OUT_LOW))
def blink ():
wrap_target()
set(pins,1) [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
#160 cycles
set (pins,10) [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
wrap()
sm = rp2.StateMachine(0,blink,freq=2000,set_base=machine.Pin(25))
while True:
print("State machine starting...")
sm.active(1)
utime.sleep(1)
print("State machine stopping...")
sm.active(0)
utime.sleep(1)
Testing it on on a development board
I tested my code in a development board called Seeed Xiao RP2040
Try different languages &/or development environments
I used ATtiny 1614 and Arduino IDE and UPDI tool chain to make an LED blink.
This is the code I used for the same:
#define LED 10
void setup(){
pinMode(LED,OUTPUT);
}
void loop(){
digitalWrite(LED,HIGH);
delay(1000);
digitalWrite(LED,LOW);
delay(1000);
}
More information can be found in the group assignment.
Using the STM32 microcontroller
This time I wanted to do something more relevant to my final project. Since I was already familiar programming in C++ with the Arduino IDE and based on a suggestion by my instructor Sibin, I chose to simulate a program in the NUCLEO-C031C6
Based on the databrief of the STM32 Nucleo-64 development board & the datasheet of the STM32C031C6 microcontroller.
- Language: Embedded C++
- Board: NUCLEO-C031C6
- Microcontroller: STM32C031C6T6
- Core: ARM Cortex M0+
- Speed: 48 MHz
- Flash:32 KB
- SRAM: 12 KB
- Operating voltage: 2-3.6V
- Pins: 48 pins
- Communication interfaces: I2C (PB6/PB7), USART (PA9/PA10), SPI
- Development support: SWD (SWCLK-PA13(Pin 35), SWDIO-PA14(Pin 36), Power-VSS/VDD(Pin 6/7), GND-VREF(Pin 5))
- ADC: 12 bit internal ADC
- Development toolchains: Arduino IDE with SWD programming tool (ST-LINK/V2)
When I was facing some difficulty finding all required information, my instructor told me to use STM32CUbeMX software, which is a graphical tool normally used to configure STM32 microntrollers and microprocessors.

I used it here to find other information that I was not able to get easily from the datasheet, for eg: the pins for SWD debugging.
Conclusion
This week I learnt the following:
- learnt about computer architectures and their differences
- learnt about different toolchains for different microchips and programming languages
- learnt to program in Micropython and Arduino C++ in an RP2040 microchip & an ATTiny1614
References
- Week 4 Group Assignment: Comparing Toolchains and Development Workflows of Different Computer Architectures.
- Offical datasheet for RP2040 by Rasberry Pi
- Abouts CPU Cores
- About the ARM Cortex-M0+ processor
- Wikipedia article on the ARM architecture family
- Wikipedia article explaining the
floor
function - Wikipedia article explaining flash memory.
- "Raspberry Pi Pico Getting Started Tutorial with MicroPython" Tutorial by Yusro explaining the significance of each of the digits in the name of the chip RP2040
- Phased-locked loop by Wikipedia
- What is Analog to Digital Converter & Its Working by elprocus.com
- An article on Static Random Access Memory by Unacademy
- The Ultimate Guide to QFN Package by anysilicon.com
- Hardware design with RP2040
- What is the logic level voltage of the Arduino microcontroller? by a Reddit user
- 'Getting Started with Seeed Studio XIAO RP2040' by Seeed Studio
- 'What is PIO?' by Rasberry Pi
- RP2040 Datasheet
- Raspberry Pi Pico-series Python SDK
- Github documentation for the rp2 module, used to program the PIO in RP2040
- AI: ChatGPT prompts
What is a PIO in RP2040
What are state machines
Explain what @rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) means
Explain wrap_target
Explain the concept in a manner that a person with no understanding of programming can understand
What do you mean by 32 instructions in state machines
Are 32 instructions 32 bits?
What is a bit
What is a byte