OS_Claim (0x1F)
Rick Murray (539) 13840 posts |
1. This assembles as a MODULE (not an AIF). CODE REMOVED – CORRECTED VERSION FURTHER DOWN THE THREAD |
Rick Murray (539) 13840 posts |
Some observations from the original:
I’m guessing HAL_TimerDevice. This is rather unclear, isn’t it?
If you want a once per second tick, then &1000000 is not the way to do it. That’s 16,777,216 (or just under 17 seconds).
Your machine will stiff. You are trashing R8 and R9 and you are calling SWIs in IRQ mode without first having saved R14_svc (so SWI call will drop to SVC mode and corrupt whatever R14_svc was).
…and a lot of stuff incorrectly copied from Rik’s HALTimer module which will be trying to restore your machine to a state that you never set up (assuming it doesn’t crash before then, that is). Remember – the reason that people think assembler is scary is because there is zero leeway for errors. Anything that assembles is accepted, whether or not it actually works is an entirely different question! ;-) If you can, you might be better off using Rik’s HALTimer module, for two reasons. Firstly, somebody else has pulled their hair out on our behalf. We don’t need to do this, a solution already exists. To this end, unless I have an itch that needs scratching, I’m not going to spend time looking to see what is wrong with my module code. Me? I’d just use HALTimer… |
adrian (2547) 18 posts |
Hi Rick |
Rick Murray (539) 13840 posts |
Quick note – just noticed a bug.
That last line should be:
The first version I wrote only stacked R14. The code was updated to be correct (preserve R6-R9 as well) but this one was missed… in the unlikely event that RISC OS can’t find 32 bytes somewhere in the RMA… [the original has been corrected] Jeffrey: Just thinking aloud… After the MSRs to change mode (in the IRQ handler), should there be a NOP afterwards like old ARMs or is this no longer an issue? |
Dominic Plunkett (2554) 1 post |
Rick, I may be wrong, you are a better man than me but I think the stack goes all wrong at BL oh_crap_jumpin. Its been many years since I’ve done modules but I think you can leak the workspace if you fail to start in some places. If I’m wrong please forgive me. |
Steve Pampling (1551) 8170 posts |
That was the StrongARM bug was it not? instruction after the MSR actioned twice so stuff in a protective NOP Plenty of instances of no NOP littered through the CVS (not least the macros) |
Rick Murray (539) 13840 posts |
Yes. If you drop out at the point of failing to set the vector claim, it will not release the workspace claim. I thought about sorting that out, but since I was just making an example to see if it worked at all, I didn’t bother. It isn’t a finished or bug free module. ;-)
I was also thinking of the ARM2/3(+?) issue where TEQP and the like needed a NOP between changing mode and accessing banked registers. If you see from the code, the first mode change (IRQ→SVC) immediately stacks R14. Both R13 and R14 are private to SVC mode. After the second mode change (back to IRQ), the registers are retrieved from R13 (private to IRQ mode). |
Steve Pampling (1551) 8170 posts |
Definitely no expert but isn’t there some tidy up call that clears those things up?
Yes, sort of:
|
Rick Murray (539) 13840 posts |
I think a module, when it is quit, the OS can release claimed workspace automatically. I haven’t looked in the code so I don’t know if this happens when a module fails to initialise.
Yes – banked registers were not “safe” to access immediately after a mode change. Possibly a pipeline issue? I don’t know.
The question wasn’t referring to the presence of the HAL on older processors, the question was that as it was not safe to use banked registers immediately after a mode change on ARM2/3, and there was an issue with MSR on StrongARM – is it “okay” to do this on current ARMs or should a NOP be used still? |
Colin Ferris (399) 1814 posts |
Thanks Rick for the example code – still looking for what goes in R3/4 in OS_claimDeviceVector r0=13 expansion card interrupt – any ideas? Doing a bvs xxx if OS_Module 6 couldn’t claim any memory might be better – it’s a pity the assembler couldn’t give a warning if the stmfd and ldmfd don’t match. Also note that the GCC’s assembler/linker is near enough the same as ObjAsm – for use by one’s who can’t obtain ObjAsm for what ever reason. Might attract some younger potential coders :-) By the way what is the difference between TSTP PC,#0 and TEQP PC,#0 ? |
Rick Murray (539) 13840 posts |
https://www.riscosopen.org/wiki/documentation/show/OS_ClaimDeviceVector
BVS to where? If it can’t claim workspace, the only thing we can do is bomb out.
The RISC OS source uses “ENTRY” and “EXIT” (if I remember correctly). This was just an oversight as the original code only stacked R14.
I absolutely do not subscribe to that theory. I believe that a function should do what it is supposed to do and exit as soon as it has done all that it can.
TSTP will AND the value into the status register while TEQP will EOR the value (IIRC). This is old-style 26 bit stuff, probably ought to be forgotten these days. ;-) |
adrian (2547) 18 posts |
Hi Rick, 1º To claim some workspace you use OS_Memory. I’ve been reading the manual and OS_Memory doesn’t use R3 to claim memory. Could it be OS_Module instead? Do you claim 32 bytes for a specific reason? This is how I create my workspace: ; Let’s claim a workspace ; Workspace offsets ; &00 Counter Value of counter ; &04 TimerIRQ Device Identifier ; &08 Buffer Buffer for OS_ConvertCardinal4 ; OS_Module MOV R0, #6 ; Code of operation MOV R3, #16 ; Claim 16 bytes SWI “XOS_Module”2º Is there a way to use gcc to generate Modules in assembly rather than in C? I’m using BASIC for the moment, but gcc is better for me. |
Rick Murray (539) 13840 posts |
Gah! <epic embarrassed!> Maybe that’s why it doesn’t work? ;-)
Four bytes for the counter, four bytes for the IRQ number, and the rest as workspace for building the numerical string in ConvertCardinal. Can’t help re. GCC. But I’m kinda wishing right now that objasm had a dumbass filter to reject stupid code. :-P Like I said. Assembler is scary because anything that is a valid instruction will assemble. Whether or not it makes any sense is an entirely different thing………. |
adrian (2547) 18 posts |
Hi Rick, 1º I have adapted my code to BASIC. I load it and I see it in the list of ‘*MODULES’. 2º I’ve changed the BASIC file which generates the Module, but when I load it, I receive the same previous abort. Does ‘*RMKill’ delete the workspace like the Module or just the Module? How do I delete the Workspace? Thank you :) |
Rick Murray (539) 13840 posts |
No, A data abort, right? Check what R12 is pointing to. Did you push it back after the allocation at the beginning? [you did change that to OS_Module right? calling OS_Memory was an error] RMKill should release the workspace as it calls the module’s exit handler (the finalise entry). If not, RISC OS will deallocate the claim itself. Read PRM 1-209, Modules → Workspace. |
adrian (2547) 18 posts |
Ummm. I just load the Module that has been created, and use the * Counter. I’m checking if I need something else (*RMTidy, for example). If *RMKill deletes the workspace, there’s something weird happening to me. As soon as I loaded the first Module, I deleted it to change something of the code. Then I loaded another Module again, but it’s still generating the same error, in the same address. If I *MEMORYI that address, I see the code of the previous Module. |
Rick Murray (539) 13840 posts |
Yes, I noticed that. I think there is a bug in RISC OS that when a module messes up releasing itself, it becomes a sort of “zombie” and reloading a fixed module will revert to the original. There was a “%” in the title, so maybe RISC OS thought it was an incarnation dying, not the entire module itself? This bugged me (plus a large helping of embarrassment from mixing up OS_Module and OS_Memory – duh) so I thought I’d take another crack at it. This time:
In my defence, I put the original together in about 40 minutes. This time, I took a bit longer on the revisions, and more importantly, consumed two mugs of tea in the process. That’s the difference. ;-) It is running right now, results in a TaskWindow, via:
Okay then.
|
Steve Pampling (1551) 8170 posts |
Bit location specific. How about this on the top end? ; ( but it has been mostly rewritten! ;-) ) GET Hdr:ListOpts GET Hdr:SWIs Works happily with the DDE. |
Steve Pampling (1551) 8170 posts |
Oh rats, SWIs.h doesn’t have the OS_Hardware etc defs |
mary (2560) 1 post |
If the handler is in IRQ mode, why do you need to change to SVC mode? |
Rick Murray (539) 13840 posts |
Because we are calling SWIs in the IRQ handler. The reason we switch to SVC mode is to permit R14_svc to be preserved. If this is not done, the first SWI called would overwrite the version of R14 specific to SVC mode with the correct address for our return. Given that IRQs take precedence, it is quite possible that the system may be executing a SWI when the IRQ happens. As such, trashing R14_svc would be a really bad thing… |
adrian (2547) 18 posts |
Rick, |
Jeff Doggett (257) 234 posts |
Small quibble Rick, the comments say “at least 2 timers”
But the code is checking for Exactly two timers….. |
Rick Murray (539) 13840 posts |
Thanks. Fixed. |
Rick Murray (539) 13840 posts |
<facepalm> Is there any specific reason why you really don’t want to use the proper API and would prefer to do things behind RISC OS’s back? Won’t work anyway. Open a TaskWindow, then:
Where’s… anything? Shouldn’t there be data here? Issue the Hint! The addresses you are looking at in the documentation are the physical addresses. The address you see when you prod &20003000 within RISC OS is the logical address. I queried these addresses about two weeks ago. More than once. Please Google and take a quick refresher on what an MMU is and what it is for. Start with this. If you really want to poke around with the hardware timer, you can access it by mapping in some physical memory (it will not be at the address &20003000):
Issuing That said, I STRONGLY RECOMMEND YOU STICK TO THE PROPER API. |