[Music]
hey everyone and welcome to class number
two of
raspberry pi pico rp 2040 the deep dive
um
and uh before we dive in just uh a
couple of notes
so first of all uh there is this
document with
all the links and resources uh from last
time i'm sharing the link
uh yeah hackaday share the link thanks
cristina in the chat
so you can follow it and uh based on the
feedback from last class i
uh this time i included the agenda so
you can find the agenda in the document
and see what we'll talk
be talking about also whenever we have
a reference to the data sheet uh there
is like uh
the section number so uh this can be
very
useful for some of you based on your
feedback and
uh other than that let's see so
um there is like a 10 situation going
right now in israel and there is a low
chance but there is still some chance
that there will be
a alarm during the class uh in which
case i will
have to go to a shelter so uh just
so if that happens you won't be
surprised again there is a pretty long
chance that it will happen but
it may happen um
cool and uh before we uh i share my
screen and we start with uh
thanks david before we uh dive in
and uh get i share my screen uh just uh
if any of you is taking notes and wants
to share them with the rest of the
people just let me know and i can add a
link to this
pi pico class resources i think it can
be really useful
if you take notes and want to share them
with other people
all right so um sharing my screen how do
i do this zoom help me
ah there is screen share yeah all right
and this is my screen share and now you
should be seeing my screen let me make
sure that i can still see the chat so
i can see all the smart things that
you're writing there
and um yeah uh so
can you see my screen yes no
while i'm waiting for your answers uh
let me just
um update you about a few changes
in the uh uh emulator that we are using
so first of all we had this program
uh last time uh it didn't really
we had some glitches with the emulator i
fixed them all i promised
uh now it should be fine so we had a
program we built last time that should
alternate uh the
leds and now it does and uh
in case you missed it we have the
dislike i added some comments and
everything but
uh you have this in the document uh code
samples from the class for
last from last class so if you want to
check it out
now in case uh i ran a poll and
some of the you have rp 2040 a physical
one
in case you want to run those examples
on your physical raspberry pi
uh pico uh you can just f1 and then
download uf2 binary it's a new feature i
added based on your feedback
so now you can just click on it and it
will download uh
it will take a second or two and it will
download the file you can just
drag into your raspberry pi pico
and run this same the same code uh
from the emulator on the physical pico
so it's super useful if you want uh
to copy code from here or to run the
program from here here
on the uh pi pico and the uh opposite is
also possible you can
f1 load uh hex file and start simulation
and load uh any hex file for instance if
you
use the raspberry pi examples repo and
compiled one of the examples you can run
it here just
by loading the x file and starting the
simulation so
just a few notes about these new
features that
are pretty useful if you want to
test the code on your physical pi or
import code from somewhere else that
like the pipeco sdk so
yeah let me see what else so last time
uh
we had this thing with uh gpio registers
we
we have seen how uh we can use let's
close this we don't need it anymore
we have seen how we can use uh the gpio
registers to
uh you know um control the
uh like the hardware registers to
control the gpio directly so we have
this
arduino program here it links an led
and then instead of like using digital
write
instead of using the arduino api we can
go low level and write to the registers
directly
let's just do it as a real quick uh
recap so we had this
section about the sao
and inside the sa oh actually i think
uh there is a shortcut from the gpio yes
so uh yeah there is this uh gpio out
register and we can write uh there is
like gpio outset
uh or clear let's use the gpio out clear
to uh just turn off gpio so we can do
define gpao out clear and then
it's a pointer to a 32-bit integer
and uh it's sao plus this
offset so this is the offset of the
register plus the
uh sao address space which is this okay
and then um we want to de-reference it
so
uh we can use it as just assign a value
to it
and then instead of you know using
digital right led
low we can do uh right set this a
specific bit in this register
so we can use the bitmacro of arduino so
uh set bit 1 and that should uh
link keep blink blinking led1
but this time turning it off is done by
writing to the hardware register
and behind the scenes it's what
digitalwrite is doing so there is
usually there is no problem
if you want to mix and match um
but this code is portable uh
i mean digital write is portable this
code is not portable to other platforms
so it ties you to the
pipe code so uh cool we have seen uh
this last time how to do this
uh thing with um gpio
um and now i want to show you another
peripheral
this time it's the timer so
um we are going to use the timer
registers
um so i think we briefly
uh last time we briefly uh looked at
uart
um so let's take a look at the timer so
uh the system timer peripheral uh it has
a micro
second time base for the system and
there is a single 64 counter
incrementing once per microsecond so it
counts microseconds
one million per second and you can read
and write from it
uh and there are four lamps which we
will see in a moment
so um the first thing we are going to do
we are just going to take a look i mean
we could
keep reading on the counter
[Music]
how it's split into two registers
because it's 64 bits
uh but basically uh these are the
registers uh
time lr to read the high part and the
low part of the time
and let's go to this register and try uh
re-implementing delay now so first we
re-implemented digital right now we are
going to replace delay with our
own uh implementation so uh we are going
to take this
timer lr let's define this register
time lr
time lr is uh at this offset
and um it's basically an
offset from this timer base so this is
the timer base
i just copy pasted it from here the base
address of the timer peripheral
and instead of like repeating this uh
thing
for every register that we want to
define we can just define a macro for
that so let's call it
mem32 and it will accept
an address and just you know
provide uh an easy access to
uh the contents of the the memory
contents of this address
i'm also going to add a volatile keyword
i'm not sure if it's
required but if we don't put it and we
read from a register and then
immediately we write to a register and
then immediately read from it the
compiler may optimize that
out so volatile make sure that won't
happen that
every time that we are writing to a
mem32
register then the compiler will actually
write it won't
optimize that and then we can just say
instead of this
this is man32 let's just quickly
and this is also mem32 let's just
quickly check that this is
still working and the led still blinks
yeah still working with this new macro
cool um so now let's use this timer lr
to define our
own variant of delay so uh let's call it
timer delay and um what we are going to
do
actually uh yeah okay so
uh actually what we are going to do we
are going to uh
take the number of uh micros we are
going how many microseconds we are going
to delay
uh micros microseconds
yeah just uh not to clash with the
arduino functions
seconds thanks and then
uh we are going to have uh target time
which
is just uh time lr plus microseconds
and then uh we can do a while uh
time lr is less than target
basically do nothing that's a busy
weight so we are just
waiting for the time to pass and now we
can replace those delays with
time delay we need to add three zeros
because now it's
microseconds and not milliseconds and if
everything works well the led should
still blink
uh led number one roughly once or
actually once a second so now um
we re-implemented delay using this timer
peripheral in just uh two lines of code
but actually the timer has a mechanism
that can help us
instead of uh sort of uh counting or
waiting for the time to pass uh and
implementing this mechanism ourselves
it has this thing called alarms um
so um i'm going to we are going to learn
how to use them and then i'm going to
show you why they are super useful
so in order to use the alarms there is
like this
section about the alarms and you can see
that it has four alarms and it
output a separate interrupt for each
alarm we'll take a look at that in a few
minutes
and the alarms match on the lower 32
bits of the 64-bit counter
so uh it's basically the the
microcontroller basically compares the
alarm value with the value of this
register which is exactly what we are
doing here but it's done in hardware
and it can count up to 72 minutes ahead
which is more than enough for our
purposes
so um in order to enable an alarm
uh we just need to uh write the time uh
for the alarm in this specific
alarm register so uh there are like four
alarm registers
for each each each of the alarms
and as soon as um we write to them it
arms the alarm so let's try that um
we are going to use uh alarm number one
for instance so
we know that alarm number one is at
offset 14. let's define the register
so alarm1 actually we can
have another helper macro timer edge
offset that will just do mem 32
and this plus offset so we don't have to
repeat the timer base for every single
timer so we can do
this and then this and then just remove
this
right um and then um
what uh so as soon as we write
the target time into this alarm one
uh like this the uh
the alarm will be armed that's uh what a
microsecond
the microsoft er the datasheet says
and the alarm will disarm itself once it
fires
and can be disarmed early using the
armed status register so
if we take a look at this register the
armed register
it indicates whether the alarm is
currently
armed or or for each alarm it indicates
whether it's
armed or not a right to the
corresponding
uh alarm x register which we did uh
we just did arms it and uh we can
uh writing one to this register will
disable the alarm it says
wc which means right clear whenever we
write a value it will clear that bit
so as soon as we do this
we can assume or the datasheet tells us
that this
armed register that the corresponding
bit which is
a bit number one for alarm number one
uh will be set to one and uh
it will disarm the alarm as soon as
the time passes so we can basically
change this
condition to let's keep it going let's
keep waiting
until uh this bit uh is cleared
like the the bit uh bitrate sorry bit
read
reads the bit number one of this
register while uh
this bit bit number one uh sorry while
it's set we want to wait
while it's set and as soon as it clears
the while will stop and a timer delay
will end
so let's run this and
light compiles and you can see it blinks
uh just as usual and just so
it's more interesting let's change the
delay to 250 so
it works a bit faster and you can see
i'm not i'm actually doing something
it's not the same
i mean we get the same result that's the
third approach already
um so that's uh
how we use the alarms we just set the
target time and then wait until this
uh beat is uh goes to zero
and the reason i used uh alarm number
one and not zero
is that um the arduino core
for the raspberry pi the one that we are
using to run our code
is actually using uh alarm number
zero and we can see this uh one way to
see this would be to print the value of
armed when the uh let's print it in
binary
when the program begins you can see that
uh the value of this
uh oh serial one i said i would
make this mistake and now i did so yeah
so you can see that uh it's one
so basically uh the operating system or
the
arduino core already uses uh
that's bit zero so it already uses um
alarm number zero and if we do this
print here we'll see that
both alarms are armed both
zero and one so that's how we use the
alarm
and it's pretty nice we implemented our
own delay in just
two lines of code let me just copy this
to the document so
you can have this later if you want this
piece of code
and uh what i want
to do next is actually uh show you
how we can do it sort of asynchronously
so instead of like
blocking the main loop while we are
waiting for this timer
we can also use interrupts and
interrupts are a way to
for the hardware to tell us that some
task has been completed or
some condition has happened like a gpio
has changed
so basically it's a way for the hardware
to notify
us about external or internal events
so um let's start learning about
interrupts
the first thing we are going to do so
the information is a bit scattered and
we are going to go over a few different
documents so try to bear with me and if
you have any questions just
asking in the chat the first thing we
are going to look at
uh is inside the system description
there is this interrupt section 232
and again that's uh in the agenda you
can find it here
so there is this interrupt section and
it has this
list of interrupts it says that
each core has like 32 interrupt inputs
even though only the lower 26 are
actually used by the hardware and then
we can see
for each interruption number
uh the hardware that is connected to
that interrupt
so uh we can see that the first four
interrupts are used by the timer
uh specifically for the four alarms that
we have
and that's what we are going to use uh
in a moment and then we can see there
like there is an interrupt for the pwm
for the usb
uh for the pio dma for the uart so
basically for uh all the peripherals
more or less
and uh it says that uh
the the implementation of uh the
interrupts
is done by uh the envy arm nested
vectored interrupt controller
and this is a piece of hardware that uh
manages uh the interrupts
and um if we check out
a section i think that's two four
three yeah there is like uh
two four five actually uh there is uh
if you there are a few words about the
nvik really few words
um it says that uh they are connected uh
external interrupt
signals connect to the anvik and the
avik prioritizes them
and software can define the priority
blah blah blah blah blah blah blah and
we can see that there are like a few
registers like there is this
interrupt set enable register which we
can use to tell the hardware which
interrupts we are interested in so um
you can see that we can use it to enable
interrupt and also to
not determine which interrupts are
currently enabled
so this sounds useful and uh we are
going to
uh anybody has a question or something
like that
here's somebody coughing okay no perfect
um so if you are not muted please mute
your mics
um and uh
uh somebody asked if this belongs to arm
[Music]
so envy belongs to arm not the specific
ic that's a great question because
that's the next thing i'm going to talk
about
but before that let's take a look at the
value of this
nvx so this is the offset of the nvik
how do we call this register that's iscr
interrupt
set enable so
define nvic iscr
and this is the offset and you can
already see that this offset is relative
to m0 plus
m0 plus is uh the the uh
arm internal registers these are
uh the uh registers that are internal to
this
arm cortex m0 core so these are a part
of the arm architecture
and they are not specific to the pi zero
and this is the base the offset let's
just plus them
so the base address plus this offset
and uh we can just uh print the value of
this
register let's print it in binary
and as you will be able to see in a
moment
you can see that there are only a few
interrupts that are
enabled like number zero
uh one two three four five number five
and i don't want to count so if you want
you can try it later and see which
interrupt is that
but you can see that number zero and
number five are enabled and if we check
the interrupt table
we can see that number zero is indeed
the uh timer iq zero for the
alarm number zero and uh number five
is the usb because the arduino core
uses usb for the default serial console
so it probably
uh enables the usb interrupts to receive
events from the usb hardware
and back to the question from hllc8 so
is this um something that is
uh specific to the pipiko or is it
arm so this interrupt table is specific
to the rp2040
however the nvik isn't specific
and that's the reason there is no
information about it there is like
only the list of registers but there it
says
uh you need to check out the arm m6
architecture reference manual uh
for more information about those
registers
and that's what we're going to do so we
are going to check the architecture
reference manual
also called arm so that's the arm arm
and what i'm going to show you is uh
how instructions work so how do we
define the
the handlers for an instruction we know
uh we now learned
we can use this uh um this
register to enable and disable
interrupts but how do you deal the
microcontroller
what what where is the function or which
function handles
uh each interrupts so for that uh
we need to understand that interrupts
this is by the way
the arm the arm arm
and i will just put a link in this
document so you also have it
the arm arm and as soon as you open it
the most important
or the most useful thing you can do you
can just download this to your computer
i think it's much more convenient in
form of
a pdf file and then once you have it
as a pdf file you can just open it like
that and go to section
uh i think that's in
b1 5 yeah
exception model and
you can see this as like so interrupts
in arm
are just uh a specific case of
exceptions
and there are a few uh exceptions that
uh are like built in like this reset
where uh
this is the uh where the code starts
executing from
and all those exceptions like heart
fault whenever you have
your access invalid memory address or
something like that
uh systick which is another timer built
into arm
but the interesting thing for us is that
the interrupt starts
at number 16. so interrupt 0
is exception number 16 and that's a bit
tricky we need to remember that
and there is another section here that
shows us
how the uh the vector table is
organized so the this um
[Music]
this just shows the exception numbers
but if we want to know
or to set the handler for a specific
interrupt then we need to go to the
vector table
and the vector table is just a table of
32-bit values
and then uh the exception number if you
go to the
uh like entry number one that would be
the
handler for uh exception number one
and uh offset zero is reserved for the
initial value of the stack pointer
not very interesting right now um
and where can we found this find this
vector table where where can we see this
list of exceptions so there is a
registered
called vitor that um
points to this exception table
sometimes it's fixed uh in some of the
microprocessors
in the rp2040 it's not fixed
it's something that uh uh
the user can set where this exception
table recites
a vector table resides and uh
we can do it by setting the vitor table
so
let's go back we are going we don't need
this anymore we have the pdf
we are going back and forth between the
datasheet so let's go back to this
um to this uh datasheet
and in the list of registers of the
cortex m0
in the pi pico rp2040 data sheet
if you scroll down and bit you can see
all the nvic registers and here is this
veto register vector table offset
register
so it holds the offset of the vector
table so
let's copy it and i have it as well so
that's the
vtor and let's see where is this table
stored
in our code so we can just you know
print this value
as hexadecimal
and we can see that uh it's actually
stored let's remove this
we don't know need it anymore we can see
that it's stored at uh
20 million and if you remember from the
previous class
this is actually the start of the sram
so
let's go real quick to this address map
and you can see
it's just at the beginning of the sram
so whenever these uh
arduino core starts it just loads there
the vector table
and then then set vtor to pointer
and the next thing we are going to do we
are going to dump this table so we can
see
uh which interrupts handlers are
currently configured so let's define a
method that will do that factor table
and it takes nothing and basically what
it does
is just um goes from
zero to 16 plus
uh so uh we said that uh the
uh interrupts actually start at uh
number 16 and then they go 16 plus
uh number of interrupts that we had and
the raspberry sprite datasheet says that
we have
26 so we can go until
16 40 exceptions plus 26 for the
interrupts actually from number one
because
number zero is not an exception it's the
sp pointer
and then uh we can just uh print this
value so
uh we could use the arduino api like the
println
but in this case it's actually more
convenient in my case to use printf
and it works here uh in this arduino
core just redirected to the
serial output so a bit more convenient
and then we can just read mem32
at meter plus i times 4
because we need to go 32 bits
down for each exception um
yeah and then we can just um
vector table and hopefully in a moment
we'll have like
uh an error oh missing oh yeah i need to
add i plus plus uh
so uh somebody is asking if arduino boot
is doing all of this
who something messed up oh yeah i need
to add
i here to the printf uh so i'm not sure
if it's
the arduino used uses embed os
uh the arduino core so i think it's
embedo is doing this
uh or um maybe it's
even the bootloader that the boot stage
2 that does this
we can check it later um but that's a
good question anyway we can see this
damp dump of addresses and um
in order to make it a bit more readable
i prepared a list of
all the interrupts so we can and the
exception so instead of
having those numbers we can just use
this
map that i prepared and print their name
so
we can just the list of
exception names from um
from the arm those exception names
followed by those interrupt names
in a nice array and then we can just
you know print uh vector names
yeah it's just let's say wanted 20s
and we want to align them so they are
nicely printed
and when we run it we can see now all
the interrupt handlers let's
just uh copy it for a moment so we can
see
everything at once and
so this is the table and you can see
that most of them have this value
1c1 or these are actually not valid
these are like
unimplemented so we can ignore them
these are the actual exceptions but we
are interested just in
interrupts and we can see that most of
the those
interrupts has this value which is
probably the missing interrupt handler
these are the interrupts that are not
enabled and then for the
interrupts that are enabled we can see
this like the address of the
timer iq 0 handler
so this is the function that handles
this interrupt
and same for the usb and we can see that
the other interrupt that we have seen
before that the other one that was
enabled
is probably this uart0 it makes sense
because we are using the uart
and um then
uh all of those are like uh
uh unused right now by the code and uh
somebody is asking if this address space
is
in the uh flash the xap yes this is like
the uh
flash where our code resides and also
the arduino core
reside so it makes sense that those
handlers will be
in the flesh even though i think you can
uh
i know you can place code in ram i think
you can even place interrupt handlers i
haven't tried
i've i don't see any reason why it won't
work though
um cool so we have this
uh piece of code that dumps the vector
table
and just so you have it let's uh let's
save a copy and give it a name so
yeah i will tidy it up later but for now
let's just uh
call it pi pico
pie pico dump vectors
now and save this
and then lock it so i won't make any
changes
and save them by mistake and uh
yeah let's add it to the list here and
uh
yeah dump dump
vector table example um
yeah so uh you are somebody asking about
timer iq 0 why it's enabled by this core
i'm not sure why it's using it for if
you want to we can look into that in the
q and a session that's a good question
and i would love to explore that but
for now let's see how we can harness
interrupts uh
for ourselves so uh we are going to
remove this code for now this
dump vector table and go back to the
mission of blinking this led
this time we are still going to use
alarms but
with interrupts so the first thing we
want to do
is to enable
to to create this uh uh
interrupt handler so um let's create
void uh alarm one
um irq handler or let's call it just
alarm1
irq and this will be our interrupt
handler
and inside our interrupt layer handler
we are just going to toggle this
led so let's define this
this is like the uh
the we defined a register that would uh
just you know
uh clear the pin but we want to toggle
it so let's
take a quick look at the data sheet
where is this sore
it's in offset 1c so
1c uh so whenever there is like an alarm
1 irq
we want to just you know toggle this
pin gp1 and then the next thing we want
to do
is arm the alarm so
let's remove this timer delay we are
going to replace it within
the interrupt and then say just like
let's say
we want to blink every uh 250
uh milliseconds uh this number of
microseconds
um so uh we want to set the next time
the alarm once
and now the next thing we need to do is
just uh you know to set
this uh vector table entry so
uh we can do something like mem32
uh vitor plus we need 16
to skip past the exception uh the the
all the exceptions plus one because
that's uh
irq one we can see here it's uh
uh what was that the interrupts here
timer irq one is for alarm number one
um yeah we can define a constant for
that to make it the code at least a bit
more readable
so plus timer iq one uh
times four because uh each entry is
four bytes one word and this
horrible thing equals to alarm one irq
and uh at this point um
it it will probably complain because i'm
trying to
this is like you in 32 and then this
is uh uh not you in 32
and um i will probably have to
uh typecast let's see
yeah i'm assigning a oh we can remove
this
and terminate the comment i got okay
so it will probably uh complain now
because
um yeah i
it's alarm one irq because it's not an
integer so i will cast it into an
integers
yeah and we don't have this anymore we
can remove the loop for now
uh and yeah we need to convert it so
let's
just type cast it um
[Music]
and yeah so at this point the code runs
and uh the led doesn't blink yet because
uh we have defined this handler but
uh we are still missing a few things and
let's write them down so
we know what we need to do so step one
is define
the handler step two is enable
the interrupt the uh nvic interrupt
inside this uh nvec iscr
so that's uh um
[Music]
exception interrupt handler so that's
from the microcontroller side of thing
but we also need to do uh
some stuff for the timer itself and
let's let's take a look at the timer to
see what other stuff we need to do
uh to to to make this uh interrupt
mechanism work
uh so let's take a look at the timer i
think it's
a section yeah in the alarm
so if we want to enable an alarm and
have an interrupt we also need to enable
uh the interrupt inside the timer uh
peripheral
so you see you need to first enable the
interrupt at the timer
uh in this register then enable the
appropriate interrupt at the processor
which is uh this nvic register
and then write the time i would like to
the interrupt to fight to the alarm
register
and then it says the armed bit and
after the alarm is fired the arm bit
will be set to zero but i also need to
clear the interrupt
by writing this one to the bit in int r
so let's write it down uh the first
thing we need to do
is actually before we do that i mean we
can define the uh
the exception interrupt at the beginning
but then we need to
enable the interrupt in
the timer in e-register
and then
um and i'm seeing you have a couple of
questions in the chat let's leave them
uh for the q a session please uh take
note of them and
we will get back to them in the q a
session
um so we need to do this and then we
already have this
and then uh yeah
and then number four is
uh set the alarm one register
to the uh time target time
and finally here we it also said once
the interrupt has fired
we also need to uh um
clear this uh the latched interrupt by
writing
one to the pre bit in the into our
registers
or in our clear
the interrupt in into r all right let's
do this so
uh defining the exception handler we
just did it
cool now um we need to enable the
interrupt in this
uh timer in e register so let's see uh
where does
in e live this in e is at offset
38 and you can see there is one bit to
uh
each of the alarm in this case we want
to enable alarm number one so we will
set bit number one
uh let's define this so we have this
e at this offset and then we can say
in e
in e we need to
set to enable
beat alarm 1 rq and uh we can also since
this is a peripheral we can also do this
by writing to the
if you remember from last time we talked
about this uh
atomic memory access uh somewhere
uh here yeah atomic
register access there is like a a
shortcut we can write to this
add this value to the memory address
sorry this one to enable this bit
but it doesn't really matter this will
also do the trick for now
um just using this c syntax
and then we need to enable this
interrupt in this register
so uh yeah enable it
so just uh write uh one to that bit as
well
and uh oh sorry this we don't need to
uh read the value uh this register is
actually
uh you can see here
whatever we write there uh writing one
will enable the interrupt and zero has
no effect so it
it's only setting interrupts so we don't
need to
or equals it and we want interrupt
number one
timer irq and finally we know we need to
set the
alarm to the target time so this is the
target time
current time plus this constant and
yeah let's set the pin to output just
before we do all of that
and finally inside this uh irq handler
we also want to clear
uh in the interrupting inter
so uh let's see uh inter
enter inter that was uh timer registers
where is this into our row interrupts at
34 and this is a right clear register so
whenever we write a value to it it will
just
clear that bit very nice
so we don't have to use those atomic
register axes we can just write a value
directly
okay so uh let's define it so
into r i think that was 30 yeah
34 hexa and then i can say
just int r uh equals it
alarm
sorry it should be one and beat one
uh just you know we want to clear alarm
one so that beats
number one and coincidentally it's
also equal to the rq number but it's not
ruined all the peripherals it just
happens to be so in the timer
so we clear the interrupt in hint r
and now let's hold fingers uh and see if
this
works let's try to run it and see if the
led blinks and if not we'll have to
trouble oh
it blinks perfect so yeah so that's how
you do it with
interrupts and now uh the cool thing
about it
is that you can now do whatever you want
in the loop it's like
running uh sort of concurrently as uh
another background thing so for instance
we can do something like uh
four in i is one
eyeless or from two we are going to just
play with the other leds pi less than
eight and i
plus plus and then we can say uh
pin mode i output
and then here we can just do something
like
uh digital or you know just have this
use this
let's use digital right just to make
things a bit more
spicy just uh you know that's
the arduino way to toggle a gpio pin
uh delay 50. and
finally i want to remove this led
and let's make this one green the first
one now
let's make it green so it's a special
one the one that we are going to blink
and uh let's run this and
if all works well uh
yeah you can see this is blinking and
those leds are doing their things in the
group
and uh everybody is happy that's how uh
interrupts are useful so uh before we go
on let's just save this as a copy
and call this uh
uh pi pico timer
uh interrupt
and share the link with you so you have
it as well
cool so that's the uh
you said that's the pi picot timer
interrupt cool um one more word
about interrupts before we move on um
instead of doing something in the loop
we can also do
something like uh and this is sort of a
sort of a bridge to the next uh
let's just look it so i don't
accidentally save on it
this a bridge to the next section uh i
can
call a processor function called an
instruction called
wfi and it won't do anything different
in the simulation
and if you run it on the real chip you
also you won't want to observe the
difference between this and
you know just an empty loop but behind
the scenes
it saves power so
i ran this uh this code before with wfi
and without this wfi wait for interrupts
and using wfi saves around
three milliamps of uh current so it
reduced the current
consumption the average current
consumption by three milliamps
and if you want uh i can show you this
later the setup i used to measure this
later in the q
a session um
okay so uh one quick question from the
chat before we move to the next session
uh
section uh is whether all the alarms
three are the same interrupts so
uh no there is uh one interrupt per
alarm
if we check out this there is like rq
zero is for alarm zero
alarm one alarm two and alarm three uh
this is not uh true for the other
peripherals like
for the gpio for instance this is like
the sao irq
there is one interrupt handler for all
the gpios per processor
and then you have to look into the gpio
registers to figure out
which gpio uh trigger this interrupt so
it's the same for most of the
peripherals you have one generic
interrupt for the peripheral and then
you have to look inside the registers of
the specific peripheral to see
uh to check the bits there to see which
condition or which event
has caused the interrupt in that
peripheral
um but uh
yeah but uh that's basically
um the essence of uh
how interrupts work on the uh arm cortex
m0 and uh that's a good a good uh
time to uh move to the cpu registers and
talking a bit about
what is this arm cortex thing so
um arm has a pretty confusing
uh i at least found it confusing when i
started
naming convention there are like a lot
of uh
different uh or there are some different
ways to
categorize the microcontrollers and the
cpus
and i think this stack overflows
summarizes
uh this question this uh this
uh topic the they're like uh
except uh cortex-m and cortex-a and
cortex-m
is for microprocessors and a is for
more powerful applications like your
raspberry pi
uh the the physic big pi uh pi
4 3 or your smartphone and
you can read about the differences later
i will just post this
answer link here so you can check it out
later
and the other question
that is interesting uh and we'll get to
that in a moment
actually we'll get to that in a moment
um
so uh another useful resource if you
want to just get a good orientation
of all the like types of uh
processors that we have uh is this
um let me find i have a link here
somewhere
yeah the thing is i will paste the link
directly because
as soon as you paste it it just tries to
download a file
uh cortex and for beginners and
yeah i don't have it open i will open it
now
so cortex and for beginners and
it also gives you a quick summary of
like the to
the three different cortex families uh
we are here
cortex m0 plus that's the rp 2040
and it summarizes all the differences
and
uh also uh one thing we are going to
start talking about is the assembly
language
and you can see uh this is like the
assembly language for this
uh arm v6 that's the um
the uh architecture of the uh m0 plus of
the rp2040 you see it has
a low number of instructions compared
with arm v7
and there is even more in uh arm v8
so added on these two cool tables there
is a lot of cool information if you want
uh
to understand like all those uh
different processors in these
families all those processors so uh i
i suggest to take a look at it later um
cool
and uh all right
so now let's talk about instructions but
before we get to assembly and
instructions there is one more thing we
need to know
and uh that's the registers and we are
going to go back to the
arm arm section uh
somewhere i think it's in this system
level programmers model
registers yeah i think we have it on the
list
so you can see registers are like uh
variables local variables that uh the
assembly code uses
and uh there are like uh
uh only a few registers uh processor
registers
in the cortex m0 they are like general
purpose registers
r202r12 which we will talk about today
and there are a few more registers that
are um
like r3 13 14 and 50 they have like
spatial roles
and we'll talk about them uh in the next
class
and uh a few more registers that uh
have status and control the uh
cpu and we'll probably mention any then
in the future but for now we we need to
know that we have like those
r0 to r12 and they are just like
local variables and um
one cool shortcut that you can use in
the simulator
so let's just uh oh i
did i not save this i don't know
i'll check it later worst case i'll
let's just open a new one so i can check
this later
anyway so oh yeah i can now see that i
did save it
uh so yeah uh
i can just remove this stuff here and
you know remove all of this and get a
clean program
and i'm going to show you something
so um usually you need to use a debugger
if you wanted to see the registers
uh and we are going to do that in future
classes but for now i'm going to
teach you a quick way to do that in the
simulator
so you can write asm bkpt 42
i will also copy this here
and this spatial instruction
is usually used to set a breakpoints in
the debugger
but here in this simulator it just tells
the simulator to print all the registers
so that's a good a cool way to you know
just experiment and see the values of
registers so you can see here we have i
hope this is uh
big enough the font we have r0 through
uh r12 then all those extra registers
that
the datasheet mentioned and
uh the first instruction we are going to
look at is
called uh move and move just copies
value into registers
so uh let's say we want to uh so we have
r0 we can see that at this point in the
program it was
zero let's say we want to set it to
uh uh hexa uh
22 we just write move
sorry move r0 22 and this is the
equivalent
of setting r0 to 22 hexa
and if we run this code let's just clear
the output
and we can see it said register to 22.
um and then this
arm arm has a complete list of the
instruction uh i think uh there is
even yeah two four three three
so if we check two four three three
where is that
two four
three three programs margin yeah
we have like the the the complete list
of instructions so we have moved that we
have seen
we can also copy values between
registers so let's say we can copy this
uh now this new value we can also copy
it from
r0 to r1 so r1 equals
r0 and
let's run it and you can see that now
both have this uh
value and then there is like this add
that
adds a value to a register so we can
for instance let's say we want to
add to r0 we can add
so this is r0 plus equals
11 exa so we can add values
and then we can see that the result now
it's 33 hexa
or uh let's make it a bit larger
yep so this is the result
or we can subtract so we can subtract
like let's say we are going to subtract
10 hexa
so that's clearly how
clearly our output yeah and you can see
this
is actually minus equals
10 and you can see the result
and do fancy things like multiplying uh
like let's see you say we have
2 and 6 in r1 and then we can say
multiply r1 by
r0 so actually
2x3 that would be easier to see in
hexadecimal
so we can say this is a one
zero two i one equals three
and then r1 equals
uh multiply equals r0
and uh yeah you can see
a r1 is now 6 which is 2 times 3. so
uh this is how you can experiment with
assembly in your code in the emulator
i will show you one more cool shortcut
instead of repeating
asm multiple times we can use this uh
c plus plus way of writing multi-line
strings
just our quotes uh open parenthesis
and then we can just write uh the
instructions directly like
let's say pkpt 42
let's remove all of those and yeah
and now uh i don't need this semicolon
yeah and now you can see uh let's run it
again
and now you can see like it still runs
uh
those two instructions and uh sets the
break point
uh so just like we have seen there is
add there is sub
there is more there is no there is no
mole there is also a
move so copy registers
or copy value into registers
are we matic
operations and then there are like
bitwise operations like there is
and bitwise or bitwise sore so bitwise
operations uh let's for instance uh we
can move
our one uh 20
and then we can just you know
how one is 20 xr
and then we can bitwise or r1 with r0
so no need for semicolon here so
basically
r1 just uh
r0 and this should equal
22 hexa because we are uh yeah you can
see the result here in
r1 22x so
yeah as you can see it's just like you
have those registers which are very
similar to variables
and then you can put values there you
can perform
operations on them and uh
all those uh bitwise operations and just
uh with those instructions we pretty
much covered
uh you see all those move and
uh logical we we covered about one-third
of the instructions that there aren't so
many instructions
uh you can see it's it spends the table
spends
around three pages and we already
covered like uh
uh move add subtract uh multiply and
uh the logical or at least
some of the logical we still haven't
done those but uh
we'll get to them anyways so um this is
uh
somebody uh pointed in the chat this is
called risk reduced instruction so there
aren't so many instructions
uh if we check the architecture
reference manual
there are like um there is like
i think it's a6 yeah there is like this
list of instructions
and you can see it goes uh it has like
77
instructions in total like each
instruction in this section
but many of them are like are repeating
like they're like
uh three uh entries for ed
and same goes for like subtract
um and uh we are going to cover
uh a few some more instructions in the
next session
like uh loading and saving data into the
memory because
how could you uh how in the world could
you build
programs with just 12 or 13 are 0 to r12
we're just certain variables so if you
want to
uh interact with the memory and the
peripherals
uh that's how we ne that's where you
need to read and write values from the
memory and there there is a separate
set of load and store instructions for
that so that's what we are going to do
in the next class but for now i invite
you you know to just
hop on the simulator and just you know
play with those uh
i'll copy it into the uh the chat
with those uh instructions you do not
chat into the document
with uh and also this example just so
you have uh
a boilerplate you can use so you can
play with uh
and i can spell arithmetic apparently so
you can play with
all those uh instructions uh until the
next uh until the next session and just
get a bit
more comfortable with uh writing
assembly code
so uh well that's been that's been a
long ride
uh thank you for i i hope it hasn't been
too intense
and thank you for joining this class
today um i'm now going to take
questions in the q a and
just before that uh i want to say that
we are working on defining the final
project for the course
um i have a few ideas i'm still uh
trying to decide how exactly that would
be like so i hope to announce
more details in the next week so just so
you know that
if you want to receive a certificate at
the end of the course there will be this
project you will have to do it
it will be a project that
will require some work i estimate around
10 or 15 hours of work in total
maybe less maybe more but more detail
details coming next week
uh cool so we have five more minutes let
me quickly try to show you
uh how i did this thing with the wfi
so uh we have this um we have this
uh code and now uh if
i'm using it uh with just an
empty loop then
uh i mean it doesn't do anything
obser there is no observable difference
between this and
wfi but now
let me uh share my desktop
my physical desktop not my virtual
desktop let's see if i can
get the camera setting right
um so sure
trying to share my desktop i hope that
won't be too embarrassing
so yeah so on my desktop if it ever
loads
okay i don't want that camera i
connected another one didn't oh i forgot
to connect the other camera
it's my best and then zoom is using the
main camera
okay issue fixed and now you can see uh
i have this set up here so this is the
uh
nordic uh uh ppk power profiler kit it
allows me to
uh blind the camera and also measure uh
power and then this is connected to the
uh
pipe code that is also sorry about
uh missing the missing focus but the pi
pico is connected to the raspberry pi so
i can program it
uh or debug it which is not really
important right now
um so the first thing i'm going to do
i'm just going to uh use this variant
without
wfi i'm going to download
the uf file so i can upload it to my pi
pico download uf2 binary
and at the same time i'm going to
plug my pi pico into
let's show this in folder so
yeah i've done this before so uh let's
just remove all those
and let's call it uh firmware
no wfi and the next thing i'm going to
do
i'm going to plug my pi pico
into the computer so we can upload this
code into it
so plugging it and let's drag this
file
so uploading this firmware
and you should be able to see the
led or maybe not
blinking on the pi pico did i miss
something
let's try that one more time
oh yeah
wait a second
let's try that one more time
yeah oh yeah of course i'm blinking the
wrong led i need to blink
led number 25 that's that's the right
one
uh not led number one
let's just run it in the emulator once
to see that it blinks led number
uh 25 yeah now it blinks the correct led
um
oh no no uh in ask whether you have to
do this
use this plugs no i just use this uh
this clip so i don't have to solder
anything into my pipe echo
and i'm using the swd to load and debug
that's true even though now i'm loading
uh
let's download the uf2 again uh now
the one with the right pin with the
correct pin
firmware no wfi
and then copy it into the pipe echo
so now i'm just using the usb but you
can also use this
serial debugging protocol to
load the firmware so copying this
oh and now it's blinking great yeah
i'm loading through usb you can see it's
blinking and now i'm going to
unplug it from the computer and plug it
to the
into the ppk so
let's see it's plugged into the ppk
you can see here the two wires going
from the ppk to the pi pico
and i'm going to open nrf connect which
is the nordic semiconductor app
and as soon as it launches power
profiler
and now we can see
let's select the device bpk2
let's put it side by side with the
camera
side by side with the camera
[Music]
and now uh the led is not blinking
because uh
the device is not powered but i'm going
to switch the
starter recording and now i'm starting
uh the power from the ppk
and nothing happens because one of the
wires is disconnected
brilliant okay now you can see the led
is blinking but this time it's powered
from the ppk you can see this peak when
i connected the wire
and this is the power consumption and
you can see like
uh this is like the on and off period of
the led
and if i zoom in you can see that this
is the uh off period
you can see that uh i need uh 30
milliamps on average
and if now uh so that was um
about 30 milliamps and now if i just
uh change the code and add this wfi
and download the uf2 and let's just
upload this again to the pipe code
data code uh
that's showing folder
firmware uh that's with wfi
so that was 30 milliamps uh
yeah 30. milliamps
low cycle when the led is off uh with
without wfi
now with wfi uh let me
go back to this and just
plug it back to the ppk now that i
disconnected it from the
usb and uh
just restart this recording and now
you can already see the numbers are a
bit lower
for some reason the led stopped blinking
that's interesting
not sure why is that but you can see
like the power consumption
is let's try to restart this for a
moment
maybe that will help yeah now it's
blinking again
and let's start the recording so now you
can see
um this is now the power consumption
uh when the led is on and off and you
know if you zoom in
when the led is off the average is 25
milliamperes so
uh just by adding wfi we just showed
about
5 milliamperes of current so 25
uh low cycle with wfi
so uh now you have seen in your eyes the
impact of just uh adding this wfi
instruction
and uh shutting the uh core off
while waiting for this alarm and they're
like
uh you can use the rtc to even achieve a
single digit milliampere current
consumption but
we won't get into that um all right so
that has been like a nice uh
extra bonus uh just uh for those who
stayed
until the end and i hope that you
enjoyed
today's session uh i see that my
camera has reset uh now you can see the
whole room
ray um yeah uh so have a great week
and i hope to see you again next week
and if you have any questions hit me on
discord or
i also try to check the hackaday chat
regularly or on twitter you have my
twitter here
and that's it see you next time goodbye