Raspberry Pi Pico PIO - 8 Little Processors You Can Program

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there my name is gary sims and this is gary explains and one of the interesting things about the raspberry pi pico is that the processor it uses the rp2040 has something called programmed io and that's basically a way of controlling the general input output pins a gpio using hardware rather than software so inside of the rp2040 there are in fact eight other small processors state machines we would call them that are dedicated to being able to manipulate the input and output pins in a hardware precise manner it's not just software when it gets round to it but based on a very strict clock routine which is great when i do high speed communication with the outside world so put another way there are eight little processors inside of the rp-2040 that you can program using assembly language and this video is all about it programmed io on the raspberry pi pico if you want to find out more please let me explain okay so really understand how to program the uh pio the state machines inside the raspberry pi pico you need to understand how they are made now they're not like general purpose processors you can't be you know doing you know ads and branches and multiplying and right you know these i've got a very limited instruction set specifically for doing something with the gpio pins now basically what you've got is you have an input queue called a fifo first in first out that means if you send one two three down the queue then one two three comes out the other end that's different to a lifo or a stack which is not used in this case a very different thing so five for what goes in the queue is in the order that it comes out you have another queue for sending things out back to the real world so you can back to your program that's running on your raspberry pi pico you've got some scratch radiuses x and y that you can load values into them and kind of use them for doing loop counting and then you have a way of shifting data across to the pins or reading them from the pins using the output shift register or the input shift register and then of course there's an actual program that runs so you have a program counter and it executes one instruction per cycle in a very deterministic way and you can write those programs so you can get it to do things so there are nine instructions very very small instructors that just nine instructions that you can use ten if you use the macro no op and we'll talk about that in a second so let's have a look at the nine instructions so you get a feel of what you can do with this tiny little state machine there's only a processor that can do programmed io so the first instruction uh is jump and that's very simple you're running a program when you want to jump to another place and you can jump there always just mandatory jump you can jump there depending if x or y those scratch registers are zero you can jump there if x and y are not the same you can jump there if a particular pin is actually set to be high you can jump there if the input output output shift register is not empty and then for looping you can actually decrement a value of x or a value of y and then loop round jump if it's not zero so that first instruction is basically a way of doing loops and jumping to different parts of the program depending on some conditions now not a very wide range of conditions you would get much more in a general processor however this is a good start being able to do a few things inside of your gp or your pio program next instruction is pretty simple wait so stall do nothing until either a given gpo pin is true or false or there's an irq flag set there's not a weight in terms of time this is wait for an event to happen the next instruction is shift shift so many bits from a source place into this special register we talked about the input shift register and you can read that from the pins that basically means you can read things coming in from the pins you can read it from x or y or you can read it from zero you can also read in from the input shift enter itself or from the output shift register now one of the things about the pio programming is basically if you you can kind of read and write to just about anything uh input shifted output you've read to the pins uh back to the queue because the idea is to be able to get as much io going on which means sending things and writing to things so that's one good thing about this so even that input into the shift register can read itself from the shift register the next command is the out it's actually the same except it's for the output shift register and you can out from the outputs you've registered to the pins 2x or y you can discard it from null you can even write to the program counter which is an interesting way of kind of doing a jump you can actually also read from the input shift register next you have two instructions for reading and writing from those two fifo so push pushes the contents of the input shift register to the rx fifo it does that 32 bits at a time and clears the input shift register to zero and there are some flags about whether it's full or not full and then paul does the opposite it pulls from the tx fifo into the output shift register and again there are some flags checking whether things are empty or not and it blocks accordingly so you've got these two push and pull how you communicate with the outside world so the actual program running on your raspberry pi pico would push things into it and it would pull things out of it and they can get communication going on and we'll look at this when we do some demo programs in a moment there's also a move function so you can copy things let's say from x2 y or from the inputs you've registered to the output shift register so a way of moving things around internally inside of your state machine you can actually set some flags for irq so that things can happen when you can check to see things happen according to an irq flag and then there is a way of setting a heart a value so you can set x to seven for example or you can set a pin to one which would mean on and that's the full nine instruction and the tenth instruction as i mentioned is no op do nothing which basically doesn't move from y to y so it takes some time takes one cycle but doesn't do anything okay now once you have all those instructions you basically now have to write a small assembly program using those load it into the state machine and then let it run now the good news is that micro python has a slightly higher extraction of those instructions so that you can actually write all this stuff in python without having to use the assembly there is an assembler included as part of the pico sdk so you can actually write this kind of programs there tex file assemble them into the binary and then use a program to load those into the state machine but micro python offers a slightly higher abstraction but not very high you're still using pull and push and set and move and the input shift registers on the output trigger all that kind of stuff but allows you to do it with inside python okay so what we're going to do is go over to a raspberry pi pico we're going to start writing some programs in micro python that specifically program the state machines and then let them run and for of course for visual effect we'll do something with leds we can see what they're doing but equally the led coming on could be a one being sent down a wire or a zero being sent and so you can actually see how you can do communication with the outside world okay let's head over to the desktop okay so here we are inside of funny funny of course is the ide for python that understands about the raspberry pi pico it's very easy to get python programs on and off the the device very simply understands the file system and everything you don't need to do anything complicated so here is our very first pio program probably this is about the shortest one you can create so the first two statements are going to be pretty much the same through any kind of pio program you write using micro python that means you need to import the stuff that understands the pico chip the rp 2040 and you need to un import some stuff from a machine which understands about the different pins because it's gpio these are things that normal python wouldn't be interested in because of course python is a general language but when you're using micropython for a microcontroller you can import these extra libraries now i'm going to jump over this section just for a minute we're going to come back to it let's jump down to here now as i explained there are these different state machines up to eight of them inside of the raspberry pi pico's processor and basically every time you want to use one of those state machines you use this state machine class that is provided by this rp2 library that we imported up here so it basically says i want to create access to a new state machine which state machine well zero and it could be one two three four five six or seven depending on which one you are going to use you can use multiple ones you can define many of these that's why in this example i've put sm0 because you could define sm for state machine of course sm1 sm2 sm3 you could call it whatever you want is a good way of dividing them up now the next parameter is the program that you want the pio state machine to run so i've just called it pio prog and if you notice that's the name of this function we've defined up here so these two have to be the same we'll come back to that and set base equal to pin 25 basically it says when i'm writing to a pin i want it to start the sequence of pins it can be a series of them at pin 25 whenever the set command is used we'll talk more about this later on specifically if you if you get this wrong then your program won't work and it can be quite frustrating to try to work out we'll talk about that later in the video so we've got these three arguments then the state machine we're trying to con figure the program want the state machine to run and what pin you want it to use whenever you talk about writing or reading from a pin and then what you do is to turn the state machine on you basically say state machine zero that's the one we defined dot active one switch it on you can do active zero which we'll see later on to switch it off again if you wanted to now at this point the python program ends there's nothing else here for the python program to do but the pio starts running in the background and will keep on running nothing will change now let's have a look at these few strange lines here now this one is obviously quite different than what you've seen before the first thing it's saying here is that i want to make sure that the uh the initial state of the set pins is low you can have low or you can have high and basically this command here is an inline assembler so it's basically saying i want you to to assemble the stuff do the right things so that we can actually have that happen at the assembly language level so it's set in its state equal to low and then we go into the program itself well this is a fairly normal python definition of a function however this is not this is something completed now this is the set instruction that we looked at earlier of those handful of instructions that you get for the pio programming and it's the mapping of of a function inside of micro python to the actual low level assembly command and you're basically saying right two pins and we've defined that the base pin is pin 25 so effectively right to pin 25 which of course the led on the picot board at one so in other words turn the led on that's all we're doing in this program we're using the programmed i o state machine to do one thing and that one thing is just to turn on the gpio so if you run it let's see what happens [Music] and of course it comes as no surprise that the led switched on okay let's look at a slightly more advanced program okay this is one of the example programs that you can find in the raspberry pi uh pico github i'll leave a link to it in the description below and basically it's a way of blinking an led on and off using the pio so let's just go down to the bottom here's the program obviously we're going to talk about that let's go down to the bottom so same idea a state machine is defined it's exactly as the same as we did in our previous example except for now we can also set the frequency now by default the frequency of the state machine is the frequency of the pico chip itself which is 125 megahertz if you want something slower then you can set the frequency here however it can only be the smallest you can do is 125 megahertz divided by 65536 which i think is actually 1908. so 2000 uh is about the lowest that you can get it running at if you want to run slower than that then you actually need to slow the clock down on the pico itself and you can do that using a micro python but running at his default clock speed 2000 is the lowest you can get to anyway so we defined this state machine and here you can see what do we do we switch on the state machine we wait three seconds and then we switch off the state machine so that's pretty simple switch it on let it do its thing and then switch it off again so what is the thing well we can see here it's calling this function called blink which is what we see up here so blink again is a micro python pio program and it's not using normal kind of python here these are again the instructions that are part of the uh the micro python's handful of of assembly instructions so what happens here well let's have a look we'll ignore this first one for the moment we'll come back to that sit pit set pins to one well we've done that before we know that does that turns on the led on pin uh gpio25 so that gets turned on but what's this thing here well one of the things you can do with the pio is you can automatically add a delay a delay to the end of every instruction and it can be up to 31 cycles because it stores this number as part of the instruction and so it can only there's only space for up to the naught to 31 so you put in here 31 so it means four now for 31 cycles at two megahertz we've got there it will do nothing so it will do nothing for 31 cycles now that's not quite long enough for us to see the led flashing so what actually happens now is that for another four lot of instructions using the no op and the no op is just a mapping to move y to y remember move is one of the instructions we looked at move y to y and to does nothing because y just gets written over again with y so nothing changes but then delay for 31 cycles and if you do that for enough of those in a row you can create manufacture a delay and then what you do is you say now set the led to zero so you should you're on then you set your office which you're on then switch off that's how you get the blinking program and again you need to delay using these no ops each one of these having a 31 cycle delay at the end if you change this frequency here it would mean these delays are shorter in real time because it's per cycle and and it would actually flash quicker now we've skipped over wrap target now basically when a program gets to the end of its uh pio instructions it needs to do something and normally it jumps back up to the top and this is what this is saying this is saying when you wrap when you get to the end wrap around to the beginning then actually it's saying set the wrap target so the set wrap target means go to here and here is the wrap now in this case of course it's going right back up to the very top of the program and that's fine but you can actually do some other things in here you know you could say set pins zero you don't need to but you can do things before and they only happen once so when it first comes into the function it will execute whatever lines there are before the wrap target then you can say the wrap target and that becomes kind of like the main loop so you can have a kind of initialization phase and then you can go through and run your main loop in this case actually just loops rack around itself so this will flash the led so let's run it and make sure that is exactly what happens [Music] as you can see there it flashed the ad for three seconds because we activated the state machine ran for three seconds then we deactivate it so it stopped doing the flashing that it was doing so there you go there is a program using a bit more of those uh commands a bit more of those assembly instructions for the programmed io now really just switching an led on and off with a manufactured delay just a hard delay of just like do nothing do nothing for 31 cycles and for another 31 cycles and it makes it flash on and off okay let's move on to a bit more of a complicated program now if you remember there are two fifos one for sending things into the state machine and one for sending things out of the state machine and what i want to look at now is basically a program that whatever you send in gets sent out so a very very simple bounce program in it goes or an echo program sometimes they get called whatever it goes in comes out so we'll jump over our actual pio program for the moment but let's again see here while we create a state machine nothing surprising here causes this bounce uh function frequency set to 2000 pin 25 which means it's basically it would be working on pin 25 but it doesn't actually do anything on this one it just sets things in and out but here down here this is the code that interests us so what we've got here first of all we say in the state machine put the number 31 onto the txq so tx transmitting into the uh into the uh state machine okay and then what i do i print out two things i print out you can ask it how many things are there in the fifo how many things are there in that queue and so i say please print out how many there are in the txq please print out how many things are in the rxq and then i say well let's run the program which is this program up here which we'll look at in a minute and let's just wait one second and then we're going to stop running the program and then i want to see how many are there on the input queue and how many are there on the output queue and if there's something on the output queue which i know there will be let's get it to find out what the value is now of course what we're expecting if we're just doing this echo is when we run it there'll be one thing on the queue before the pio starts running and there'll be nothing on the output queue we then run it for just one second and in that one second the pio will have bounced it back onto the output queue that's the program we're going to look at in a moment so therefore the number of words in the firefocus is zero because it kind of got inputted it got sucked in pulled off and then it actually writes it out again to the rxq so it then gets pushed on to that and then we say okay let me tell you what it is and then we read it so basically we're expecting 31 to pop out the other end having gone into the state machine and come out of the state machine how do we do that well here's our program again very simple pull pulls off something from the tx fifo and puts it into a register called osr the output shift register remember that's one of the registers that's in the pio we then use the move instruction one of the assembly instructions and we say move the contents of the osr into the isr the isi is the input shift register and then push automatically pushes whatever's in the input shift register onto the rx fifo so paul pulls it from the tx fifo into the osr the osr is then copied over to the isr and then push pushes whatever from the isr back onto the rx firefox so let's see what happens when we run the program okay so what do we see the number of words in the txq is one that's correct that's what we'd expect it's the number 31 we put in there and there's nothing in the output queue the rxq we then run wait for one second then stop and now it's inverse the number of words in the input qtx fifo are zero because it got pulled into the pio but the number of words in the output queue is now one and then we say we'll get it from the output from the rx and it's 31. so we put 31 in we did something within the firefox and then we kind of output it out again on the other side so now you can see you can get things into the fifo and out to the firefox imagine if you were writing a program that was sending some numbers over the serial over uh you know i squared c over spi you can say please send the number 27 and it would know then how to do that with all the bits going up and down bit banging are they calling it all the bits going up and down in the right sequence so that protocol is understood at the physical level so now we can get things in and out and if there's a reply that comes back we can get that out again to the calling program and now you have full communication going on via the pio machine and the pins that it's controlling so let's develop a little bit this program that sends things in on the fifo and then does something and sends it out last time we just copied out it was about an echo now we're going to write a function called double it so we're still going to send in 31 we're still going to check the queues we're going to let the program run for one second and then we're going to fetch the result out again but now we're going to double it rather than just echo the number back out now a clever thing you can do in binary is if you shift a number to the left then you double it so if you had one in binary shifted to the left you get two if you have two and you shift it to the left you get four if you have four you should to the left you get eight so you double it every time that's actually the nature of binary so we can actually do something here to double a number just by shifting it to the left so what we're going to do in our pio program we pull what on the tx fifo into the osr and then we use this in function which basically is a way of putting things into the isr by rotating it a certain number but shifting it certain number of bits so what we're saying is go into the isr from the osr and we want to do that 32 times 32 bits so basically shift in the numbers by 32 we could have done it using a move for example i just wanted to show you a different command here in in this case because n is bit wise if i just did this like eight or two it would only do it by two bits or by eight bits it didn't have you don't have to do it with the whole word but we do it with 32. i also wanted to note that because there's actually a keyword called in inside of python you have to use in underbar note in underbar not in okay that's just because it so it doesn't clash with the actual language of python itself and then what i do is i set x to have zero in it and then what i do is i shift the input shift register again by one using uh what in x and i do it by one bit so effectively it's gonna shift everything that's in the input shift register which is in fact what we pulled off the tx firefox we shift it uh to the left once and obviously there's overflow situations here if you had a 30 one bit number and then you shifted it you'd start to get overflow but if we stay in something like 31 that's not going to be a problem okay so let's give it a go okay so the program runs similarly as before how many words are there on the tx fifo there's one on the rx five for the zero we run the program we wait one second we stop it there's nothing on the tx5 anymore because he got taken into our program and now there is something on the rx fire phone what is it it's 62 hooray 31 times by two of course is 62. okay here is another new program and this time i want to show you that you can actually execute commands on the uh the state machine in a bespoke manner just by saying execute this command on the state machine so what do we do ignore this bit for the moment but what do we do we create a state machine as per normal uh running a function called prog which we'll talk about in a minute and we set pin 25 and then what you can actually say is sm dot execute exec okay and you say set pins to one so it's the same as what we wrote in our very first program but now we're doing it kind of in line and this will actually assemble this to the right machine constructions send it to the machine and just execute those instructions and then we can say sleep for half a second and then we can say set the pins to zero so what we're actually doing is this is a way of setting the pins to one and zero turning on and off just by calling the set function in line without actually writing an actual program that runs and we'll actually see run it in a second that it will just come on for half a second and the way you do this here is that when you write this prog which is what's defined here in the state machine you use this uh construct they have in python called pass which basically means i i might put something in here later i need to put this null really but it's syntactically correct so this is a program a function that does nothing it just passes in other words it's correct okay so this program does absolutely nothing uh but it need you need this parameter you can't not put this parameter in so we're basically putting in a dummy function to make it happen and then we're kind of talking to the state x the state machine uh individually ourselves by running these individual instructions this is really handy also for debugging because if you say to yourself oh can i just uh do this quick thing here at this point and kind of try to get something out the state machine or set something in the state machine change the value of x change the value of y you can do all that kind of in line by using that python program okay let's run it and see what happens and as you saw there we get one flash it just goes on and then switches off again okay now that we know how to send data into the the uh the pio the state machine we know how to turn pins on and off with that wouldn't it be good if we send it some numbers in and whatever numbers we send in it flashes the led according to the ones and the zeros of the number that we put in and that's exactly what we're gonna do here so basically again we define a state machine the function is called blink pull because it's pulling it off the fifo and we're making sure that it is a shift to the right that happens and i'm setting base pin 15 in this case which is actually just one that i've got a wired up to a different led let's just you know jazz things up a bit here i'm using a different led to make things a bit different of course the idea of course showing that you can use any gpio pin as defined on the raspberry pi pico we set it running no problem at all and then we go around here in an infinite loop putting onto the fifo this number which is basically zero all low bunch of zeros or ones 15 bits as well zero's in a one 15 bits over zeros and then a one so basically it's going to have 15 loads of zeros and then a one fifteen loads of zeros and one so you're kind of gonna get a flashing going on and if you change that number to other things you're gonna get different patterns what does the program itself do well we set the wrap target in the wraps that just means it just goes round and round and round and round forever paul basically pulls something off the fire and by the way a thing we're not going to go too much into now is there are mechanisms for knowing whether the fifo is full whether it their stuff to be pulled off basically the default is that it blocks so when it says pull here it will wait until this program actually has actually got round to put something on it and this will just keep trying to put it on and this will block when the fifo is full and this will wait until there's something to pull off the firefox so it's all synchronizes by the fact that it knows whether there's something there or not okay once we've pulled off the number from the fifo we now want a loop to go through all those bits so we set this to 31 we say x to 31 and you'll see why in a moment we then define a label so we can do a jump and it's called bit loop and you can see that's used down here with the jump we'll get to the minute and what we basically say is and what this command does it outputs to the pins in this case pin 15 one bits worth by using shifting to the right because it's the output shift register remember is what's on the it gets pulled out so the output shift that's why it's called that okay it shifts it to the right one and whatever that number is whether it's a one or a zero it writes that to gpio pin 15 and then it waits a delay of 31 cycles so basically if there's a one in the next bit it's gonna turn it on if there's a zero it's going to turn it off and then there's this nice jump here that jumps back around to here so it basically just does the next out but there's this clever thing here and it basically says decrement x and keep going if it's not zero so this has a special meaning decrement decrease x by one and then jump around if it's not zero so basically we get a loop that goes around all the bits here and then once that's happened it wraps around pulls the next number off and does it again okay so let's run the program and see what happens [Music] as we can see there the program factor let's get rid of the one there so we're going to have more zeros and less ones let's run that and see what happens and as you can see there that flashed less frequently because we're sending uh more zeros and less ones and you could put whatever you like and of course you can imagine this is again demonstrating how if you actually wanted to communicate over some lines to some other devices i squared cspi uart whatever then you can actually send things into the machine and actually get it to send them across in fact there is a uart example uh that you will find on the github repository the examples from the raspberry picker again the link same as before is in that description is in the description below now we've just about come to the end of all the programs that i wanted to show you which i hope this has given you a good idea of how you can use this however i in my kind of playing around with this did come stuck want and i wanted to point it out to you to make sure that you don't have the same problem now if you look here this looks like a fairly okay program we define a state machine pin 25 we turn it active and what does the program do it just sets pin 25 to 1. but the problem is we're using set and in here we've used out and down here we've used out in fact if you run this program you won't get anything at all there'll be no flashing leds there'll be no leds going on or off at all but there are also no error messages there's nothing to say that you've configured the pio the the state machine incorrectly so this should be a set and this should be a set because we're using set here now in my debugging and in my playing around i've switched between set and out and and i kind of like and if you change the method that you're using set rather than out rather than using the output shift register you're just using explicit set then you've got to remember to set these so maybe it's kind of a tip you should always set you know the uh set and the out you should always use set and out you should always define set and out here so you make sure you're using uh the right pins just a bit of a gotcha uh it took me a little bit of head scratching because i worked out oh i just changed i didn't know silly me so just so that you don't fall into the same pit okay that's it my name's gary sims and this is gary explains i really hope you enjoyed this video if you did please do consider giving it a thumbs up if you like these kind of videos well then stick around by subscribing to the channel don't forget you can follow me on twitter at gary explained and i also have a monthly newsletter go to gary explains.com type in email address no spam but you will get the email okay that's it i'll see in the next one [Music] you
Info
Channel: Gary Explains
Views: 70,045
Rating: undefined out of 5
Keywords: Gary Explains, Tech, Explanation, Tutorial, Raspberry Pi, Raspberry Pi Pico, RP2040, Pico PIO, PIO, programmable input/output, MicroPython, Output Shift Register, Input Shift Register, FIFOs, State Machine, Pico State Machines, PIO State Machines, PIO Assembler, 16-bit instructions
Id: QlKtEA5XKc4
Channel Id: undefined
Length: 31min 55sec (1915 seconds)
Published: Mon May 02 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.