SietseAchterop
Posts: 13
Joined: Fri Mar 06, 2020 12:39 pm

Using the system timer interrupt at 1MHz

Fri Mar 06, 2020 1:11 pm

Hello List,

As far as I understand the BCM2835 documentation, the system timer has 4 channels that can generate interrupts at a rate of 1MHz.
Two are used in the GPU, and the others can be used by the CPU.
I want to use one of them to control a 16 bit ADC chip with SPI, being a MCP33131.
I already have the code running in a loop on an RPI Zero, and the rate is a little bit better than 500kHz.
To control the ADC I have to create a conversion/CS pulse of 700nsec and then the read/writing of 2 bytes to get the data and write it
into a buffer.
The idea is to toggle the CS-line every 1usec, and do the I/O stuff after the negative edge. That should work.

I created a "hat" for the rpi with the ADC including a pre-amplifier and low pass filter. It is going to be used as a software defined radio,
also to record bat-sounds. I hope to get it working to frequencies up to 200kHz.

The question is how to setup one of these interrupts to do that.
Is one of these interrupts used for the linux system clock? But then the other interrupt should be available.
I looked quite extensively on the net, but found not much useful stuff.
Hopefully someone can point me in the right direction.

Thanks in advance,
Sietse

PS. If this does not work, I will have to go bare-metal, but that is a bit of a problem since I need to use wifi or bt to get the (reduced) data from
the RPi and I understand that still is not working on bare metal.

LdB
Posts: 1476
Joined: Wed Dec 07, 2016 2:29 pm

Re: Using the system timer interrupt at 1MHz

Fri Mar 06, 2020 4:02 pm

On linux there is no point you can't run 1uS interrupt rate you will struggle with that rate even in baremetal.
Tightloop or fancy DMA is the only way you are going to do that rate on a Raspberry Pi.
You are basically building a storage scope and you need real hardware :-)

What you are wanting to do is trivial on an FPGA or DSP you might want to think about getting a cheap dev board (cheaper than the Pi) and learning.

Bitscope is probably a typical example of that they have FPGA/DSP probe and the Pi to do the display
http://www.bitscope.com/product/BS05/

Basically your hat should have been a little more complex than what it is and you would have a fighting chance.

SietseAchterop
Posts: 13
Joined: Fri Mar 06, 2020 12:39 pm

Re: Using the system timer interrupt at 1MHz

Fri Mar 06, 2020 6:23 pm

Thanks for your reply!
I understand what you're saying, but I believe it is, barely, possible.
Given an interrupt each microsecond which consumes less then half the processing cycles leaves us with an Rpi with half
the capacity, so a 500MHz RPi zero. That is still quite capable.
The data left in the interrupt routine can be picked up in a kernel module where some data reduction occurs. A user program than
connects to the module. I agree, a challenge, but that was the idea of the project ;) .

But the question was, how to use one of the channels of the system timer.
I am hoping someone has experience on how to change the interrupt table and connecting an interrupt routine to it.
It really should be possible to have something simple as toggling a gpio in that routine, and then I can start from there.
I will also take a look at the CPU documentation to find out about it.

Thanks again,
Sietse

LdB
Posts: 1476
Joined: Wed Dec 07, 2016 2:29 pm

Re: Using the system timer interrupt at 1MHz

Sat Mar 07, 2020 5:16 am

The baremetal version for generating the IRQ is about 10 post back.

In linux you are wasting your time it isn't possible because linux has it own needs for the IRQ system and on the Raspberry Pi it has heavy interrupt sharing as there is only one IRQ signal. Essentially linux installs its own interrupt system and there is no way it is going to give access to do whatever you want. You have to politely ask linux to install an interrupt handler and it goes into the system as whole. Up to you if you want to waste your time.

The only real possibility you have is if the Raspberry Pi linux kernel doesn't hook the FIQ. On some linux distros the FIQ is free and then you can install your own handler and play merry hell. You could also conceivably crash the hell out of linux doing it because the FIQ has a higher priority than the IRQ and you could starve the scheduler and it blow up. That is probably your only bet from inside linux but dangerous.

Anyhow given you my 2 cents, go and play.

User avatar
joan
Posts: 14747
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Using the system timer interrupt at 1MHz

Sat Mar 07, 2020 9:23 am

Given you have enough time you could busy poll on the system timer microsecond transitions.

jayben
Posts: 22
Joined: Mon Aug 19, 2019 9:56 pm

Re: Using the system timer interrupt at 1MHz

Mon Mar 09, 2020 5:54 pm

I agree that if you are thinking of bare-metal, interrupts are an unnecessary complication; since this is an SPI device, just arrange the clock rate so you get a sample at the required time, then just poll for the FIFO non-empty, toggle CNVST, then get the next sample, and so on. There will be a small amount of timing jitter due to the polling, but I suspect you'd see very similar jitter if you used interrupts.

How you can get access to the data you've collected; that's another issue...

If you want to run Linux, then DMA is the way to go; getting the SPI sample and toggling CNVST will require some tricky coding of the DMA descriptors, but there are plenty of examples around.

SietseAchterop
Posts: 13
Joined: Fri Mar 06, 2020 12:39 pm

Re: Using the system timer interrupt at 1MHz

Mon Mar 23, 2020 4:16 pm

Thanks for al the replies.
I found an example that does more or less what i want.
It uses the fiq, but not the system timer:
https://bootlin.com/blog/fiq-handlers-i ... ux-kernel/

I still think it is doable. I cannot use DMA because I have to generate the CS-pulse for the SPI-ADC.

I still have my initial question. How to select the system timer number 1 to use as an interrupt, normal or as fiq?
There is a "request_irq" function but it is unclear how to use it.
The device tree contains the interrupt description in bcm2835-common.dtsi.
Can someone point me in the right direction?
Thanks again, SIetse

cleverca22
Posts: 323
Joined: Sat Aug 18, 2012 2:33 pm

Re: Using the system timer interrupt at 1MHz

Tue Mar 24, 2020 6:16 pm

it would be a bit more complicated, and well into undocumented territory, but the VPU side of the rpi has a full IRQ vector table, and all 4 timer channels have their own irq vector, no sharing

in theory, you could take one of the timer channels the VPU never uses, and then use it for a custom VPU interrupt vector

you would need to write some VPU code (either assembly or c), and compile/link it for whatever address your loading it at (physical ram address)

then fill in the right irq vector slot, unmask it on the vpu side, and begin setting the compare channel to trigger interrupts

i have done some very crude testing on my rpi4, and was able to bit-bang a 50mhz square wave out the gpio, so generating a complex wave-form, that starts on the edge of a 1mhz clock (via the timer channel) would be fairly plausible

main problem, is just not breaking the closed firmware, and the lack of debug options for the VPU


a second route, is to just fully switch over to the rpi-open-firmware side, you will loose all video outputs (they dont work yet), but then have a much simpler time writing custom VPU code to meet your needs

SietseAchterop
Posts: 13
Joined: Fri Mar 06, 2020 12:39 pm

Re: Using the system timer interrupt at 1MHz

Thu Mar 26, 2020 3:15 pm

Thanks for the reply!
But I am confused. I have seen, not tried though, a number of examples that use systems timer 1.
Notably the blink07 example from https://github.com/dwelch67/raspberrypi
That directly uses the system timer #1.
Several people describe that it works; it is as described in the BCM2835-periphiral document.
Or am I missing something?

Thanks again,
Sietse

PS. Interesting stuff, rpi-open-firmware. But I do not read anything about Wifi/bluetooth, and I would need that.
If that was available under bare-metal, I would have chosen that route in the first place. But for the moment I stubbornly
attempt it in this way ;)

LdB
Posts: 1476
Joined: Wed Dec 07, 2016 2:29 pm

Re: Using the system timer interrupt at 1MHz

Fri Mar 27, 2020 2:06 am

He is talking about the VC graphics processor which is a Video Processor Unit (VPU) you are talking about the ARM processor (CPU).
So he is taking the IRQ on the graphics processor, the blink7 code takes IRQ on CPU.
Now go back and read what he said again.

If you had used the external hardware help you would be finished by now ... just saying :-)

SietseAchterop
Posts: 13
Joined: Fri Mar 06, 2020 12:39 pm

Re: Using the system timer interrupt at 1MHz

Fri Mar 27, 2020 8:42 am

Sorry to persist, but I don't understand this.
I know about the 2 processors, but the blink7 code does get the system timer #1 interrupt, does it not?
If not, which interrupt is it getting and controlling?
If so, then the VPU does not come into it.
So again, what am I missing?

I don't understand what external hardware has to to with it, where talking software here.

Thanks, Sietse

LdB
Posts: 1476
Joined: Wed Dec 07, 2016 2:29 pm

Re: Using the system timer interrupt at 1MHz

Fri Mar 27, 2020 1:36 pm

All the interrupts go to the GPU and then to the CPU cores coming thru a matrix switch covered by the QA7 document
https://www.raspberrypi.org/documentati ... rev3.4.pdf
Note the figure under 3.2 on page 4
So the IRQ's are all available at the GPU and on a Pi2,Pi3, Pi4 you can route it to a particular core.

The blink7 example is setup specifically to work on core0 which is the default route matching a single core Pi1.
However we can take the interrupt on the GPU ( as per above) or we can simply re-routing the interrupt to another core.
Doing either and the blink7 code stops working even if you set it up and it's code is irrelevant.
The hardware is more fundemental than the software and you can't ignore it.

Now with linux on a multicore Pi, I have not looked but it is traditional on multicore linux systems to use balance irq's
https://linux.die.net/man/1/irqbalance

So blink7 is just a baremetal code implementation there is nothing significant or fundamental about it especially under linux. More specifically the blink7 code can not be used under linux because the linux interrupt handler is very different.

As I said earlier under linux the FIQ may be free (you found an example) but the IRQ will be routed and probably the hardware in use. So there is nothing in this area that is going to help you with linux. You need to look at the specific linux IRQ implementation under Raspbian or whatever version of linux you are going to use and ask questions in a linux forum.

So where you should go for answers depends on one simple question are you going to use linux or baremetal?

cleverca22
Posts: 323
Joined: Sat Aug 18, 2012 2:33 pm

Re: Using the system timer interrupt at 1MHz

Sat Mar 28, 2020 4:30 am

https://github.com/librerpi/rpi-open-fi ... .c#L37-L40

on the VPU side, the IRQ vector table is an array of 128 function pointers
slots 64-127 are the 64 IRQ's that are described in the official docs, but without the whole matrix mess

Code: Select all

 278    #define INTERRUPT_TIMER0               (INTERRUPT_HW_OFFSET + 0 )                                                                                                                                                                                                              
 279    #define INTERRUPT_TIMER1               (INTERRUPT_HW_OFFSET + 1 )                                                                                                                                                                                                              
 280    #define INTERRUPT_TIMER2               (INTERRUPT_HW_OFFSET + 2 )                                                                                                                                                                                                              
 281    #define INTERRUPT_TIMER3               (INTERRUPT_HW_OFFSET + 3 )                                                                                                                                                                                                              
and all 4 timer compare channels have their own IRQ's

https://github.com/raspberrypi/firmware ... ecute-code
https://github.com/ali1234/vcpoke/blob/ ... .c#L21-L34

in theory, you can take a compare channel that is unused, and then begin using it for custom code on the VPU

you would need to write some VPU assembly, compile it to binary, and load it into ram (see vcpoke as an example)

Code: Select all

#define IC0_VADDR                                                HW_REGISTER_RW( 0x7e002030 )
#define IC1_VADDR                                                HW_REGISTER_RW( 0x7e002830 )
those 2 addresses (dont forget to convert bus->arm-physical) tell you where (again, in bus addr space) the vector table is
so you could read IC0_VADDR to get the address of the vector table, then write to vectorTable[64] to remap compare channel 0 to a custom function (convert arm physical back into a bus addr)

then the VPU will run the given assembly, any time the compare matches

https://github.com/librerpi/rpi-open-fi ... #L122-L125

as with the arm based timer stuff, you need to read the status register, and ideally, write only the compare flags your handling (not all, like this example)
then you can do whatever you want, and just be careful to return the VPU to the state you found it in

https://github.com/librerpi/rpi-open-fi ... .S#L46-L58
this is an example VPU interrupt handler


in theory, if you get all of that right, you can run linux and the stock firmware, but still have custom code run on the VPU any time the match occurs

SietseAchterop
Posts: 13
Joined: Fri Mar 06, 2020 12:39 pm

Re: Using the system timer interrupt at 1MHz

Sat Mar 28, 2020 3:54 pm

Thanks both for the detailed replies, much appreciated!
Note that I only want to use the rpi zero, so only one core.
Does that mean that the system time registers are available on the arm side in the same manner as in the blink07 example?
I know one (number 3) is, because Linux is using it.

I am going to look in the Linux source where the system timer 3 is used there and
then do an experiment on whether I can access system timer 1.for use as an interrupt source.

I am trying to use Linux because it has a working wifi/bt stack, while in bare-metal it
still is not working as far as I can see.

Thanks again!
Sietse

cleverca22
Posts: 323
Joined: Sat Aug 18, 2012 2:33 pm

Re: Using the system timer interrupt at 1MHz

Sat Mar 28, 2020 6:48 pm

all 4 timers are shared between the vpu and arm, so you need to first figure out which timers the firmware and linux are using

the baremetal arm examples wont take the ones linux is using into account, but a simple way to check, is to just read the 4 compare registers a few times, and see if they are ever changing

i dont know the exact details, but i think the armv6 era pi's used one of the timer channels for linux, because the arm cpu lacked its own timers
and then the armv7 era ones switched to using a standard arm timer

also, depending on what linux is doing with its timer (an irq on every tick maybe?) you could just let linux do its thing and have the VPU interrupted by the same timer, though the ACK'ing would be more complex

Return to “Bare metal, Assembly language”