heuristicjohn
Posts: 39
Joined: Thu Jan 31, 2013 11:55 pm

Interrupt servicing via BASIC ?

Mon Mar 11, 2013 12:50 pm

I would like to be able to call a BASIC/assembly language program in response to an interrupt input.
Setting up a GPIO pin is straightforward (BCM2835 handbook p90+ ), and applying an input duly results in the correct bit being set in the Event Detect Status Register.

After this it gets difficult. It says: "The interrupt controller can be programmed to interrupt the processor when any of the status bits are set ". How to do this ? - moving on to the Interrupt section (handbook p.109+) one finds a promising-looking IRQ 49, aka gpio_int(0), settable (probably) in Interrupt Enable Register 2; but how can this be related to the bit I have just set in the Event Detect Status Register ?

It gets worse. Looking at the operating system commands available, presumably OS_IntOff, OS_IntOn, OS_ClaimDeviceVector and OS_ReleaseDeviceVector are relevant, but what device number is appropriate ? (and what are podules ?).

This must be a fairly standard requirement, so guidance from the many people who have already sorted this out would be most welcome.

Markodius
Posts: 134
Joined: Fri Jan 04, 2013 11:14 pm

Re: Interrupt servicing via BASIC ?

Tue Mar 12, 2013 4:11 pm

Hi Heuristicjohn,

Is possible to periodically check the appropriate register and then code accordingly? I guess maybe not because you would have done that already?
“In the modern age, to call a man unelectable means he cannot be bought”

heuristicjohn
Posts: 39
Joined: Thu Jan 31, 2013 11:55 pm

Re: Interrupt servicing via BASIC ?

Thu Mar 14, 2013 12:54 pm

Markodius wrote:Hi Heuristicjohn,

Is possible to periodically check the appropriate register and then code accordingly? I guess maybe not because you would have done that already?
Hello Markodius ! Thanks for your comment. I have used this approach in the past, but it's a bit like having a sports car and only driving it in first gear - there is considerable room for improvement. The RPi-BASIC-assembler combination is very well suited to real time operation and direct hardware control, so it's a pity not to use all the facilities.

Deep in the riscosopen form I have found a suggestion that i/o pin 25 and the aux-int interrupt (29) are linked. I haven't been able to test this as my efforts to manipulate the interrupt registers are not working at present. I shall blunder on regardless. All contributions gratefully accepted.

Markodius
Posts: 134
Joined: Fri Jan 04, 2013 11:14 pm

Re: Interrupt servicing via BASIC ?

Thu Mar 14, 2013 5:06 pm

Ah yes I see what you are saying heuristicjohn.. It sounds like you know what you are doing 8-) so very probably you are already aware - there are limitations on coding within an interrupt. It is important that the code completes well before the next interrupt occurs - so it's important to avoid any kind of user input during it's run time and to be fairly concise. If it's appropriate I'd love to ask what are you creating?
“In the modern age, to call a man unelectable means he cannot be bought”

heuristicjohn
Posts: 39
Joined: Thu Jan 31, 2013 11:55 pm

Re: Interrupt servicing via BASIC ?

Sat Mar 16, 2013 12:57 pm

It sounds like you know what you are doing
Flattering, but if this were the case I'd be offering rather than seeking advice ! Yes, handling interrupts may be complex and require care (and knowledge), so let's find the documents which spell out the necessary steps, and start writing code (or maybe wait for Bruce Smith vol II ?). Solutions exist in raspbian/Python, so why not RISCOS.

For what it's worth, my current activities include a long-term obsession with measuring the ratio of two time periods (many applications in measurement), and generally dabbling with interfacing hardware to this marvellous RPi device.

theom
Posts: 73
Joined: Wed Jun 13, 2012 2:53 pm

Re: Interrupt servicing via BASIC ?

Sat Mar 16, 2013 9:35 pm

So you want to use interrupts. Here's the top level overview.

First, you need to be writing a relocatable module. The difficulty with code in application space (the area of memory that BASIC and normal compiled C programs run in, starting at &8000) is that applications are swapped in and out. So you can't guarantee that your code will be paged in when the interrupt happens - you might end up calling another app instead. This means that BASIC is out.

If you're writing C, you need to set up appropriate 'interrupt veneers'. These are entry points that set up the right registers (stack etc) to call the C functions themselves. This is done with the module header generator - either CMHG (Acorn/ROOL C) or CMunge (GCC). If you're writing assembler you don't need veneers.

Then you need to register the entrypoints to the veneers with the interrupt handler. This is indeed OS_ClaimDeviceVector. You also need something to OS_RemoveDeviceVector when you're done (eg in the module finalisation section if your module is killed).

And finally you need to know what device number your interrupt is at. In the old days, the manual told you. On all Acorn hardware podules (the cards that plugged into the back of your Archimedes or Risc PC) were interrupt 13, for example. Today we run on lots of different hardware, so we have to look up the device number. For this we use the HAL:
https://www.riscosopen.org/wiki/documen ... on%20Layer

First, see the HAL Device API section to find out what the device number of your chosen hardware is. Then use the device number with OS_ClaimDeviceVector. Finally use the HAL Interrupt API to enable interrupts on your chosen device. When you're done, turn off interrupts for it before removing the device vector.

Note that HAL_Something isn't a SWI, it's a HAL call. You can make HAL calls via the SWI OS_Hardware 0, but you can also get a pointer to the function to call directly (using OS_Hardware 1).

You don't want to use OS_IntOn or IntOff, because that kills interrupts for the whole system. If you do that all your USB, network, etc will jam up.

Hope that is enough of an overview to get started. As an aside, you might want to look at the HAL Timer API, as that might give you sufficient fine-grained timing to not need interrupts.

User avatar
DavidS
Posts: 4241
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Interrupt servicing via BASIC ?

Sun Mar 17, 2013 8:01 am

For interupt handling just stick with Assembly, it is easy, and there is no need for the work arounds needed by C. Also you can write the module source using the BASIC Assembler if you wish.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

AMcS
Posts: 184
Joined: Sun Jan 06, 2013 11:23 am
Location: Dublin, Ireland

Re: Interrupt servicing via BASIC ?

Sun Mar 17, 2013 9:29 am

Theo thanks for the comprehensive description (I had a sneaking suspicion the HAL would figure in it !).

heuristicjohn
Posts: 39
Joined: Thu Jan 31, 2013 11:55 pm

Re: Interrupt servicing via BASIC ?

Sun Mar 17, 2013 11:58 am

Theo - many thanks for your very helpful posting - exactly what I was looking for.

(to quote Gershwin) There may be troubles ahead ....

PS I understand that Bruce Smith Vol II will indeed cover this topic, so I have a fallback as well. Not that I'm a pessimist.

theom
Posts: 73
Joined: Wed Jun 13, 2012 2:53 pm

Re: Interrupt servicing via BASIC ?

Sun Mar 17, 2013 4:33 pm

I omitted to mention something else...

You don't have to write a relocatable module as such... you can write an interrupt handler in assembler and do the rest from BASIC. However it's a bit messy.

To do this, claim a block of memory from the RMA (using OS_Module 6). Assemble your interrupt service routine into that block. Once it's set up, call OS_ClaimDeviceVector with a pointer to your routine, and do all the HAL stuff as above.

The ISR cannot call any BASIC code, reference anything in BASIC's memory space, and is limited in the SWIs it can call (as is any ISR). In particular printing text will lock up your machine (no printf debugging here)

When you are finished you must remember to release the ISR and free the block (via OS_Module). The danger with this method is if your BASIC program gets stopped and goes away, and your ISR is still running. This isn't a catastrophe (the ISR is still there in an RMA block which is now memory leaked so won't get reallocated) but nothing will ever see the output of the ISR, you can't release it, and claiming the interrupt again may get you into trouble.

So it's not a very clean solution - OK for messing about, but not for a program you intend to give to other people.

Markodius
Posts: 134
Joined: Fri Jan 04, 2013 11:14 pm

Re: Interrupt servicing via BASIC ?

Mon Mar 18, 2013 12:24 am

I did believe that all devices under running under RISCOS were memory mapped - so one could peek the right addresses to determine hardware state? Is that a fallacious notion?

Is it not possible to write a timestamp to file and then terminate the ISR if not as predicted?
“In the modern age, to call a man unelectable means he cannot be bought”

theom
Posts: 73
Joined: Wed Jun 13, 2012 2:53 pm

Re: Interrupt servicing via BASIC ?

Mon Mar 18, 2013 2:15 am

I don't quite follow what you're trying to do but, yes, the devices are memory mapped. In supervisor mode or interrupt mode you can peek the relevant address to read state from them. (Except for devices that need more complex protocols - like things on the end of I2C buses).

File IO is another of those things that won't work in an ISR (because the ISR may well have interrupted an ongoing file operation). What you can do is write a log or similar to a block of memory, and then code outside the ISR (running in user or supervisor mode) reads the block, or writes it to disc, however you want. One way of getting around this is to call OS_AddCallBack in the ISR which will schedule a callback routine you pass it to be called when the processor is next in user mode.

So, for example, the ISR writes its log to a block of memory. It schedules a callback. Next time the CPU returns from a SWI in user mode (ie some time later) your callback gets invoked. This routine writes out the memory block to disc and updates the pointers. Because you can't control when (if ever) your callback will happen, the ISR needs to account for the situation when the memory block is filled because the callback hasn't happened yet. You also need to think about the concurrency issues - what if the ISR occurs which the callback is executing?

Markodius
Posts: 134
Joined: Fri Jan 04, 2013 11:14 pm

Re: Interrupt servicing via BASIC ?

Mon Mar 18, 2013 2:10 pm

Thanks Theom for meeting me at the shallow end of the pool. What I was principally attempting was to expose any progressable avenue that might prove useful to heuristicjohn and might otherwise have been overlooked - as well as clear up any misconceptions on my part concerning the way RISCOS deals with it's hardware. My own interest was RFID and the PI is a tempting platform on which to fashion a beacon due to it's stability, low power consumption and affordability as well as almost cost free UPS. However, so far it's all just as you said - too messy to be viable to industry or commerce. I'm no longer actively involved in RFID development and haven't been for quite a few years but it's still of interest.
“In the modern age, to call a man unelectable means he cannot be bought”

AMcS
Posts: 184
Joined: Sun Jan 06, 2013 11:23 am
Location: Dublin, Ireland

Re: Interrupt servicing via BASIC ?

Mon Mar 18, 2013 8:06 pm

Markodius wrote:Thanks Theom for meeting me at the shallow end of the pool. What I was principally attempting was to expose any progressable avenue that might prove useful to heuristicjohn and might otherwise have been overlooked - as well as clear up any misconceptions on my part concerning the way RISCOS deals with it's hardware. My own interest was RFID and the PI is a tempting platform on which to fashion a beacon due to it's stability, low power consumption and affordability as well as almost cost free UPS. However, so far it's all just as you said - too messy to be viable to industry or commerce. I'm no longer actively involved in RFID development and haven't been for quite a few years but it's still of interest.
Sorry Markodius, I don't follow - which is "too messy to be viable in industry or commerce"?

Is it specifically related to RFID - or just RISC OS hardware access in general ?

Markodius
Posts: 134
Joined: Fri Jan 04, 2013 11:14 pm

Re: Interrupt servicing via BASIC ?

Mon Mar 18, 2013 11:15 pm

AMcS wrote:
Markodius wrote: Sorry Markodius, I don't follow - which is "too messy to be viable in industry or commerce"?

Is it specifically related to RFID - or just RISC OS hardware access in general ?
More related to me really AMcS. Dropping to assembler always was 'last resort' to me - in fact these days I doubt that I could achieve anything useful at that level. Perhaps I should have written "Too disparate for me to mentally encompass". I should know from bitter experience that industry and commerce will buy just about anything and keep on buying it despite daily experience.

I am surprised that heuristicjohn's requirement seems so convoluted to adequately fulfil. But he doesn't seem daunted! 8-)
“In the modern age, to call a man unelectable means he cannot be bought”

AMcS
Posts: 184
Joined: Sun Jan 06, 2013 11:23 am
Location: Dublin, Ireland

Re: Interrupt servicing via BASIC ?

Mon Mar 18, 2013 11:49 pm

Markodius wrote:
AMcS wrote:
Markodius wrote: Sorry Markodius, I don't follow - which is "too messy to be viable in industry or commerce"?

Is it specifically related to RFID - or just RISC OS hardware access in general ?
More related to me really AMcS. Dropping to assembler always was 'last resort' to me - in fact these days I doubt that I could achieve anything useful at that level. Perhaps I should have written "Too disparate for me to mentally encompass". I should know from bitter experience that industry and commerce will buy just about anything and keep on buying it despite daily experience.

I am surprised that heuristicjohn's requirement seems so convoluted to adequately fulfil. But he doesn't seem daunted! 8-)
Dropping to assembler is the last for most people I'd think!

But when it's needed it's needed (mind you as assemblers go ARM is not bad - particularly as presented in the BBC BASIC inline assembler).

I believe he needs to use assembler precisely because he wants to handle GPIO using interrupts (this makes sense if you want to handle things as and when they're required rather than continually checking (polling) to see if a particular GPIO pin has become set).

Mind you it might be possible to "package up" some of the functionality into a module (or what not) in which case it might be easier for the next person ;)

theom
Posts: 73
Joined: Wed Jun 13, 2012 2:53 pm

Re: Interrupt servicing via BASIC ?

Tue Mar 19, 2013 1:31 pm

There's no reason to drop to assembler for this. C will handle it just fine. And it's not that complex to write either.

Historically, BASIC was people's primary 'scripting language' (if we can use the modern name), and C cost (lots of) money. BASIC comes with a builtin assembler, so if BASIC was insufficient people used assembler. Indeed, on Linux you can't write interrupt handlers in Python - it's a similar kind of situation.

Now GCC is free. It comes with all the tools you need. If you're starting 'serious' RISC OS programming and have programmed before I'd recommend going straight to C, there's no reason to learn BASIC as you'll find it limiting eventually.

If you like you can buy the formerly 'professional' Norcroft/ROOL C compiler, which arguably outputs slightly better code and is needed to build the OS ROMs (at the moment). Many RISC OS folks use it because they've had it since it was the only compiler in town and are used to it. But if you're starting out then just begin with GCC and get Norcroft if you hit the 10% of cases that need it.

dr_d_gee
Posts: 84
Joined: Fri Jan 04, 2013 1:30 pm

Re: Interrupt servicing via BASIC ?

Tue Mar 19, 2013 2:01 pm

Is there any reason why gcc still doesn't appear in the package lists in !PackMan on the Pi--it's obvious from comments elsewhere that people have used it successfully?

heuristicjohn
Posts: 39
Joined: Thu Jan 31, 2013 11:55 pm

Re: Interrupt servicing via BASIC ?

Tue Mar 19, 2013 6:36 pm

As AMcS says,
(this makes sense if you want to handle things as and when they're required
. Right on ! For simple I/O transactions, the BASIC assembler package allows you direct access to GPIO pins, so why use higher level languages with more abstraction and overheads ? Assembler is not portable (but that's not a problem here). It's fast (about 25 instructions per microsecond), and conceptually no more difficult than any other language. Also this implementation is an excellent vehicle for program development - if you crash the system, just reboot (10 seconds) and try again. All it needs is a decent interrupt handler (and when I finish my present hardware activity I shall lurch into action. Of course, if anyone else get there first .....)

theom
Posts: 73
Joined: Wed Jun 13, 2012 2:53 pm

Re: Interrupt servicing via BASIC ?

Tue Mar 19, 2013 11:41 pm

The reason I omitted GCC from the PackMan distro is because on my extra-slow SD card installing it thrashed the SD for hours. I haven't had a chance to investigate why - it's worse than installing it with the Filer. Obviously it's small-file writes on the SD which are very slow, but something else is making it worse.

However, I'm tempted to enable it temporarily and see how people get on. It might be most people's SD cards don't suffer from this problem.

heuristicjohn
Posts: 39
Joined: Thu Jan 31, 2013 11:55 pm

Re: Interrupt servicing via BASIC ?

Wed Jun 18, 2014 9:48 am

Back again ... can anyone point me towards a listing of actual working code for handling interrupts under RISCOS ? I gave up working on this one a year ago, having got nowhere, and have not found any references since then. On the bare metal forum, there are references to interrupt handing, but I would really like to be able to do this using RISCOS. Even the usually helpful Bruce Smith avoided this one; it does seem to be difficult, though whether this is a result of inadequate documentation or a flaw in RISCOS is unclear (to me). Have I overlooked the obvious ?

andycsmith
Posts: 1
Joined: Thu Aug 14, 2014 12:51 pm

Re: Interrupt servicing via BASIC ?

Tue Aug 19, 2014 9:02 pm

Just browsing the forums out of interest and came across you post.

You will definitely have to use Assembler/C, I remember doing this about 30 years ago on my Archimedes, I really liked using ARM assembler, never got the hang of C.

As far as I can remember most of the information was in the Programmers Reference Manual (PRM). I ditched mine a few years ago after finding them in a cupboard at my parents and not thinking that they would be of much use any more. RISC OS Open do have a access to parts of it and the bits that you need to look at are https://www.riscosopen.org/wiki/documen ... ow/Vectors, this also tells you which calls you need to use to trap a vector and some other information about handling vectors. Again from memory it is pretty straight forward although I tended to use software not hardware vectors but I think the logic is similar.

Not knowing a lot about the Pi your main problem may be identifying the vector you need to claim but hopefully this will give you a starting point.

Andy

Return to “RISCOS”