Raspberry Pi 4 GPIO
Pages: 1 2
Dave Higton (1515) 3526 posts |
I took on the job of updating the RasPi 4 HAL so that the GPIO pull-ups and pull-downs would work. After several rewrites, I have some neat and elegant code; the problem being that it doesn’t work yet. So far, so normal. I don’t understand the role of register sb (R9) in the HAL code. AFAIUI, all the workspace for the HAL code is accessed relative to sb, but in some (but not all) cases sb is loaded from a workspace location. But where does sb get its initial value from? I need to work out what functions need me to get a value of sb from somewhere. In some cases it’s loaded from a member of a structure whose address is passed in a1. I’d like to be able to find it programmatically so that I can call some bits of code from BASIC assembler. When HAL code is called from a RISC OS SWI, at what point does sb get loaded with a suitable value? I’m also interested to learn debugging methods that will work in the HAL. Unless I hear of a better method, I’m about to put in some code to save some values in a DA that I can create in BASIC and search for in assembler in the HAL, assuming I can call OS_DynamicArea SWIs from the HAL without something blowing up. |
Colin (478) 2433 posts |
When the hal is initialised a block of memory is allocated it for static variables and sb is used to reference the data there, in the same way that all the static data in a module is referenced relative to the private word (r12) |
Dave Higton (1515) 3526 posts |
What OS_Hardware call do I use to refer to GPIO functions? |
Jeffrey Lee (213) 6048 posts |
The reason why some code loads sb from workspace and some code doesn’t is because there are two inconsistent ABIs in use. The main HAL entry points (the routines available via OS_Hardware 0/1) all require the caller to provide the sb value on entry. “HAL devices”, like the GPIO HAL device, use an APCS-compatible ABI, which means that sb / R9 is undefined on entry. So HAL device calls which need access to the HAL’s static workspace must load the SB value from a private location in the HAL device struct (all the HAL device calls receive the device struct pointer in a1 on entry)
I think most people just use the serial port for debug output from the HAL. Calling SWIs from the HAL is technically forbidden (the HAL is intended to be OS-agnostic), but for debugging/testing it’s fine. You just need to be aware of when the code is being called, so that you don’t call a SWI at an invalid time (e.g. trying to call a SWI before the MMU is enabled would be bad). HAL devices are initialised after the initial dynamic areas are initialised, so calling OS_DynamicArea should be possible. |
Colin (478) 2433 posts |
I was going to point you toward sources.HWSupport.GPIO.c.gpio So you could see how it accesses the device but when I look a the ROOL gitlab version it is different – it’s in assembler |
Dave Higton (1515) 3526 posts |
(Apologies if anyone read the previous contents of this post – I provided some misinformation. I’m looking again at my findings.) |
Jeffrey Lee (213) 6048 posts |
To answer a little bit of it (the bits I can remember now that I’ve refreshed the page!)
|
Dave Higton (1515) 3526 posts |
I now have some signs of life – I can swap GPIO4 between pull up and pull down. Curiously, once I disable the pull, I can’t re-enable it. But that’s only a matter of keeping looking. Thanks for the macro, Jeffrey. HI or LS according to which I branch for. The DA method works – nothing goes bang and I can store lots of values for subsequent examination. The assembly language to find the DA turned out to be very easy – also returns 0 and EQ if I forget to create the DA :-) |
Dave Higton (1515) 3526 posts |
Well, I appear to have achieved the impossible. The ROM I build works correctly on a RasPi 3B+, but the same ROM and the same test code on the RasPi 4 will swap GPIO17 between pull up and pull down, and pull off, but one the pulls are off, it won’t enable them again in either direction. The really impossible bit is that I can show, with diagnostics, that a2 and a3 on entry to GPIOPullControl have the value &FFFDBFFF. Anyone who studies the GPIO module will see that those values can only ever have one or no bits set. This is right at the entry to the function, before any test and branch to platform-specific code. I’ve completely removed the diagnostic code in case it was causing the malfunction. Now I can no longer see the values on entry, but the symptoms are unchanged. I don’t know where to go from here. |
Colin (478) 2433 posts |
You are in real trouble if after pressing send you haven’t come up with a solution. My first port of call is to turn to my wife and say ‘its impossible this’ she says ‘you always say that’ and that can trigger a solution. When that fails I post here just like you have and the moment I press send an idea comes to me. If it doesn’t work thats the end of that project – I’ve got a pile of them. |
Dave Higton (1515) 3526 posts |
I know what you mean… These HAL GPIO functions are called from relocatable modules, but many functions (not only those I’ve changed) modify R12 without stacking and restoring it. Isn’t that doomed to failure? If not, why not? It was my understanding that R12 points to the module’s workspace, so, if the module calls out to the HAL which then corrupts the workspace pointer, all sorts of bad might happen. I’m sure you can get away with it if one SWI calls one HAL function, but setting the pull resistors requires several HAL calls per SWI. Maybe the module stacks R12 around calls to the HAL, I don’t know. |
Jeffrey Lee (213) 6048 posts |
This. And also on the same page, “If an assembler device driver module is using a lot of device calls, it might be preferable to move the workspace pointer from the traditional R12 to R11.” |
Dave Higton (1515) 3526 posts |
Let me make sure I know which foot the boot is on (as it were). It’s the callING code, not the callED code, that preserves the registers. So something, somewhere, behind the example C statement (and well enough hidden that I haven’t found it) preserves R4-R11, so that the called code in the HAL can do what it likes with R4-R11? |
Rick Murray (539) 13840 posts |
Info: https://www.riscosopen.org/wiki/documentation/show/HAL%20calling%20standards Generally speaking, it’s the duty of the function being called to preserve none/some/all of R4-R11, depending on what registers (if any) it needs for itself. This is typically an STMFD at function entry to stack those registers that need preserved, and R14; which can be then unstacked (and return pushed into PC) on exit. |
Dave Higton (1515) 3526 posts |
I think it’s working. |
Dave Higton (1515) 3526 posts |
I’ve got the code tested and working to my satisfaction. Two files are affected: hdr.BCM2835 and s.GPIO. The former is dead easy; I’ve added 4 equates for the offsets to the new registers. The latter is possibly a problem, though. I’ve added quite a lot of code, so it’s really beyond what I could reasonably do with the web interface. So I installed the new RISC OS git client and cloned the HAL_BCM2835 stuff. So far, so good. But when I looked at s.GPIO, someone else has added a lot of other stuff while I’ve been doing my bit. (I think it must be to support another model of RPi.) I also noticed that my changes of a few weeks ago are not in the repo. Perhaps that doesn’t matter, since they are of course in my current file. So how does the merge happen? Is this an automatic or a human process? If I submit this change successfully via git, does it automatically get assigned to ROOL for review and submission? (I failed on my use of the web client for previous changes; I didn’t set the assignee.) |
Dave Higton (1515) 3526 posts |
(Btw I found what was causing the strange failures documented a few postings back. I had used v3 instead of a3 in one instruction. All too easy to do in assembly language. I must have seen the error countless times without noticing it.) |
Jeffrey Lee (213) 6048 posts |
There were some changes to fix Pi 4-only pins accidentally being reported as being available on earlier models. The commit view of the web interface is a good way of seeing what’s been going on. https://gitlab.riscosopen.org/RiscOS/Sources/HAL/HAL_BCM2835/-/commits/master
Your fix for ticket #490 is definitely there.
Automatic, assuming you start from the right commit. Assuming you started development using version 0.88 of the sources: # Go back in time git checkout HAL_BCM2835-0_88 # Start a new branch git checkout -b Pi4GPIO # Now make and commit your changes ... # Rebase the branch to merge in the newer changes that other people have made git rebase master Unfortunately, git 1.0.0 lacks the support for two of the three above commands, so you won’t be able to use that. If you don’t have access to a full version of git, sgit will work. Starting from a fresh install: | Set your name & email address so your commits will be attributed to you: sgit config --global user.name "Dave Higton" sgit config --global user.email some@email.com | Make sure suffix swapping is disabled (ROOL repos are already using RISC OS format file names). | This setting isn't saved, so you'll need to remember to reset it after reboots, etc. set UnixEnv$sgit$sfix "" | Clone the repo sgit clone https://gitlab.riscosopen.org/RiscOS/Sources/HAL/HAL_BCM2835.git HAL_BCM2835 dir HAL_BCM2835 | Go back in time sgit checkout HAL_BCM2835-0_88 | Start a new branch sgit branch Pi4GPIO sgit checkout Pi4GPIO | Now make your changes ... | Commit your changes. | Unfortunately '-m' is the only way of supplying commit messages, so I think it'll have to be a one-line message. sgit add -A sgit commit -m "Update GPIO pull-up/down code to support Pi 4" | Rebase the branch to merge in the newer changes that other people have made sgit rebase master | Add your fork as a remote sgit remote add myfork https://gitlab.riscosopen.org/dhigton/HAL_BCM2835.git | Push your changes to your fork. It'll ask for your username & password for ROOL's git server. sgit push myfork Pi4GPIO | Now go to the web interface and create the merge request The above steps worked for my super-important changes, so it should work for you as well.
Unfortunately not, you need to manually assign each merge request to ROOL. And annoyingly, you’re only allowed to assign them to ROOL if you’re a member of the RiscOS group, which it doesn’t look like you are, so you’ll either have to email ROOL and ask them to add you, or post here on the forums and I can assign the merge request to ROOL once you’ve created it. |
Dave Higton (1515) 3526 posts |
Many thanks for your comprehensive response, Jeffrey. I must correct one thing that I said: yes, my previous change is there. I had mis-remembered the change (I had the “from” and “to” swapped in my mind). It’s a pity I can’t do it all using RISC OS, but I do have a Linux box next to me. |
Dave Higton (1515) 3526 posts |
I’ve emailed code@ to request admission to the RiscOS gitlab group, so, one way or the other, it will be possible to assign the changes as necessary. |
Dave Higton (1515) 3526 posts |
My membership has been granted. |
Rick Murray (539) 13840 posts |
🎉🍾 |
Dave Higton (1515) 3526 posts |
Oops, must look more carefully, sgit as linked above is for RISC OS… |
Dave Higton (1515) 3526 posts |
In response to the sgit commit command, I get: Author information not properly configured! I take it this means that the commit has failed, not that it has succeeded but needs some separate update? I can’t see anywhere in the sgit help anything about setting author or committer info, which clearly must be different from user info, which is set. Btw I was happy enough in the end to edit my changes into the current version, so I didn’t need to check out a historical version. |
Jeffrey Lee (213) 6048 posts |
Hmm, I’ve never encountered that before. Maybe double-check that the user info was actually set correctly? !Boot.Choices./gitconfig should be like this: [user] name = Jeffrey Lee email = some@email.com
“sgit status” will tell you if there are any files which haven’t been committed. |
Pages: 1 2