• Keine Ergebnisse gefunden

This section explains how to set up HSDMA, using an example program that transfers data to PWM (16-bit timer) for audio output.

DMA transfer to 16-bit timer

The example program shown below uses HSDMA channel 3 and 16-bit timer 5 as a trigger to transfer data from RAM to 16-bit timer 1.

Initial settings

|

;; PWM output timer

#define PRESC16_1 0x40148 ; 16bit Timer 1, Prescaler

#define TMCTRL16_1 0x4818e ; 16bit Timer 1

#define COMPARE_A16_1 0x48188

#define COMPARE_B16_1 0x4818a

#define TIMER16_1_IMASK 0x40272

#define P2_FUNCTION_SELECT 0x402d8 ; Function select output port

;; trigger timer

#define SPK_INTR_LEVEL_0 0x04

#define PRESC16_5 0x4014c ; 16bit Timer 5, Prescaler

#define TMCTRL16_5 0x481ae ; 16bit Timer 5

#define COMPARE_A16_5 0x481a8

#define COMPARE_B16_5 0x481aa

#define TIMER16_5_IMASK 0x40274

#define TIMER16_5_IFLAG 0x40284

#define TIMER16_5_ILEVEL 0x40268 ; Upper 4-bits

;; HSDMA

#define HSDMA_IMASK 0x40271

#define HSDMA_IFLAG 0x40281

#define HSDMA3_IFLAG_CLR 0x08

#define HSDMA_01_ILEVEL 0x40263

#define HSDMA_23_ILEVEL 0x40264

#define HSDMA_23_TRIGGER 0x40299

#define HSDMA3_ENABLE 0x4825c

#define HSDMA3_TFLAG 0x4825e

#define HSDMA3_TRANSFER 0x48250

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#define PRESC16_3 0x0004014a ; 16bit Timer 3, Prescaler

#define TMCTRL16_3 0x0004819e ; 16bit Timer 3

#define COMPARE_A16_3 0x00048198

#define COMPARE_B16_3 0x0004819a

#define TIMER16_3_IMASK 0x00040273

#define TIMER16_3_IFLAG 0x00040283

#define TIMER16_3_ILEVEL 0x00040267 ; Upper 4-bits |

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; void SpkOpen_0(BYTE *SpkParams, int ReloadValue)

;;; dose not destroy r12 - r15

;;;

SpkOpen_0:

; init HSDMA triger timer

ld.w %r5,0x00 (1)

xld.b [TMCTRL16_5],%r5 ; Timer Stop xld.b [PRESC16_5],%r5 ; Prescaler Stop xld.w %r4,TIMER16_5_IMASK

bclr [%r4],7 ; disable comparison A intr.

bclr [%r4],6 ; disable comparison B intr.

xld.w %r5,0xf0

xld.b [TIMER16_5_IFLAG],%r5 ; clear comparison A B factor flags xld.h [COMPARE_B16_5],%r13 ; set compare B value (ReloadValue)

; init HSDMA

ld.w %r5,0 (2)

xld.h [HSDMA3_ENABLE],%r5 ; HSDMA Ch3 disable (stop) ld.w %r5,HSDMA3_IFLAG_CLR

xld.b [HSDMA_IFLAG],%r5 ; clear DMA Ch3 interrupt flag clear xbset [HSDMA_IMASK],3 ; enable DMA Ch3 end interrupt xld.w %r4,HSDMA_23_ILEVEL

ld.b %r5,[%r4]

and %r5,0x0f ; mask lower 4bit

ld.w %r6,0x4 ; HSDMA Ch3 interrupt level = 4 sll %r6,0x04 ; level is upper 4bit

or %r5,%r6

ld.b [%r4],%r5 ; set interrupt level

ld.w %r5,8 (3)

sll %r5,4

xld.b [HSDMA_23_TRIGGER],%r5 ; HSDMA trigger is 16bit timer ; Ch.5 compare B

|

|

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; int SpkNext(BYTE *SpkParams)

;;; interrupt routine

;;; dose not destroy r9,r10 r12 - r15

;;; In DMA version, change to control register

;;; r9 : (*Length)

;;; r10 : Length

;;; r12 : SpkParams

;;;

SpkNext:

xcall QueueRead ; QueueRead dose not destroy r12 - r15 cmp %r10,0x00 ; r9:*Length, r10:Length, r11:*Buffer jreq RetSpkNext ; if (Failed) QueueEmpty

| ; Write HSDMA register

xld.w %r4,HSDMA3_TRANSFER ; start of dma transfer register (4) ld.w %r6,%r10

xoor %r6,%r6,0x80000000

ld.w [%r4]+,%r6 ; Length and address mode dual ld.w %r7,%r11 ; source address (buffer pointer) xoor %r7,%r7,0x70000000 ; addr increment, harf word transfer ld.w [%r4]+,%r7 ; for 10bit PWM

xld.w %r8,COMPARE_A16_1 ; 16bit timer compareA register ld.w [%r4]+,%r8 ; dest address, single

; Enable HSDMA ld.w %r5,1

ld.h [%r4],%r5 ; HSDMA enable (start) HSDMA3_ENABLE RetSpkNext:

ret

(1) Initializing the HSDMA triggering timer

In this example, 16-bit timer 5 is used as a trigger for HSDMA. Temporarily suspend timer 5 operations and turn off the prescaler clock output for timer 5.

; init HSDMA triger timer ld.w %r5,0x00

xld.b [TMCTRL16_5],%r5 ; Timer Stop xld.b [PRESC16_5],%r5 ; Prescaler Stop

With the interrupt controller, disable the timer 5 interrupt and clear the interrupt factor flag.

xld.w %r4,TIMER16_5_IMASK

bclr [%r4],7 ; disable comparison A intr.

bclr [%r4],6 ; disable comparison B intr.

xld.w %r5,0xf0

xld.b [TIMER16_5_IFLAG],%r5 ; clear comparison A B factor flags

Set the HSDMA cycle data (e.g. 8k times per second) passed via R13 from the calling routine in the compare B register.

xld.h [COMPARE_B16_5],%r13 ; set compare B value (ReloadValue) (2) Initializing HSDMA interrupt

Always confirm that HSDMA is disabled before setting HSDMA. If set while operating, the register may be read or written to incorrectly.

; init HSDMA ld.w %r5,0

xld.h [HSDMA3_ENABLE],%r5 ; HSDMA Ch3 disable (stop)

With the interrupt controller, clear the the HSDMA channel 3 interrupt factor flag and enable the interrupt.

ld.w %r5,HSDMA3_IFLAG_CLR

xld.b [HSDMA_IFLAG],%r5 ; clear DMA Ch3 interrupt flag clear xbset [HSDMA_IMASK],3 ; enable DMA Ch3 end interrupt Set the interrupt level to 4.

xld.w %r4,HSDMA_23_ILEVEL ld.b %r5,[%r4]

and %r5,0x0f ; mask lower 4bit

ld.w %r6,0x4 ; HSDMA Ch3 interrupt level = 4 sll %r6,0x04 ; level is upper 4bit

or %r5,%r6

ld.b [%r4],%r5 ; set interrupt level (3) Setting HSDMA trigger

Set 16-bit timer 5 for the HSDMA channel 3 trigger.

ld.w %r5,8 sll %r5,4

xld.b [HSDMA_23_TRIGGER],%r5 ; HSDMA trigger is 16bit timer ; Ch.5 compare B

(4) Setting HSDMA transfer conditions

Set the DMA transfer count (data count) passed via R10 from the calling routine. Set transfer mode to dual-address transfer.

; Write HSDMA register

xld.w %r4,HSDMA3_TRANSFER ; start of dma transfer register ld.w %r6,%r10

xoor %r6,%r6,0x80000000

ld.w [%r4]+,%r6 ; Length and address mode dual

Set the transfer source address, increment mode, and 16-bit data size. The transfer source address is the start address of the buffer (RAM) in which PWM data has been prepared.

ld.w %r7,%r11 ; source address (buffer pointer) xoor %r7,%r7,0x70000000 ; addr increment, harf word transfer ld.w [%r4]+,%r7 ; for 10bit PWM

Set the compare A register for PWM 16-bit timer as the transfer destination. Select single transfer mode, in which one data unit is transferred by one DMA operation.

xld.w %r8,COMPARE_A16_1 ; 16bit timer compareA register ld.w [%r4]+,%r8 ; dest address, single

Enable HSDMA.

; Enable HSDMA ld.w %r5,1

ld.h [%r4],%r5 ; HSDMA enable (start) HSDMA3_ENABLE

DMA transfer is now executed as many times as set at the frequency of the compare B cycle set in 16-bit timer 5.

Interrupt processing at the end of DMA transfer

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; SpkIntr0

;;; HSDMA transfer end interrupt

;;;

SpkIntr0:

pushn %r15 (1)

ld.w %r0,%ahr ld.w %r1,%alr pushn %r1

xld.w %r12,SPK_PARAMS_0 ; SpkParams

xld.w %r13,HSDMA_IFLAG ; IFlagReg (2) xld.w %r14,HSDMA3_IFLAG_CLR ; IFlag clear data

ld.b [%r13],%r14 ; clear DMA Ch3 interrupt flag ld.w %r15,[%sp+0x12] ; OldPSR (3) xcall QueueNext

popn %r1 (1)

ld.w %alr,%r1 ld.w %ahr,%r0 popn %r15 reti

Register the start address (SpkIntr0) of this handling routine as the vector for HSDMA channel 3.

Process the interrupt generated each time a number of HSDMA transfers set is completed.

(1) Saving and restoring registers

At the beginning and end of interrupt processing, save and restore all of R0–R15, AHR and ALR.

pushn %r15 ld.w %r0,%ahr ld.w %r1,%alr pushn %r1 | popn %r1 ld.w %alr,%r1 ld.w %ahr,%r0 popn %r15 reti

(2) Resetting the interrupt factor flag Clear the interrupt factor flag.

xld.w %r13,HSDMA_IFLAG ; IFlagReg

xld.w %r14,HSDMA3_IFLAG_CLR ; IFlag clear data

ld.b [%r13],%r14 ; clear DMA Ch3 interrupt flag clear (3) Processing for the subsequent transfer

Disable HSDMA and restore transfer conditions before starting the next data transfer.

ld.w %r15,[%sp+0x12] ; OldPSR xcall QueueNext