LPC_GPIO_PORT and LPCXpresso812-Max - Page 1
Forum section: electronics / beginners

author: bodzio_stawski
author_rank: Regular Contributor
timestamp: June 09, 2023, 03:09:21 pm
content: Hello!I look timidly towards cheap microcontrollers for learning, which some people will consider (and some will probably advise against) LPC microcontrollers.While searching I got here:https://forum.digikey.com/t/getting-started-with-the-lpcxpresso812-max/13319One thing immediately struck me:- The paragraph titled IDE shows the choice of the microcontroller (or board) on which to work. The author of the article, of course, chose his board based on the photo, but on the left on the print screen you can see that you can, for example, choose LPC810, LPC811, LPC812, etc. I assume that you choose, for example, one of them depending on the microcontroller you have and move on. Then some pre-code is probably generated based on your recent choices.Question:And: next is a sample code to play with diodes.Code:void LED_Init(){LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);//red ledLPC_GPIO_PORT->DIR0 |= (1<<7);LPC_GPIO_PORT->SET0 |= (1<<7);//blue ledLPC_GPIO_PORT->DIR0 |= (1<<16);LPC_GPIO_PORT->SET0 |= (1<<16);//green ledLPC_GPIO_PORT->DIR0 |= (1<<17);LPC_GPIO_PORT->SET0 |= (1<<17);return;}Look at this line for example:Code:LPC_GPIO_PORT->DIR0 |= (1<<7);Number 7 reffers to port 7 of GPIO: PIO0_7 (not "physical pin/leg of microcontroller; PIO0_7 is on pin 17 of microcontroller.So it seems that this code refers directly to the PIO0_7 of the microcontroller,hence my question:A given subgroup (810, 811 or 812) has its different versions! So, for example, the 812 version can be 16-pin, and it can also be 20-pin, so then PIO0.7 will be on a different leg depending on the variant of the microcontroller - not always on pin 17 (if we buy it as a single microcontroller, not on the entire devboard of course). So how to distinguish in the code, to which physical pin/leg of a microcontroller a PIO0_7 belongs, since the code operates on GPIO numbers, and not on the numbers of physical pins?

author: ataradov
author_rank: Super Contributor
timestamp: June 09, 2023, 03:55:40 pm
content: Quote from: bodzio_stawski on June 09, 2023, 03:09:21 pmWhy do you need it?The only way to do it is to read device ID and have mapping tables. But if you need it, you are likely doing something wrong.Usually you don't use numbers directly. You define their functions. Something like: "#define LED (1<<16)" or "#define BUTTON (1<<7)". Then use logical names in the code "LPC_GPIO_PORT->SET0 = LED;". There are far more generic and complicated ways of doing this, but the basic approach is this.And you define things based on the schematic of the board. Pin numbers are irrelevant here. And it is a good idea, since it lets you easily move between the devices without redefining everything.

author: bodzio_stawski
author_rank: Regular Contributor
timestamp: June 10, 2023, 11:22:55 am
content: Thank you for your clarification and suggestion on how to define functions in code. Sorry if my question seemed trivial, it was not my intention to offend you. I appreciate your help and hope you didn't mind my question. Thank you again!

author: bodzio_stawski
author_rank: Regular Contributor
timestamp: June 10, 2023, 07:32:31 pm
content: Excuse me, but I would like to ask again about this. Ok, I can feel somewhere inside myself that it's better to operate on the GPIO numbering, not the numbering of the physical pins. However, I remembered a certain analogy regarding AVRs (I know that AVR is more simple). There, if you operated on Eclipse, you could choose "Target Hardware" and choose a microcontroller. Here in LPC, at most e.g. LPC812 is selected for example. Then I have subversions with different amount of pins (just a few GPIO pins more). Regardless of which version (amount of pins) I choose here, finally I get the same header file, supposedly universal:https://github.com/sebseb7/lpc8xx/blob/master/core/LPC8xx.hQuoteOk, I know my question is like " which particular blood cells of John Smith are destroyed by Covid", but I would like to understand what is going on in the code / libraries / pin tables that, for example, a D1 diode connected to PIO_7 on pin 14 of the LPC-"X" microcontroller will be the same like D1 diode connected to PIO7 which is on pin 17 of the LPC-"Y" microcontroller and this discrepancy between the fact that here is 14 and here 17, doesn't matter for a programmist at all. I can't finally sort it out in my head, because it would mean that you would transfer the code controlling this diode from the microcontroller X to Y and the pin number (14 or 17) would not matter.Half the trouble, if we could move the code to a microcontroller with more GPIOs (the surplus of which we wouldn't use anyway). But moving the other way around, i.e. to a microcontroller with a smaller number of GPIOs, would be impossible. "LPC_GPIO_PORT->SET0 = (1<<16);" would be impossible when we move from LPC812 20-pin to 16-pin version. I feel that I need to understand at least in general, where it is encoded in the microcontroller that PIO0_7 or any other GPIO is located on pin 14, even though the programmer does not need to use it.

author: ataradov
author_rank: Super Contributor
timestamp: June 10, 2023, 09:36:13 pm
content: Quote from: bodzio_stawski on June 10, 2023, 07:32:31 pmOn the hardware level AVR still uses port numbers. Literally all microcontrollers from the very beginning did it that way.Quote from: bodzio_stawski on June 10, 2023, 07:32:31 pmIf whatever environment was hiding port numbers from you, it was purely software thing. Arduino does this, and it is annoying as hell and causes constant confusion.Quote from: bodzio_stawski on June 10, 2023, 07:32:31 pmYes, that's the idea. The hardware is the same, it is the same physical die, not all pads are connected to the pins, but otherwise there is no difference between them.And this is another reason why they can't make 1:1 assignment of pins to bits - the same die gets packaged into different packages with different number of pins. You would have to have some re-mapping table inside to support this.Quote from: bodzio_stawski on June 10, 2023, 07:32:31 pmYou have to plan ahead for the target MCU. You will often see evaluation kits be designed for the largest MCU in the family. This lets you develop your application on the kit and then seamlessly move it to your target hardware. Obviously you need to plan ahead for what pins would be available there.But another advantage is that on a bigger MCU you can use some pins that would not be on the smaller one for debugging, for example. Then the same program would still run, you will just not have access to the debug pins.And you also need to keep in mind alternate functions, which are not present on all pins. You can attach an LED to any pin, but UART or I2C are only available on some pins. So, planning of resources is something you do to select the appropriate MCU. Just pin count is not enough anyway if those pins don't have functions you need.

author: bodzio_stawski
author_rank: Regular Contributor
timestamp: June 11, 2023, 07:08:02 am
content: QuoteFor now, I can't figure out why I wouldn't do it in the current situation.https://www.nxp.com/docs/en/data-sheet/LPC81XM.pdfHere are all packages: from DIP8 to TSSOP20. For example, PIO0_0 pin, described as PIO0_0/ACMP_I1/TDO in every package, has different leg/pad number: 8. in DIP8 package (LPC810M021JN8), 16. in TSSOP16 package (LPC811M001JDH16 and LPC812M101JDH16).QuoteLPC8xx.h - when I open this file I feel that it's prepared for the largest (20-pin) version of LPC8XX microcontroller. But nowhere, absolutely nowhere, can I see how this file would cope with the fact that sometimes PIO0_0 is on pad/leg no. 8., and sometimes on leg no. 16.So I have a huge request - can you show me an example of pin mapping in the code of any microcontroller of your choice? Maybe then it will be easier for me to look for it in LPC and any microcontroller.

author: ataradov
author_rank: Super Contributor
timestamp: June 11, 2023, 03:26:05 pm
content: Quote from: bodzio_stawski on June 11, 2023, 07:08:02 amI really don't understand why you want it.Quote from: bodzio_stawski on June 11, 2023, 07:08:02 amOk, let's say you used DIP8 for prototyping because it is easier on a breadboard and wrote your firmware to use pin 8. Now for the real bard you want to use TSSOP16 package because it is easier to solder. If you just referred to the pin as PIO0_0, you would not have to change a thing, just route the board accordingly. If you referred to it as 8, you would have to go an update your firmware. And you can't route it to pin 8, because pin 8 on the TSSOP package would be a completely different pad.Quote from: bodzio_stawski on June 11, 2023, 07:08:02 amBecause it does not matter. Firmware does not know about legs, it does not care about them. Firmware works with ports. How those ports are mapped to the pins is a hardware thing, firmware is no involved in that.When you migrate between the devices, it is on you to route the board according to the pin functions, not pin indexes. When moving from a package with 8 pins to a package with 16 pins, you don't just use ins 1-8 and leave pins 9-16 alone. This would not even work because power pins are different.Quote from: bodzio_stawski on June 11, 2023, 07:08:02 amI don't really understand the request.Here is a practical example with this level of abstraction -https://github.com/ataradov/mcu-starter-projects/tree/master/samd21In the main.c you can see how pin functions are mapped to the pads:Code:HAL_GPIO_PIN(LED, B, 30)HAL_GPIO_PIN(BUTTON, A, 15)HAL_GPIO_PIN(UART_TX, A, 22)HAL_GPIO_PIN(UART_RX, A, 23)On the board LED is connected to the pin with a function PB30. I don't know what pin number it is, and I don't care. If i wanted to make a new board with a different device, I would find pin PB30 on that new device and connect LED there. If new device is smaller and PB30 is not pinned out, then I would have to pick a new pin for it, and then I would have to change the code.

author: Christe4nM
author_rank: Unknown
timestamp: June 11, 2023, 05:31:58 pm
content: Quote from: bodzio_stawski on June 09, 2023, 03:09:21 pmFirst to say: good thinking and you’re on the right track. Indeed, in software you work with PORT and PIN numbers (NXP calls them PIO, other may call them GPIO). And indeed, where they connect on the physical package is different per package. If I understand your question right, then you’re wondering how do the two connect? And if you use a different package on a different project, then what happens?Thankfully, the manufacturer gives you the information you need in the Data Sheet or Reference Manual.Look here for the datasheet of the LPC 81xOn page 6, chapter 7, you will see these figures. They show you for each package on which physical pin each PIO is connected.There is also this table starting on page 8, that lists all the PIO (and some other) functions, and which pin they connect to for a given package. And if you look at either or both, you can see for example that PIO0_1 is physical pin 12 on the TSSOP-20 package, but pin 9 on the TSSOP-16 package.You may notice that some pins have more functions than only PIO. That is common, as a microcontroller can do many things. And you can choose what you use a certain physical pin for. It usually can only do one thing at a time, and there are ways to tell the code which function to use. That also means that after the microcontroller starts up, after reset, there will be function that it goes to automatically. Usually, but not always(!) that is PIO.What if you want to use a different package for your controller?Now to the question: you have written some code, and now you want to use it on a different package where the physical pins are linked to a different PIO. This is where you need to do some work. On one hand you need to decide which pin you want to use for what. If you make your own board that is simple, you can choose almost freely. Almost, because not all functions are available on every pin.But you as the programmer must look up which PIO connects to which physical pin, and then use the correct PIO in your code.So say, you have the LPC812 in a TSSOP-16 package. And you want to connect a LED, and you’d like it to connect to physical pin 8. For example, maybe that’s the easiest for you for doing your PCB layout.Now you go to the diagrams and the table in the data sheet, and you look up which PIO you need to use in your code. If you look in the datasheet I linked above, you will find that you need to use PIO0_10 for your LED now. So in your code you will now need to use “(1<<10)” when you need to do something with your LED.But what if you wrote all your code and then later decided that you actually wanted to use the TSSOP-20 package. But you still want to connect the LED to physical pin 8. Well, again you need to do the same thing: you go to the table in the data sheet, and now you see that in your code you must use PIO0_11. So now you need to change every single use of (1<<10) in your code and make it use (1<<11) instead.Easier with MacrosBut can’t that be done easier then, because now you need to change your code everywhere you used PIO_10? And perhaps you used other PIO as well that also need to change. It’s a bit difficult to make sure that you changeeveryinstance of PIO to the correct number. Well, that’s where it is easier to use “macros” in C:What if you could just, for example, write “MY_LED” everywhere. And somewhere at the top of the code is where you tell the compiler that “MY_LED” means “use PIO0_10”?This is how:Code:#define MY_LED(1<<10)Now instead ofCode:LPC_GPIO_PORT->DIR0 |= (1<<10);LPC_GPIO_PORT->SET0 |= (1<<10);You can write:Code:LPC_GPIO_PORT->DIR0 |= MY_LED;LPC_GPIO_PORT->SET0 |= MY_LED;And if you need to change which PIO you want/need to use, the only thing you need to do is change the macro:Code:#define MY_LED(1<<11)And the rest of your code has now changed as well to use PIO0_11 everywhere it says MY_LED.If you apply this to the code you shared in your first post, is looks like this:Code:#define RED_LED(1<<7)#define BLUE_LED(1<<16)#define GREEN_LED(1<<17)void LED_Init(){LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);//red ledLPC_GPIO_PORT->DIR0 |= RED_LED;LPC_GPIO_PORT->SET0 |= RED_LED;//blue ledLPC_GPIO_PORT->DIR0 |= BLUE_LED;LPC_GPIO_PORT->SET0 |= BLUE_LED;//green ledLPC_GPIO_PORT->DIR0 |= GREEN_LED;LPC_GPIO_PORT->SET0 |= GREEN_LED;return;}TL:DRSo in summary: you as the programmer need to know which PIO you must use if you want to use a certain physical pin. If you change the package, then you need to change some things in your code too. But you can use the table and diagrams in the Data Sheet to tell you what you need to know. And you can use macros in C to make your life easier if you need to change something.

author: bodzio_stawski
author_rank: Regular Contributor
timestamp: June 15, 2023, 01:51:07 pm
content: Thank you for both answers. I wanted this approximation of the level of abstraction, in relation to pin mapping, but when we use the same GPIO pin, although the example of Christe4nM, when we insist on a specific leg, was also interesting and I will keep it as well, as well as the example of ataradov. Thank you!