Stm32 Peripheral Drivers from Scartch : GPIO Programming: Interrupts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right now in this video we're gonna go over writing the the interrupts functions for our GPIO to generate interrupts on specific pins now before we go into actually writing the functions I want to get an overview how it is that the interrupts work on the ARM Cortex processors so to do that I'm gonna give up I guess a brief explanation of how it is that it works basically in the processor what you have going on is the way it handles interrupts I'm gonna draw this out because it'll be much better to understand what you have going on is basically this you have your arm let's say this right here is your your your m3 cortex right this is your core inside of it so to speak and Vic you have the N Vic and this handles all basically all the exceptions that can come from the core itself or from different peripherals such as the GPIO and things like that and other other peripherals like the I squared C or the Ewart cetera and I believe the first 15 interrupts let's say these are all interrupt lines correct the first 15 lines are internal right it has to do with the core with reset and other things like that and then the lines that remain come out here right it's not exactly that many but let's just say it is and some of them are out here this right here this black is called the eat TI the external interrupts block on this block is where your GPIO interrupts are connected so what ends up happening is that you're going to use your gonna enable you enable it interrupt for a GPIO you're gonna enable it here right so let's say this line this interrupt line right here corresponds to let's say I don't know GPIO on port B pin four right and then this line right here as you can see is line one but over here it's not line one over here it's let's say it's line 16 so you're gonna have to enable line 16 on the end Vic line one on the a ext I block to enable GPIO port B pin for external interrupt as well as do a couple more settings on this external block now this number to get this number to find out what what this number is that's the ir q and the ir q number and i'll show you how to find this and we'll also figure out how to find this number and all of that good stuff i mean so that's that's a very very basic idea of how it works so let's see what it is that you that you actually have to have to do to get all of that working so let's first look at the first one look at the end Vic the end Vic is the one that's internal to the processor and if you go on section 10.1 on your datasheet and you go to the ISO Note 10.1 point 2 you'll see this table this table shows most of the interrupts that are excuse me that are on the that the cortex handles as you can see you have interrupts for your timers for I squared t can buzz direct memory access channels these interrupts right here are the ones that are that go from that n Vic block like that block that goes to the ext I so these lines are the ones that are control your GPIO lines okay another thing to notice is that you have these settings right here this position priority type of priority description and address what this means is let's look at this example make this smaller so that's it's a you can see the top or not anyways what this is telling you is that the ext the external interrupt line 0 that's what the 0 the one in the to mean is position 6 so the irq n the number on the end Vic corresponds to position 6 so that's the IR cue number on the envy the exe I block its line 0 as you can see right there and this is telling me that it's the priority is settable so you can actually change the priority so for example if you have both of these interrupts happen at the same time this one in this one you can change the priority of them so that you can control you can control which one happens first and the lower the priority number the higher the priority so if this were priority 2 and this is priority for this one would execute first should they both fire at the same time this right here is just a description that is telling you that this is the external interrupt line 0 and this right here is the address of the handler so obviously when an interrupt happens it's happening because you want your program to do something well this address right here is where the function should be located that it's going to control is going to handle your intro up basically and you don't have to worry too much about this because it's already mapped and I'll show you how to find that so you just start you know you just write a specific function name and it'll be mapped to this address and then whatever you put in that function is what's going to happen when you're in trouble fires okay so I'm showing you all of this tin data sheet and I'm going to show you where to find it in your actual your actual application okay so that's the that's the end Vic table and again it has all the interrupts that are coming out of the end Vic or into it however you want to see it the position numbers the addresses what they do and if their priority is settable or not okay let me just go ahead and show you that in the actual application itself if you go to this file right here the stm32 f110 X dot H file and you type in our rqn if you press ctrl F and you type in our QN it'll bring you to this which is kind of close to the top of the file and it has all of those all of those interrupts with their respective position numbers so I could just type in our a QN and it'll return the value 6 the proper position number on the end of ik line when it's time for me to to activate it and what I'll show you how this is all relevant once we start coding now the next thing even the next thing you need to know about is the actual register that you're going to use which are the of that external interrupts block and this is the description for this starts at 10.2 page 206 on your manual here and you can read that so I'm just gonna go over the some of the basic things as you can see this is telling you that that external internal block has 19 different lines okay and they correspond mostly to your GPIO pins and a couple for some extra stuff so as you know each port has 16 pins so then that leaves a couple of interrupt lines for other stuff now the way this works is like this EXT i0 which is external interrupts line 0 which is the one we just saw on the end Vic that was position 6 again let's say this one right here external interrupts 0 1 2 or 3 & 4 etc those the way this works is like this if you want an interrupt on port a pin 0 you're gonna use external interrupts line 0 if you want an interrupt on port a on pin 1 you're gonna use external interrupts line 1 as you can see this right here is a multiplexer these are multiplexed into a single line so you see you can use multiple of these on the same interrupt line for example you can have Port a 0 on pin B Z and port B 0 the thing is when you do that you have to figure out which it came from because it's just it's not gonna tell you which one set the intro up you have to figure out yourself so it's more tedious to do that if you want more than one interrupt it's better just to set them on separate lines that way each of them execute their own code as opposed to you trying to figure out ok which pin 0 set off this interrupt as you can see all the port pin zeros are mapped to external line 0 okay furthermore so you have 15 basically 15 options here you have Port a pin 15 will get you're gonna have to put that through external interrupts line 15 the interrupt line 15 so this is pretty straightforward so that should make sense now here's a here's a little thing though you only really have if you look at your here you only really have external interrupts line zero line one my two line three in line four okay let me make this bigger so you only really have these five interrupt lines so which these correspond to pin zero on all ports pin one and all ports pin to pin three pin 4 so what about the rest of your pins well those are multiplexed on these lines so if you look at this one right here this is line nine to five or five to nine however you want to read it okay so this is zero to four this one's gonna be five to nine so pins five through pin nine are multiplexed on this single line you know that's annoying but that's how it is and then the remaining pins ten to fifteen are multiplexed on this line right here okay so just be aware of that that these are all the pains are multiplexed on a single line but then furthermore you have you know this mess going on here but we'll get to that again once we start coding so that's how the that's how you know what line you're gonna use it really just depends what what pin you want pin you're gonna use now let's get into the actual registers of the external internal block basically all you're really gonna need is one two or one of these maybe both of them if you if that's what you want and this third register right here so let's just go through the first register is the interrupt master register basically this is where you enable the interrupt for the certain pin for example if you're gonna the if you're gonna do an intro up on pin 4 you just put a 1 over here into this register and you shift one into the fourth bit and that will enable the interrupt for that specific ext I line okay so if you want to label line four remember doesn't and over here doesn't really matter what port you're on because all pin fours of all the ports are gonna go to the line for of the xti block so you would just put it one in here and you would enable line for you the event mass register I really don't use so I can't tell you much about that now your interrupt for example let's say it's a push button that when the user pushes it you want on led to go on now when do you want to enable that when do you want to trigger that interrupt on the rising edge in other words the second that they're pushing it or on the falling edge which would be the second that they let go of the button again that depends how you have the button wired I usually wired my button to to ground and that when the user pushes it it gets pulled up but again this so if you wanted again that pin for - to trigger an interrupt when when to use on the rising edge you would put a one to trigger the rising edge for line four so everything here is mapped one to one so you know this fourth bit is line four so it would be trigger rising edge four line for that same line for that you did in the intro mass register right here and this other register would do the same thing but this is the falling edge so if you want your intro up to happen on the falling edge that's uh this is where you would make that happen and yes you can do both but then you get to interrupts okay the next one is a software interrupt this is basically when you want to make the interrupts happen without it actually happening in the real world for example if I wanted to in my software pretend that the user pressed the button I would just put a one I would set this right here and this would generate that intro up as if it actually happened okay so this is why this is called the software interrupts event register so this is where you would uh by software generate that interrupts and again everything is mapped one-to-one were bit four corresponds to line four of your your intro clock now when an interrupt actually happens what what goes on is that a flag is set and it's set in this register so when that interrupts on pin four happens what happens is that a one is gonna be set right here it happens automatically by hardware when that one is set your processor jumps to that interrupt handling routine that you're gonna write okay now here's the thing so long as this one is still set in here it's going to keep triggering and interrupt so when you're in truck happens and it jumps to that interrupt handling routine the very first thing that you need to do is clear the pending interrupt register you need to clear this so that you tell the processor hey I've handled the interrupt or I'm going to handle the interrupt so you clear this so that that interrupt is no longer pending now the weird thing about it is that to clear it you would think you write a zero but you don't to clear it you actually have to write a one into that bit even though there's already a one they're being set by the hardware to clear it you actually also have to write a one into it and we'll see we'll do that in the code now another another thing we have to look at is the actual how we're gonna set this sets up the the interrupts and the events but we also have to set up the alternate function on that GPIO pin okay so we're gonna actually use the alternate function in Alton function a RAF i/o registers here now the way this works is as it's the one that we're actually going to use for for interrupts there are these four register right here the external interrupts control register one external interrupt control register two three and four now register one as you can see it sets lines EXT i0 EXT i one EXI two and three and controller just two two is line four five six seven all the way up to your ext eye line 15 so this is where you tell those lines what port or what pin you're setting for example if we're gonna set pin four we would go to the ext eye line four correct so we would use exe on line four and we're gonna set an interrupt but it needs to know what port to expect that interrupt from could remember all the ports pin fours are mapped to this interrupts so I need to tell it which one it is that I'm gonna be using so I'm going to be using let's say for our example I'm gonna use pin port B so I would write a 0 0 0 1 0 0 0 1 to tell this register that online for expect an interval from pin 4 on port B so line 4 corresponds to pins for and by depending what number I put here I'm gonna tell it which port that interrupts it's coming from so I would write josie1 port B and that's basically how you control what you do with these registers so if you were to set a interrupts on let's say line 14 on pin 14 of Port let's say F right so F port F corresponds to this right here so you would write a 0 1 0 1 on that and that's basically how that works now another thing to keep in mind is that in your excuse me in your your RCC register your clock gating register you actually have to enable that alternate function alternate notice neighbor astir the alternate function here the alternate function you have to enable the alternate function even though we're setting everything over here that has its own clock so you have to enable that and you would do that by shifting a one-in-two bit 0 of the RCC a PB to enable register and we'll do that all in code what else am I forgetting that should be it hopefully so let's start um let's start getting the code down for this and we'll run through everything as it as it has we're doing it so the first function we're gonna we're gonna do is actually to configure the GPIO interrupts so I'm gonna go ahead and paste this and you can pause the video and copy it this is configured GPIO interrupts and we're gonna pass it first a port so we know what port are our intro pin is gonna be on we're gonna pass it a pin number and we're gonna select the edge where it's gonna be if it's gonna be rising edge falling edge or you know what I mean and this is uh okay this is a 32-bit integer this right here is a enumeration I made and that is right here type def enumeration rising edge falling edge and rising falling edge and it's an edge to like type def okay so it's like we made our own little variable so then when we call this function when we're gonna pass this edge our parameter we're going to pass it one of these okay so here's our function and now we're gonna go to our C file and we're gonna go ahead and we're gonna start writing those functions again I'm gonna copy it from my file whether it words already written because I'm not going to type this over 20 time okay now this looks like a really long function and it is but a lot of it is repetitive so here is our function okay the first thing we're gonna do is we're gonna go to that APB to enable register and we're going to enable the alternate function now this right here is if you if you copy this let me make this big again if you copy this word-for-word this is defined in this document right here as you can see it just means it's all that's doing is just setting it to one basically it's going to shift the one into that oops into that uh what the hell into that that alternate function setting that I showed you in the datasheet so hmm all this doing its sifting a1 in here so you can do it like that or you could alternately you could do shifter one into the 0s bit you can write it like that or you can just write that whatever floats your boat so that's enabling the alternate function register this right here is going to now we start checking for the ports okay so this parameter that was that were typing port so if they if we're gonna configure port a remember we have to set all how do I explain this all right back to datasheet this is the way the stm32 people made this go here we're gonna go to our afo registers now remember these four registers the ones that I told you that that you're gonna set depending on what line you're gonna tell it what port you want so the way they set this up is they have the alternate register pointer and it points to these different registers but it points to them in an array and for some reason if you if you're if you're gonna access where is it if you can access external interrupt control register one to set these pins right here so this is a external interrupt control register one remember this one did ext I line zero on line one mine to line three and this is the first one control register one this is where you type in what port it's gonna expect that interrupt on so the numbered 1 through 4 but over here they're in an array and they're indexed from 0 to 3 so if you're gonna write this register right here you would actually write to ext I right here so the 0 is 1 and if you're gonna write to the next one you would write to 1 so to sum it up if you're gonna if you're gonna set line 0 line 1 line 2 or line 3 on which it corresponds to the first register you would actually be doing index 0 right here so you can see line 0 line 1 line 2 and line 3 on this first register which is index 0 now when you do in line 4 line 5 in line 6 and 7 these are on the index 1 register so the way they did this is basically they took all these write these four registers they put them in an array from 0 1 2 3 and it's kind of confusing because in the datasheet it's 1 2 3 4 so that's all that that it is if you can just remember that 0 1 2 3 is really 1 2 3 4 ok so the way I have my code here is let's make it smaller so we can read it basically I first I'm I'm gonna do an entire if statement right with with a switch case and I'm checking for the pin number so if I'm on port a right and then I'm checking pin number okay so I know I'm in port a then I'm checking pin number so this is if it's pin number 0 I'm gonna go to that first register right register 1 which is index 0 what my datasheet so I'm going to go to register one right here I'm on port a I'm gonna go to I'm checking the pin number so if it's if it's zero I'm gonna go to the first of these registers in X zero and I'm gonna shift this right here just it's zero zero zero zero that's all that's all that does and again this if you if you copy it word for word and then you right click and you go to its definition it's in that same file and it has the values written so for port a is zero zero port B is 1 port C is two it has all these values right here already right now so that you're not that way in your code you're not typing you know zero zero zero one because that's kind of hard to really read so again so that's what we're doing here so we're for pin zero and we know we're in Port a that's why you see all of these say pa-pa pa-pa-pa we report a so again let's say let's go to case three so if I'm in pin three I'm again I'm still doing that first register this first register right here and I'm gonna shift that value that zero zero zero into the the three the line three which is gonna be right here okay so you see how it says ext I 3 it's gonna shift there right there correct and yeah so these are all these things are mapped out the way they should be so you don't have to worry about any of that being wrong now from four as you can see now this four we have to go to the actually to the next register because this one only goes up to line three so we're gonna go to the line to the next register which it's to here but it's it's one over here and there and in since it's four we're doing line for ext I for this is gonna shift the proper value into that line four okay so I hope that makes sense so we're gonna do all of this for port a okay so we're gonna go to line four we're gonna ship this value for port a into the line 4 or line five all the way up to 15 and every time we're changing registers once we get to the new register so over here line eight so we're gonna have to go to the third register line eight is in you know in this register starts in this register line eight right there so it's three here but it's it's two over here so it's basically four zeros for ones for twos and for threes and then these right here these are not all the same you got to look at them carefully this are these two words are the same but the line number the xti 0 will correspond with the case number you know EXT i-5 would be case five and they're all port a so we do that up to 15 for the entire port a now you can literally copy and paste this and now you're gonna do it for port B the only thing you have to change is this right here the B over here and all of these B's right here everything else would be exactly the same okay and the same thing for the next register C D whatever all you're gonna change is the letter here and the letters over here and all everything else is the same so that's why this is a really long function but it really is just just copy and paste so once you've done that after you you and this is just setting the autumn this is basically setting the the pin into an alternate function mode once you've done that we can check to see what the user passed for edge did they pass rising edge did they pass falling edge or did it pass rising falling edge which would be both so if they passed rising edge we're gonna go to the this ext I registered which was uh which wasn't over here in our ext I block and if they selected a rising edge we're gonna go to this ext I rising edge register right and we're gonna shift a1 into whatever pin number they wanted because remember the pin number corresponds with the line number so if they're using pin four we would go to line four so we would put a 1 over here to put a rising edge trigger on line four so that's why right there we go to that register and we put a 1 into the equivalent pin number the same thing if they select falling edge we pass it that into the falling edge register or if they select rising falling edge which would be both edges we just do both of these steps would first put a 1 into the rising edge and then a 1 into the the falling edge register and the rising edge register so that handles the configuration part of the of the pen the next function we're gonna do and now these functions get a lot shorter is enable the actual GPIO so now we're gonna enable the interrupt you can configure it and then we're gonna enable it and this is gonna take as a parameter a pin number and then our irq number okay so go ahead and copy that and then we're going to write the function we can write it right under this one and of course I'm gonna copy it from my okay now this one is short and sweet and it looks just like that okay so this function all it does is it goes to that interrupt mask register and which is right over here the in short mass register and remember it just all that does is enables an interrupt on that line so if we're gonna go to line four we'll put a 1 over here and that's all that one does put someone into pin number on the in chart mask register and then the second line here what this does it in tables because remember I told you you have to enable it on the ext I block and you have also have to enable the line on the end Vic side and to find that again it depends on what line you're using so if you go to the top of this document here what you have or you are our cue numbers depending on what line you're using that's what you would pass it and it would it would just enable it and this function right here is an internal function that is defined in the core this right here is a function that's defined in your core files provided to you by the the vendor and the people over at arm and that's how you would enable it on the N Vic side so that's that the last function or not really last but at least the last two these header files it's gonna be to actually clear the interrupt because remember I said that once once the interrupt happens it you have to the very first thing you should do is clear the interrupt so we're gonna have a function it's gonna clear the interrupt and all we really need to pass it is basically the pin number because that's all it really needs because all this is gonna do it's gonna go to this pending register and where every line you're interrupted is on all you got to do is write a 1 to that line to clear it and as you can see that's all the that's all the function is going to do so that clear interrupt function is that right there where we're gonna pass it a number and it's gonna clear it and I compile with no errors and cetera now how do we use this simple so this is a code we have I assume from last time it's been months since I've seen this up here we're using our previously made things here to set pin 13 on port C to an output and then we initialize it and it's set and this one we're setting port a to pin 7 and initializing that I'm not sure why I have that but what I will show you is how to actually use the the what we just wrote so we can delete this because we won't really need it for our purposes so get my keyboard out and you can start typing so the first thing you're gonna do is you're gonna call that configure function that we wrote so figure it is configured interrupt and we're gonna pass it first the port so if you remember from our previous code this these ports are already named so you just start typing so we're gonna use port B we're the passport B then the next thing is what the hell was the next thing what PIN number and then edge select pin number so we're gonna use pin number four like we've been saying edge select would be these this enumeration that we made right here so we can select rising edge and that should configure it and then we'll call the enable function enable that your GPIO interrupt and all that is going to take is the number four right that's where I put a pin number and the irq and number so since this is pin four I know it's on ext I line four so I'm gonna go look at this our this vector table here and I know that ext line pin number is equal to ext line four so I'm gonna copy that our irq n number and where am I mmm peace that it's at that so that's that now that hand was that now remember I told you that when your interrupt goes off it has it goes to a function and that function is mapped to to a certain address that we saw in the in the vector table so for example ext I line four is mapped to this address now the way you'd handle that is you have to write a handler function to handle that interrupts and all that really is is you know start writing the function you can just copy this right here there are q n number copy that right that's how your function is gonna be called except you erase to the N from the end you raise that n you type in underscore irq handler so i r cubed and blur and boom that's it that's your function that's going to handle your interrupt on line four if you have more interrupts you know you're just gonna write different functions each with the corresponding interrupt line and also remember the very first thing you should do in your intro up handler function is called that clear GPIO interrupt so that it can intro so it can clear that pending bit so you're not so your CPU because let's say you have you know a lot of code in this function that's gonna happen during your interrupt well then it's not really gonna happen because your interrupt is constantly gonna be calling this function and it's constantly gonna be just running it's gonna flood your CPU so you have to clear that interrupt depending Bittner that's the first thing you do before you write actual code in here so again I don't really have a good camera at the moment to show you this code works but I've done it a million times it works so if I have forgotten something I will surely probably added to to as a comment somewhere or something but this is really the basics and enough to get you going on interrupts on the stm32 and don't forget that you really have these four individual lines and the rest of your lines are multiplex nine to five and ten to fifteen and you can get smart and figure out how you can find out which pin generated and interrupts so that's it for now 45 minutes I don't know if this came out bad but that's too long I'm not gonna redo it if you have any questions you can go ahead and comment I get the notifications on my phone or email me or something alright that's that
Info
Channel: Eddie Amaya
Views: 13,885
Rating: undefined out of 5
Keywords: stm32, stm32f1, stm32f103, stm32f103c8, arm, cortex, arm cortex, microcontroller, programming, arduino, 32bit, driver, GPIO, blink, led, pins, embedded
Id: A_zuzEajLE4
Channel Id: undefined
Length: 45min 33sec (2733 seconds)
Published: Mon Jan 02 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.