Pi GPIO in RISC O/S
Andrew Conroy (370) 740 posts |
You have the physical pin number, the logical GPIO number and then the “Wiring Pi number” which Wiring Pi decided to adopt to “simplfy” things! The logical GPIO number doesn’t always map to the same pin on every Pi (eg. the very original Pi had GPIO 0 on Pin 3, but later models replaced GPIO 0 with GPIO 2). |
Julie Stamp (8365) 474 posts |
Also GPIO_Info returns “logical GPIO pin number” and “physical GPIO pin number”, which on my Pi 3 are always the same, and seem to be what you call “logical GPIO number”. I’d be interested to hear if they are ever different! |
Andrew Conroy (370) 740 posts |
I’m not sure how it defines “logical GPIO pin” & “physical GPIO pin”. I was using “physical” to mean actual metal pins 1-40 and “logical” to mean GPIOs 2-27 which appear electically on some of the physical GPIO pins (the other ones being power & ground pins). |
Ian Nichols (1527) 6 posts |
The StrongHelp documentation does, indeed, still need a bit of attention. For example, the page about GPIO_WriteMode says that bits 0-4 of the new mode setting are “mode from pin info” which links to the page about pin info which says that at offset +9, bits 0-4 are the “mode number for GPIO_WriteMode”. Bit of a circular reference there. So far as I can tell (from the earlier version of the StrongHelp manual which I’ve now overwritten with the new one), the lsb of the mode number sets the pin to be an input (0) or an output (1)… which duplicates the function of GPIO_WriteOE, but with inverted logic… doesn’t it? So why do we need to have GPIO_WriteOE? other than that it will now break many people’s code if it gets removed. Or have I missed something important? If it’s OK to do it that way, I’d prefer to used GPIO_WriteMode to set whether pins are IN/OUT simply because I can then set the pull-up/down for inputs at the same time. This modified version of some of Chris Hall’s code, does what I expect, i.e. light LEDs attached to pins 24, 25 and 8, cycling through them when pin 7 is grounded through a switch.
|
Alan Adams (2486) 1149 posts |
It can get worse. I’ve just spent two days working through some working, well commented code to drive part of the GPIO which exists on the Wandboard inside the ARMX6. It was written mostly in BASIC with small sections in assembler, and all I wanted to do was convert a small subset to mostly assembler, with just one or two calls from BASIC, so that I could operate 4 pins. |
Alan Adams (2486) 1149 posts |
So on the Wandboard, I’ve got LED drivers connected to GPIO pins 6 and 7 on the JP4 connector on the board. I can, in software, toggle both of these to 0 or 1 output. However pin7 low seems to want to be at around 1 volt into 10k, so the LED there stays lit. Adding a 4.7K pulldown resistor allows that LED to be switched on and off correctly. Pin 6 goes low to around 0 volts, as I would have expected. I have a recollection that some of the GPIO controls allow internal pullup or pulldown to be specified (on rPi). As the CPU on the Wandboard is the same as some PIs, I assume the same would apply there too. I’m wondering whether pin 7 is defaulting to internal pullup, while pin 6 defaults to pulldown. Is this likely, and if so, how would I go about reconfiguring it? |
Chris Hall (132) 3554 posts |
If the pin is set to output, then its pull-up or pull-down status (these are about 60k Ohm remember) is irrelevant. |
Alan Adams (2486) 1149 posts |
That corresponds with chapter 28 of the IMX6DQRMr2_part1.pdf document. Which leaves me wondering why one of the outputs seems to want to be fairly high when set low, while still going a lot higher when set high? I might have to add some more wires, so I can test the 3 remaining gpio pins on that connector. Hardware fault? |
Dave Higton (1515) 3525 posts |
From the symptoms, it looks to me as if you think you’re altering the output level but in fact you’re altering Output Enable. |
Alan Adams (2486) 1149 posts |
I see what you mean. However I’m using the same functions on three pins, and only one behaves like this. It’s complicated, because this is on an ARMX6, which does have a version of GPIO but doesn’t have GPIO module support. Step one is to map the mux register and to map the base register for bank 3. The output enable register is then at an address 4 bytes above the base register, while data is sent or received using the base register. To setup, I first write to the pad register, using the mux base address, with the parameters for each of 4 pins. For these to be GPIO pins, I need to set option 5. Then I write to the output enable register for all 4 pins, 3 as output, 1 as input. Then I can repeatedly write to the data register for the three output pins, and read back the data register for the input pin. When I write a 1 to the data registers, all three pins go high. |
Dave Higton (1515) 3525 posts |
Is it possible to read back from the output enable register to verify what you think you’ve written? |
Alan Adams (2486) 1149 posts |
There’s something in the manual about reading back from that register, and it returns something other than the setting you’ve just made – I think. “While the GPIO direction is set to input (GPIO_GDIR = 0), a I’m not sure what to make of that. I think in effect the GPIO_DR register is write-only, while the GPIO_PSR is read-only, and they share an address.
I’m not doing the loopback bit, as the code I’m basing this on doesn’t do that, and I’m not sure what the “.sion” means. |
Dave Higton (1515) 3525 posts |
It’s also possible you’re swapping the data direction instead of the output state. |
Alan Adams (2486) 1149 posts |
Yes, I understood that, and it might produce the described symptoms. However, it should therefore produce them on all outputs, which it doesn’t, and if it’s switching it back to an input, the pullup resistor value is far too low – I’d estimate around 1K. I’ll dig into it some more later, although probably not today. |
Alan Adams (2486) 1149 posts |
So a quick test shows that it is something in my software. I’ve gone back to the original example code, and removed a couple of links on my circuit board so that the pins were independent, and all 4 behave as they should when used as outputs. I did notice however that this pin is at the mid-voltage level as soon as the computer powers up. This raises the possibility that I’m not setting the pins up properly, rather than driving the outputs incorrectly. More detective work needed. |
Robin Hounsome (1539) 25 posts |
Just a thought. Page 1423 of the manual talks of GPIO output Drive Strength and Open Drain operation. Is it possible you’ve got the two pins set up differently. The GPIO-07 control register detail is on page 2482 |
Alan Adams (2486) 1149 posts |
If it is, then it’s because that’s the default setting. That second page reference might be useful though, if I can work out what address to use for the register. Now got that. I’ve gone through the sample code, which as I said, works, and nowhere does it access the control register. At the moment, the original sample code works correctly, while mine, which uses the same assembler routines, but called from assembler instead if from BASIC, doesn’t work correctly, but is, I think, consistent. I’ve added logging to the assembler functions in both cases, recording which was called, and the entry registers, and I’m comparing the listings. I can’t find anything different so far, but I’m wondering whether the faster sequence of calls from assembler might be involved. There’s bits in the manual talking about needing “two wait states”, but I don’t know what they mean by wait states. Is this a delay that the hardware controls, or am I supposed to count something down? THe assembler routines called from BASIC, start with OS_EnterOs and end with OS_LeaveOs. I’m calling those in the outer assembler routines, because eventually this will be run as a callback, and that’s already in SVC mode. So far I haven’t read all 5000 odd pages of the manual. All the GPIO stuff *seemed" to be in chapter 28, but you’ve pointed out some more relevant stuff in chapter 36. I wonder what else might be hidden somewhere in there? And pin 7 is GP3-08 on JP4 connector pin 16, so I’m using register 3 of the GPIO. I assume the pad control register is number 3 too, page 2473, and also the mux_control_pad on page 2109 is also for GPIO 3. Both of these could affect the pin, but as I said the working software doesn’t touch them, and my non-working version doesn’t touch them either. (The sion reference I didn’t understand is on page 2109. ) And now I think I’ve found the problem. The sample software had the wrong mux register offset for pin 7, but still worked. It also worked when I corrected it. My software works provided I have the correct offset. Instead of using IOMUXC_SW_MUX_CTL_PAD_DISP0_DATA08 is was using IOMUXC_SW_MUX_CTL_PAD_EIM_AD08, while using the correct addresses for the other pins. Weird that the sample software worked. |
Alan Adams (2486) 1149 posts |
Getting closer, but not quite there yet. As long as the sample code has been run first, then as long as the processor remains powered up, my code works. However starting from cold my code doesn’t work. The sample program runs a full setup sequence before asking which test to run. Mine does the setup part that seemed necessary for the 4 pins I’m actually using. It may be that some part of the setup would benefit from being run twice, or with a delay between setup and use. I don’t think I’m missing out any of the setup steps for those 4 pins. More checking shows that the wrong offset is being used for two of the pins, not just one – unless I’m misunderstanding the documentation. The register description of the apparently wrong registers says something like “this is part of a chain”. Huh? Still, it gives me something to work on tomorrow… |
Dave Higton (1515) 3525 posts |
I’m not familiar with that CPU, but there are limitations in other CPUs (different manufacturers, so not necessarily comparable) as to how fast one can access multiple peripheral registers without the internal queue getting out of order, so a spinlock might make it behave differently – it’s easy to implement and so worth a try. I suppose assembly language makes it more likely to trip over that sort of problem. |
Alan Adams (2486) 1149 posts |
Thinking about it overnight, it seems that to get my bit to work, I need to run the original sample code, then mine. If in mine I access the AD08 register as used in the sample, it doesn’t work. If I use the DATA08 register it does work. Edit: So a few more things to try. |
Alan Adams (2486) 1149 posts |
So five days later, and now it works. The odd thing though is that I didn’t change anything, at least as far as I can see. |
Glen Gilchrist (8824) 8 posts |
I came here looking for a “simple” primer into how I can drive IO via the GPIO pins on a PI Zero Forgive the obviously noob Q’s I see how I can drive IO to light LEDs and respond to switch toggles….. from the example in the Wiki (Crosses fingers)…. Where can I find anything to help demystify how I could possibly access I2C devices (say things like this: https://www.amazon.co.uk/AZDelivery-Humidity-Temperature-Interface-Raspberry/dp/B07PFHM9HN/ref=sr_1_3?dchild=1&keywords=I2C+temperature&qid=1618258818&sr=8-3) Use case Cheers |
Alan Adams (2486) 1149 posts |
I wouldn’t say “demystify” for this, but it’s a starting point. https://www.riscosopen.org/wiki/documentation/show/IIC_Control The point being that you don’t use the GPIO module for it. You could, I think, but then you would be doing a lot of low level stuff yourself. You’ll see a reference to IIC_OP in there. It’s the more recent interface, but adds complexity that I think you don’t want for your usage. |
Steve Drain (222) 1620 posts |
You can avoid problems with pin numbers and blowing up your Pi by using an IIC port expander. This should be plenty quick enough anything in the classroom. There have been several add-ons using the MCP23017 chip, with two 8-bit ports, and they can be chained for more if you really need them. They are pretty cheap. There are others here who have done some elaborate things with them and in the early days I used the SliceOfPi. I have a very small BASIC library for controlling them and I also wrote a module to provide SWIs to do much the same thing. I hope they might be of use. |
Steve Pampling (1551) 8170 posts |
Ouch! Sorry, that would be “ouch, ouch” really :) |