PDCA ring buffer

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

Hi!
I have a working program with PDCA controler transfering data to USART0 on an AT32UC3C2512C processor and I whant to enable the "ring buffer" function in PDCA controller. Byte 3 in MR register, (MR.RING). I'm using PDCA channel 0. Anyone how can give me some simpel C-code example for how to enable this function.
Best regards!

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

This will set the MR.RING!

AVR32_PDCA.channel[PDCA_CHANNEL_USART].mr = AVR32_PDCA_MR0_RING_MASK;

I have been doing some testing with this function and it seems just to create a loop function in PDCA. Not a ring buffer where you can write new data to now and then and it will be transmitted. Anyone else using this function?
Best regards!

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

The PDCA supports dual buffers (kind of ring buffer with two banks) by using the reload registers with interrupt.

Reload registers are a second set of the two registers MAR and TCR (memory address and transfer count).

The reload registers are named MARR and TCRR. These registers are used by hardware to setup the next transfer immediately after one buffer is finished. The hardware just copy the values of MARR and TCRR into MAR and TCR so it can continue seamlessly on the next buffer.

One "problem" is that MARR and TCRR are zeroed after the copying, but an interrupt can be generated just after this hardware event occurs. It is the "reload counter zero" interrupt. This interrupt can put new values into MARR and TCRR and the loop continues...

The way to use double buffering:
1) Allocate two memory areas for the PDCA data (two buffers).

2) The PDCA init must do this:
- register TCRR zero interrupt including pointer to handler
- set transfer size (BYTE, HWRD or WORD)
- set PID
- TCR = TCRR = number of transfers for one buffer
- point MAR to first buffer
- point MARR to second buffer
- save first buffer address into a global int variable

3) write interrupt TCRR zero interrupt handler that do:
- copy the global variable value into MARR
- point the global variable to the other buffer
- set TCRR to number of transfers for one buffer
- set some global variable flag to tell main about the event (main must clear the flag as soon as it knows about the event)

Since there is an interrupt that controls memory address for MARR, it is possible to implement a ring buffer with more than two banks.