Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Bare metal GPIO interrupts

Tue May 09, 2017 8:07 pm

I was able to implement interrupts in my old RPi (model 1 B) using the arm timer. Now i would like to implement an interrupt that comes by GPIO (enabling int_gpio[x] instead of basic IRQ) using an input button.I know that i have to active GPEDS and the asyncronous falling and rising registers, but I have two questions to ask:
-How could i change the interrupt handler to manage the arm timer and the GPIO interrupts?
-How could i clear the IRQ when and interrupt occurred as we do with arm timer? i know that to clear ARM timer we have a specific register...
Thank you.

dwelch67
Posts: 802
Joined: Sat May 26, 2012 5:32 pm

Re: Bare metal GPIO interrupts

Tue May 09, 2017 8:19 pm

this is a bare metal forum so basically the interrupt handler is the one you write, there isnt one to modify...

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Tue May 09, 2017 8:25 pm

dwelch67 wrote:this is a bare metal forum so basically the interrupt handler is the one you write, there isnt one to modify...
I explained myself wrong. I meant that how to manage the interrupt handler to manage both types of interrupts (GPIO and arm Timer).

Thank you.

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

Re: Bare metal GPIO interrupts

Wed May 10, 2017 4:54 am

Hi again Jonvii I have been down with flu, but it sounds like you solved most of it in meantime without me :-)

You already have the answer you use the GPEDS if they aren't set it's not a GPIO interrupt branch over it.
The timers also have status registers with a similar bit identifying if it is the interrupt source.

As you are doing baremetal, you are the only one who can set interrupts to trigger they are all masked to off by default so you are in control of the only possible sources.

As for clearing GPIO interrupts page 96 ... you write a 1 to the GPED bit you want to clear .. zero to everything else so just roll a "1" to the right place much the same as your GPIOSET code.
https://www.raspberrypi.org/documentati ... herals.pdf
The relevant bit in the event detect status registers is set whenever: 1) an edge is detected that matches the type of edge programmed in the rising/falling edge detect enable registers, or 2) a level is detected that matches the type of level programmed in the high/low level detect enable registers. The bit is cleared by writing a “1” to the relevant bit.
Timer is similar you hit the IrqClear register page 198 .. you write a 1 to clear it (offset 0x40c). The raw Irq status is available to check source (offset ox410).

Just remember if is set to drop thru and check the other in chain as it may have interrupted in meantime while you were dealing with interrupt ... again a normal chained interrupt thing.

It's quite normal to have to identify irq source by checking status masks on the Pi. You could imagine if they made an interrupt vector for each GPIO port alone (like you might see on a microcontroller) that would be 54 and you should see the irq controller would get massive.

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Wed May 10, 2017 12:45 pm

LdB wrote:Hi again Jonvii I have been down with flu, but it sounds like you solved most of it in meantime without me :-)

You already have the answer you use the GPEDS if they aren't set it's not a GPIO interrupt branch over it.
The timers also have status registers with a similar bit identifying if it is the interrupt source.

As you are doing baremetal, you are the only one who can set interrupts to trigger they are all masked to off by default so you are in control of the only possible sources.

As for clearing GPIO interrupts page 96 ... you write a 1 to the GPED bit you want to clear .. zero to everything else so just roll a "1" to the right place much the same as your GPIOSET code.
https://www.raspberrypi.org/documentati ... herals.pdf
The relevant bit in the event detect status registers is set whenever: 1) an edge is detected that matches the type of edge programmed in the rising/falling edge detect enable registers, or 2) a level is detected that matches the type of level programmed in the high/low level detect enable registers. The bit is cleared by writing a “1” to the relevant bit.
Timer is similar you hit the IrqClear register page 198 .. you write a 1 to clear it (offset 0x40c). The raw Irq status is available to check source (offset ox410).

Just remember if is set to drop thru and check the other in chain as it may have interrupted in meantime while you were dealing with interrupt ... again a normal chained interrupt thing.

It's quite normal to have to identify irq source by checking status masks on the Pi. You could imagine if they made an interrupt vector for each GPIO port alone (like you might see on a microcontroller) that would be 54 and you should see the irq controller would get massive.
Hi Leon,

Yeah, you gave me the key sentences to solve my doubt i had. Now i'm able to know how to manage a interrupt with different peripherals in pi. I'll focus in mixing all things i learned and i'll post it here my results.

I'm very grateful to you.

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Thu May 11, 2017 3:52 pm

I've uploaded a video into YouTube of my learning process with this topic. Here you are the link: https://www.youtube.com/watch?v=HTxUP4DWhB8

What do u think about it?

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

Re: Bare metal GPIO interrupts

Fri May 12, 2017 2:51 am

Good work you got it all going and nice presentation.

Now the extension exercise get a 16x2 LCD character screen and display the number on the LCD. The screens can be run in 4 bit mode with 1 clock line and 1 read/write line and it is very slow typically (50-250Khz clock speed is used). So it's no more IO lines than you have to display the seven segment display but now you have to make clocking signals off the timer irq and put commands on those signal lines. Nice to see young students learning baremetal :-)

User avatar
rpdom
Posts: 11200
Joined: Sun May 06, 2012 5:17 am
Location: Essex, UK

Re: Bare metal GPIO interrupts

Fri May 12, 2017 5:01 am

LdB wrote:Now the extension exercise get a 16x2 LCD character screen and display the number on the LCD.
That's one of the first things I did with my bare metal kernel code - wrote a simple driver for a 16x2 LCD panel. It was very handy for debugging before I got video output working (one routine to hexdump R0, another to hexdump each register in turn repeatedly).
The screens can be run in 4 bit mode with 1 clock line and 1 read/write line
The read/write line should be tied to ground, as you only want to write to the display. Setting it to read mode could place 5V on the gpios and kill them. The sixth line that is needed is the data/control line to say that the value sent is data to be displayed, or a control instruction.
Nice to see young students learning baremetal :-)
It is indeed :-)

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Fri May 12, 2017 2:05 pm

So, if i understood right: I've to buy a LCD screen which is compatible with my pi (i've already searched one called HD44780). After buy it, i've to write the right bits in the right place to do whatever i want (for example, clear the lcd or move to the second line...). I think to do this functions, the lcd needs a few time and that is the reason you told me about the importance of the clock (spend the functions time).

Correct me if i wrong.

I'll try it, for sure! ;)

User avatar
rpdom
Posts: 11200
Joined: Sun May 06, 2012 5:17 am
Location: Essex, UK

Re: Bare metal GPIO interrupts

Fri May 12, 2017 9:08 pm

Correct. The HD44780 screens can be cheap. Note that there are two types. The standard screen uses the direct interface to the Pi. Some screens come with an i2c controller board which is slightly harder to drive in bare metal, but uses fewer GPIO pins.

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

Re: Bare metal GPIO interrupts

Mon May 15, 2017 1:52 am

Exactly as per the responses above the only thing I will add is there is usually a contrast pin which can go between +Vcc and Gnd and as will be shown on typical diagrams from vendor it will be a potentiometer from vcc to gnd middle wiper to contrast pin or you can work out which is high contrast and connect it via a 10K resistor to that. The screens without backlight barely draw any current typically it will be around 50-60ma so you can power them from the Pi board. I would avoid screens with backlight they draw a fair amount of power or need special high voltage inverters.

It's really worth the effort because the screens are very cheap and they are often used on embedded projects for exactly the reasons described above.

Techinical software stuff:

1.) The clock pulse will break into two phases using a bool or equivalent. Each alternative irq you will regard as either clock lifting or clock falling and you will set the clock line up or down accordingly (so your LCD clock rate will be half your clock timer rate). You will need a buffer which has the raw 4 bit commands. If you have commands you change them onto the bus on the lifting clock so they are out and stable by the falling clock there is a reasonable capacitance on the bus you can't output the data and then take the clock low at the same time.

2.) At times there are delays that data can't be sent to the LCD typically after line select and screen clear commands. So you need an output delay mechanism. I typically use a byte command buffer the low 4 bits being the data to output and the 7th bit is used to indicate a delay command and the number being how many clock LCD clock cycles to skip.

If it helps this is the typical irq
[code]
bool clockRising = false;
unsigned char LCDByte; // Used to avoid use of stack in irq
unsigned char LCD_snd_count; // LCD transmit buffer count
unsigned char LCDTimeCount; // This creates an LCD time count
unsigned char LCD_snd_head = 0; // LCD transmit buffer head
unsigned char LCD_snd_tail = 0; // LCD transmit buffer tail
unsigned char LCD_buffer[128]; // LCD transmit buffer

void LCD_interrupt(void) {
if (clockRising) { // Things only change on rising clock
if (LCDTimeCount != 0) { // Time count is active
LCDTimeCount--; // Decrement the time count
} else if (LCD_snd_count != 0) { // We have data for LCD
LCDByte = LCD_buffer[LCD_snd_tail]; // Fetch byte to send
LCD_snd_tail++; // Increment send tail
if (LCD_snd_tail >= sizeof(LCD_buffer)) LCD_snd_tail = 0;// Roll send tail in needed
if (LCDByte.7 == 0) { // Not a time count command
/* Output 4 data bits */
/* Output cmd instruction bit */
/* Take E clock high */
} else LCDTimeCount = (LCDByte & 0x7F); // Set time count
LCD_snd_count--; // Decrement send count (1 byte removed from buffer)
}
clockRising = false; // Move to falling clock next irq
} else {
/* Take E clock low */
clockRising = true; // Move to lift clock next irq
}
}
[/code]

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Tue May 23, 2017 7:25 pm

I recently received hd44780 LCD and i already connected to my Pi to check if something is wrong but all is right with 4-bits mode. I'm new controlling this appliance and i would like to start with the basic level.

I would like to be able to print in the first line some character and the same for the second one. I have one timer implement so i could use a delay function to delay the max time of all operations.

I readed this Instructions which could help me but i'm not sure about using them. For instead, to put a character in the 4 position I would use this estructure:
- Clear display: DB0 1 and the rest 0
- Return Home: DB1 1 and the rest 0 (DB0 does not matter)
-wait();
-Entry mode set: DB2 1 and DB1 1 to increment address, the rest 0.
-wait(); (repeat this procedure four times)
-put a character hexadecimal number

it would be right? if you could help me with one example i would undertand and i would be able to do more complex bare metal practices.

Thank you mates.

dwelch67
Posts: 802
Joined: Sat May 26, 2012 5:32 pm

Re: Bare metal GPIO interrupts

Tue May 23, 2017 10:28 pm

start by polling a free running timer, later (if ever) mess with interrupts...

are you bit banging or using a serial peripheral?

dwelch67
Posts: 802
Joined: Sat May 26, 2012 5:32 pm

Re: Bare metal GPIO interrupts

Tue May 23, 2017 10:29 pm

ahh parallel interface, so you are bit banging...

dwelch67
Posts: 802
Joined: Sat May 26, 2012 5:32 pm

Re: Bare metal GPIO interrupts

Tue May 23, 2017 10:35 pm

I personally would do it at least twice, first bit bang and poll a timer (or just a dump count to N loop even) to kill time, learn how to use/program the display as the goal.

Next if you wish you could for example compute the sequence of gpio port writes that would reflect the bit banging, buffer that sequence up in memory, then have a timer at a fixed rate that each interrupt grabs the next value and writes it to the gpio port (or ports) until it hits an agreed upon end of list, then the interrupts wait for the list to show as having a new list.

maybe there is a third implementation that puts a little of the application work in the interrupt but not too much.

Note: you should have absolutely no problem writing things to this display with no interrupts and no timer even...as far as program whose job it is to do just that. then if that consumes too much foreground time then timers or other solutions (there are other non-interrupt with timer foreground solutions)

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Tue May 23, 2017 10:46 pm

Hi dwelch,

So u recommend me to start by pooling handling dram of hd44780 lcd peripheral and if it works fine, start with interrupts?

dwelch67
Posts: 802
Joined: Sat May 26, 2012 5:32 pm

Re: Bare metal GPIO interrupts

Wed May 24, 2017 2:17 am

Nope, if I had just bought one of those displays (I have one I am sure actually), I would not use any interrupts as I learned how to program it to display something. might not even use a timer.

Jonvii
Posts: 15
Joined: Fri Apr 07, 2017 11:06 am

Re: Bare metal GPIO interrupts

Wed May 31, 2017 12:10 pm

Before I start handling the lcd, i would like to undertand this assembly file well. It's about the _reset_ function programmed by Bryan in his http://www.valvers.com/open-software/ra ... -in-c-pt4/ tutorial.

I know that the first Load and Store arm functions are used to copy the vector table into 0x0000, but then starts handling the stack pointer register, first going to IRQ mode and then returning to Supervisor mode (in a different memory place, could be the using of different registers in both user modes?).

I Suppose the reason is to avoid conflict between the physically separated sp registers and be able to accept the IRQs.

I'm right? Thank you.

Return to “Bare metal”

Who is online

Users browsing this forum: No registered users and 7 guests