OS_IICOp
Dave Higton (1515) 3534 posts |
Two questions and a suggestion. The questions: HAL_IICTransfer can return IICSTATUS_INPROGRESS if background transfers are supported, hence it needs to be called repeatedly; but the documentation for OS_IICOp suggests that it doesn’t return until the transfer is completed. I take it, then, that OS_IICOp takes care of the repeated calling? And does that mean that the list of iic_transfers must always be placed by the caller in unpaged memory in case the hardware supports background transfers? The suggestion: add a function to OS_IICOp to return the number of IIC busses directly, to avoid having to descend to calling the HAL. Call OS_IICOp with R0 = -1 as this would be a daft thing to do for a real list of transfers; I don’t mind whether the return value is in R0 or R1. |
Jeffrey Lee (213) 6048 posts |
Yes.
I don’t think it would be possible for anything to mess with the memory map while a transfer is in progress, so it should be safe to have the transfer list in paged memory. The only dangerous thing I can think of would be to call OS_IICOp from an RTSupport routine, using transfer lists/data held on the SVC stack. Even though each routine has its own SVC stack, they all share the same logical address space, with RTSupport using the CPU to copy the stack for the active thread into that space. (This is done so the stack can be MB-aligned, as most/all C code needs a MB aligned SVC stack in order to store the C static relocation offsets)
Sounds sensible enough to me. Also plenty of scope for adding other negative reason codes in the future if necessary. |
WPB (1391) 352 posts |
So does OS_IICOp just spin while polling HAL_IICTransfer? Can someone tell me where the sources to OS_IICOp live? (I have looked on the CVS viewer, but only came up with IIC_OpV which is in an Attic directory of the kernel somewhere.) |
Dave Higton (1515) 3534 posts |
Then perhaps R0 = -1, R1 = reason code; return values in R2 upwards so the reason code is preserved across the call (this may make things marginally easier if multiple calls need sorting out – whether or not this is a realistic problem I don’t know, but anyway I can’t see why R2 upwards shouldn’t be used for return values).
I searched through the BCM2835 sources in my build directory last night, with equal lack of success. |
Jeffrey Lee (213) 6048 posts |
IIC_OpV (in Kernel.s.PMF.IIC) is correct. Remember that we’re using the HAL branch of the kernel, and by default the CVS viewer shows the trunk, so some files which are in use may appear deleted. |
Rick Murray (539) 13850 posts |
It’s dangerous to retrofit an existing API with new register behaviour. The only “safe” way would be to do it only when using a new call, not an old one. The problem here is that it could end up a tangle of code to determine who-does-what-when. Why, in fact, are we talking of hacks like -1 to IIC_Op to return hardware information? Is it alien to create a new SWI – like IIC_Enumerate or somesuch? To expand upon the first paragraph: Why do you think the OS mouse code doesn’t return the mouse scroll wheel activity in, say, R4? And additional information in R5 for things like “finger dragged” or “multitouch: this is point 1 of 3” or “pen pressure” etc etc? The reason is simple. Anything written on the understanding that OS_Mouse uses/corrupts R0-R3 may wind up going horribly wrong if you start corrupting other registers. |
Dave Higton (1515) 3534 posts |
I think you should have a look at the existing API first. This is SWI OS_IICOp we’re talking about. The current definition has a single purpose, and R0 on entry points to a list of iic_transfer structures. Perhaps you can see now why adding the proposed functionality is safe. |
Jeffrey Lee (213) 6048 posts |
We’re talking about OS_IICOp, not its predecessor IIC_Op. Not that that’s any reason not to add a new SWI if necessary. |
Rick Murray (539) 13850 posts |
<facepalm!> |
WPB (1391) 352 posts |
Thanks, Jeffrey. That’s something that had passed me by. Now it makes sense why it’s in the Attic. I had a bit of a look through the source. I found the spin where the SWI code waits for the HAL to complete, though it surprised me a bit. It seems that the kernel code just reads IICBus_Status directly from memory, rather than repeatedly calling into HAL_IICTransfer. I suppose that’s for speed? Could this spin not take quite a lot of time? I think IRQs are on, so presumably that means other background processing can be ongoing (IRQs, FIQs, RTSupport routines, not sure about callbacks), but it basically means the SWI OS_IICOp blocks until completion of the entire transfer, doesn’t it? Then I noticed something else which doesn’t make sense to me. I’m sure I’m just not following the logic right, but I can’t see how the ROR at line 281 below results in it being the “transfers remaining” (comment on line 283) being stacked. Doesn’t the ROR essentially switch the number of transfers into the three high bytes, and the bus number into the low byte? 270: ; IICDoOp – main serial-execution entry point Apologies in advance if the above questions/queries are blindingly obvious to some, but this stuff is stretching me a bit ;) |
Jeffrey Lee (213) 6048 posts |
Yes, the spin could take a long time, yes IRQs are on, yes OS_IICOp blocks until completion.
Documentation error; should be “Move bus number to low byte”. On line 286 you’ll see it masks R1 with 255 to get the bus number, and on line 298 it deals with decreasing the transfer count (using the count that was pushed to the stack since R1 will have been corrupted by then). Plus it looks like there’s a couple of other bits where it does LDRB xx,[iicsp] to get the bus number. |
Jeffrey Lee (213) 6048 posts |
The loop around line 850? That’s for IRQ-driven transfers, where IICBus_Status will be updated by the IRQ handler (See IICIRQ). So it needs to start a transfer via HAL_IICTransfer and then wait for the IRQ-driver HAL_IICMonitorTransfer to say that it’s done. One day I might stick a call to Portable_Idle in there, although there is the warning down at line 401 of the code needing to work OK before the SWI despatcher is initialised. |
WPB (1391) 352 posts |
Thanks for fixing that!
Yes, that’s what I’d assumed was doing the “repeated calling” that Dave asks about at the top of the thread. I can’t see anything else that calls the HAL in this way. Does anyone here have experience of IIC APIs on other OSes? I was wondering if there’s a need for non-blocking calls, seeing as IIC can be quite slow. I suppose OS_IICOp’s API could be extended to provide both variants, a bit like SDIODriver does. |
Steve Drain (222) 1620 posts |
I have fitted a Ciseco Slice-of-Pi/O to my RPi. This has an MCP23017 16-Bit I/O Expander working off the IIC bus. I have been trying to work out how to communicate with it using OS_IICOp. I think I have got the addressing ok, but beyond that I have not been able to tie-in the transfer list to the data sheet information. A pointer to an introduction to using IIC or a little hand-holding would be most welcome. |
Steve Drain (222) 1620 posts |
I did work out how to use the IIC bus and I have written a module to present the 2 ports of the Ciseco SliceOfPI/O through a SWI interface. I have written a demo program to allow the configuration and the in/out to be played around with. These seem stable, but they are still very much experimental. If anyone is interested I shall be at the London show in the Pi room. |
Tank (53) 375 posts |
Steve, see here ….. |
Steve Drain (222) 1620 posts |
Yes. I downloaded your program and read your source, which helped me sort out the IIC. But as far as I could tell your SWIs only allow 1 bit at a time to be set. I did not know how to contact you. In any case, I wanted to provide full configuration and 8-bit port manipulation, and I do not think I could do that with the GPIO module. I would be interested in doing the same with the 8 bits of the GPIO port as well, because they are brought out to an 8-pin header on the SliceOfPI/O and the even cheaper SliceOfPi. I have just done a check with my new revision 2 Pi and GPIO does not seem to reconise the IO chip. This is with module version 0.43 06 Oct 2012. Could this be to do with the different bus numbers? This has been corrected in recent versions of the OS, but it caught me out for a while. |