How would you setup the interrupts for this on the mega4809

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is for my multiplexed quad 5x7 display.  The device will be a SPI slave and allow daisy chaining the display so it will have its MISO connected to the next displays MOSI and so on.

 

I am currently using these interrupts:

 

ISR (PORTC_PORT_vect) - this is for the "register select" pin changing.  Any change on the RS pin triggers it.

ISR (PORTE_PORT_vect) - this is for the SS pin.  It going high triggers it.

ISR (SPI0_INT_vect) - this is for receiving a byte from SPI and setting the SPI0_DATA to the proper value so that it will shift out the correct byte when the next one is received.

ISR (TCB0_INT_vect) - main display multiplexing interrupt, fires at 700 Hz giving a 7 rows by 100 Hz refresh rate.

ISR (TCB1_INT_vect) - used to turn off the row at a specific time to control brightness of that row, controlled by the TCB0_INT_vect

 

I've read the interrupt section of the 0-series datasheet and it looks like there is a single level 1 interrupt and then the level 0 interrupts can do a round robin thing if preferred, or the level 0 priority can be altered so a specific interrupt has a higher priority than others.

 

So this seems to give not only a level 1, but also allows you to make a level 0 the highest level 0 which is interesting.

 

Obviously I want the rows and brightness adhered to so they will have a solid and reliable display, but honestly the SPI is my bigger concern.  The reason is that I want to make it be as fast as possible.  The thing is that the display will basically have 3 modes - a command mode (RS is HIGH), a text mode (RS is LOW, configured for text mode), and a graphics mode (RS is LOW, configured for graphics mode).  What this means is that it has to have a buffer to shift out the correct value for text/graphics.  If in text mode and I send 4 bytes via SPI "1234", then if I shift "5678" then "1234" will be shifted to the subsequent display.  To do this I am using a ringbuffer and a pointer which works great, but there is a critical time element when receiving a byte (or an RS pin change) that I have to set the SPI0_DATA register to the correct value to shift out next (before the next SPI value comes in!).  In command mode this is no big deal as the value that came in is the next one to be shifted out (SPI0_DATA does not have to be set or changed), but in the data/graphics mode, this happens in two places.

 

The obvious place is the SPI0_INT_vect where it grabs the value first and then sets the next value to be shifted out based on (RS and mode).

 

Then the interrupt that handles a RS pin change must also set the SPI0_DATA value correctly as well.  If you switch from command mode to text/graphics mode, it must set the next SPI value to go out to the proper value from the ring buffer.

 

Given this, I'm thinking of making the level 1 priority the SPI0_INT_vect AND then setting the LVL0PRI (for level 0) to make the RS interrupt the highest level 0 interrupt.

 

Obviously there will need to be timing restrictions that say after changing RS, you must wait X uS before proceeding.  Probably also a similar time restriction after sending a SPI byte.  Again, the goal is reducing these to the bare minimum amounts.

 

Do you agree with my strategy?  Any better ideas?

 

Also, the LVL0PRI register is a little confusing in the datasheet.  When the default value is 0, it points to figure 12-3 which shows 0 to be the HIGHEST priority.  Then it says that if you change it to another vector that that vector will be the LOWEST priority, but the next one will be the highest.  To me this does NOT make sense because the second one contracts the first one.  Any thoughts about that?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also - is there a document with more details on these two registers?

 

The default priority can be changed by writing to the CPUINT.LVL0PRI register. The value written to the register will
identify the vector number with the lowest priority.

 

Bits 7:0 – LVL1VEC[7:0] Interrupt Vector with Priority Level 1

This bit field contains the address of the single vector with increased priority level 1 (LVL1).

 

So one has a "vector number" and the other has the "address of the single vector"?  Are these two different values?

 

The interrupt table is 4 bytes per entry (2 words).  In the LSS file it goes 0, 4, 8, and so on (byte addressing).

 

So should LVL0PRI have the vector number, the word address, or the byte address?

 

So should LVL1VEC have the vector number, the word address, or the byte address?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>So should LVL0PRI have the vector number

 

Both LVL0PRI and LVL1VEC are vector numbers- whether you have a mega4809 with jmp, or a tiny416 with rjmp, makes no difference.

 

>To me this does NOT make sense

 

They could do a better job on that, but the reset vector is not a vector where priority matters (a reset of any kind doesn't wait around for priorities to sort out).

LVL0PRI = 0, 0 is lowest priority (not actually), 1 is highest (NMI always is), so 2 is the level0 vector with highest priority

(now it may be that there is actually a special case for 0, but there would be no reason for it)

LVL0PRI = 1, 1 is lowest (but NMI is actually highest), 2 is highest, so 2 is the level0 vector with highest priority

so 0,1 are actually vector 2 in practice

LVL0PRI = last vector, last vector is lowest, 2 is now highest again

LVL0PRI:HIGHEST - 0:2, 1:2, 2:3, 3:4, last-1:last, last:2

 

You may also want to check if your 4809 has a date code older than 1914 as level1 irq may not always work, they say.

Last Edited: Tue. Sep 10, 2019 - 06:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wouldn't use multiple interrupt priorities unless they really seem to be needed.  All you'll do is introduce complexities in locking/etc that are ... annoying.
All of your interrupts sound like they don't really have very tight latency requirements, so I don't think you need it.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
Also - is there a document with more details on these two registers?

 

http://ww1.microchip.com/downloa...

 

EDIT: also you can take a look at this Pdf for process scheduling on 8-bit AVR (ATtiny 0&1) series:

 

http://ww1.microchip.com/downloa...

 

 

Last Edited: Tue. Sep 10, 2019 - 08:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got two 1821 datecodes and a 1930 datecode.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I enabled the level 1 on my DIP packaging (1905K 4 W).

 

It seems to work and NOT reset, does that mean it doesn't have the error related to the level 1?  Also, what revision is it?  I kept seeing references in the errata sheet to Rev A and Rev B.

  //sets PORTC_PORT_vect to the highest level 0 priority
  CPUINT.LVL0PRI = PORTC_PORT_vect_num-1;

  //sets SPI0_INT_vect_num to level 1 priority
  CPUINT.LVL1VEC = SPI0_INT_vect_num;

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It works well on the DIP with datecode 1905K 4 W.  I set it up with the above code and then checked to see if it worked with:

 

  if ((CPUINT.STATUS & CPUINT_LVL0EX_bm) && (CPUINT.STATUS & CPUINT_LVL1EX_bm))
    {
      test=1;
    }

 

Also confirmed it worked by sending a bunch of SPI bytes and if I send a long enough string I can see where the display interrupt delays the SPI interrupt from running enough to cause a problem (it wasn't ready to send the next proper SPI byte).  With the SPI vector selected as a level 1 vector, it works perfectly.