Closed pottendo closed 7 months ago
Thanks. I tried it, but I don't think, this should become a Circle sample, because accessing GPIO pins is already shown in other samples.
Please branch off from develop for eventual further PRs. Merging to master is only done for releases (see CONTRIBUTING.md for the branching model).
I cherry-picked your commits from the master branch, moved your code from sample/ to the test/ section, did some small modifications and merged it to develop. I think, this is the right place for this tool. Thanks again for this contribution!
Great. Thanks for the feedback. I may add some more functions to test the comparison to direct register access and maybe other functions (for Pis which are supported). Bye, pottendo
There is a way to access the GPIO pins much quicker on the RPi 5 using the RIO module. How it seems, with this you can write all GPIO pins at once or set their mode at once and read them at once in in less than 200µs for each operation. I'm still researching this to provide an improved class CGPIOPin.
Good news indeed! Does this also allow somehow to switch direction of the I/O.? Thanks for investing more time into this. I hope that it's not only my use case to drive this! Bye pottendo
You are welcome. Yes, there will be a method SetModeAll(u32 InputMask, u32 OutputMask). The GPIO pins are set to input, for which the respective bit in InputMask is set. The same for OutputMask (set to output). How it seems, this takes about 125µs, when both masks are != 0. It's always good to have a use case to make something new. I guess, there will be more users for this sooner or later. I'm still working on it.
The update is on the develop branch. There are the following new methods in CGPIOPin
:
static void SetModeAll (u32 nInputMask, u32 nOutputMask);
static void WriteAll (u32 nValue, u32 nMask);
static u32 ReadAll (void);
The first is only available on the RPi 5 and is described in include/circle/gpiopin2712.h. The other methods were already available for RPi 1-4 and are described in include/circle/gpiopin.h. The old SetMode()
and Write()
methods also need less time now. Please let me know, if it works for you.
Thanks, even more good news! Will test, but not before tomorrow... I think SetModeAll could be easily done for all Pi versions to be API compatible... my app does it basically (see first post in the discussion). But probably you're planning this already. Let's see if my app gets happier wit this improvement. Thx pottendo
If it helps, I can implement SetModeAll()
for earlier RPi versions, but it requires up to 8 register accesses to be accomplished there (only 2 on the RPi 5). So the timing will be different. I should do it anyway to have to same API.
CGPIOPin::SetModeAll()
is implemented for RPi 1-5 on the develop branch now.
Hi, here some results: Pi5 & Pi3
logger: Circle 46 started on Raspberry Pi 5 4GB (AArch64)
logger: Revision code is c04170, compiler has been GCC 12.2.1
00:00:00.13 timer: SpeedFactor is 7.69
00:00:00.13 kernel: timing of GPIOs on Raspberry Pi 5
00:00:00.14 kernel: maxed freq to 2400MHz
00:00:00.14 kernel: Temp 30C (max=85C), dynamic adaption possible, current freq = 2400MHz (max=2400MHz)
00:00:00.15 kernel: loop 1 -------------------------------------------------
00:00:00.16 kernel: LED on , 1000 loops: 1074us, 1.074us avg.
00:00:00.19 kernel: LED off , 1000 loops: 1073us, 1.072us avg.
00:00:00.21 kernel: SetMode(Out), 1000 loops: 105us, 0.104us avg.
00:00:00.23 kernel: Write(H) , 1000 loops: 103us, 0.103us avg.
00:00:00.25 kernel: WriteAll(H) , 1000 loops: 102us, 0.101us avg.
00:00:00.28 kernel: Write(L) , 1000 loops: 103us, 0.103us avg.
00:00:00.30 kernel: WriteAll(L) , 1000 loops: 102us, 0.101us avg.
00:00:00.32 kernel: SetMode(In) , 1000 loops: 105us, 0.104us avg.
00:00:00.35 kernel: Read() , 1000 loops: 194us, 0.194us avg.
00:00:00.37 kernel: ReadAll() , 1000 loops: 152us, 0.151us avg.
00:00:00.39 kernel: SetModeAll(Out), 1000 loops: 102us, 0.101us avg.
00:00:00.42 kernel: SetModeAll(In), 1000 loops: 102us, 0.101us avg.
logger: Circle 46 started on Raspberry Pi 3 Model B+ 1GB
logger: Revision code is a020d3, compiler has been GCC 12.2.1
00:00:00.30 timer: SpeedFactor is 3.33
00:00:00.30 kernel: timing of GPIOs on Raspberry Pi 3 Model B+
00:00:00.31 kernel: maxed freq to 1300MHz
00:00:00.31 kernel: Temp 32C (max=85C), dynamic adaption not possible, current freq = 1300MHz (max=1300MHz)
00:00:00.32 kernel: loop 1 -------------------------------------------------
00:00:00.33 kernel: LED on , 1000 loops: 018us, 0.017us avg.
00:00:00.36 kernel: LED off , 1000 loops: 019us, 0.018us avg.
00:00:00.38 kernel: SetMode(Out), 1000 loops: 161us, 0.160us avg.
00:00:00.40 kernel: Write(H) , 1000 loops: 014us, 0.014us avg.
00:00:00.43 kernel: WriteAll(H) , 1000 loops: 010us, 0.009us avg.
00:00:00.45 kernel: Write(L) , 1000 loops: 013us, 0.013us avg.
00:00:00.48 kernel: WriteAll(L) , 1000 loops: 010us, 0.009us avg.
00:00:00.50 kernel: SetMode(In) , 1000 loops: 161us, 0.160us avg.
00:00:00.53 kernel: Read() , 1000 loops: 067us, 0.067us avg.
00:00:00.55 kernel: ReadAll() , 1000 loops: 057us, 0.057us avg.
the Pi3 doesn't like:
u32 i, o; i = 0xffffffff, o=0x0; (void)CGPIOPin::SetModeAll(i, o);
and crashes.
Probably wrong masks?
bye, pottendo
PS: Pi4 doesn't build currently:
i2cmasterirq.cpp:169:41: error: 'ARM_IRQ_I2C' was not declared in this scope; did you mean 'ARM_IRQ_USB'?
169 | m_pInterruptSystem->ConnectIRQ (ARM_IRQ_I2C, InterruptStub, this);
| ^~~~~~~~~~~
Be careful with modifying the mode of GPIO pins 0-1 and 28-31. They have a special function in the system and shouldn't be changed. The RPi 4 build error has been fixed on the develop branch.
Ok, fixed the tests now to run on all PIs (I've tested) - should be in my dev-branch to be updated on your side (if you like). I'll post the results in the discussion - probably better to be found be others.
Hi @rsta2, thought this may be useful for you. bye, pottendo