Forum: Mikrocontroller und Digitale Elektronik [xmega] USART RX ISR umstellen auf DMA


von Markus C. (ljmarkus)


Lesenswert?

Hallo,

ich würde gerne meine ISR für den USART_RX auf DMA umstellen.

CPU: XMEGA32A4

Es werden immer 600 Byte vom PC gesendet. Als Startflag für 600 Byte 
wird per ISR Pin Rising Edge gemacht.

Wer kann mir helfen es auf DMA umzustellen?



Derzeit schaut es so aus:
--------------------------
1
volatile uint16_t buffer_counter;
2
volatile uint8_t buffer_in[600];
3
4
/****************************************************************************/
5
ISR (USARTC0_RXC_vect)
6
{
7
  buffer_in[buffer_counter] = USARTC0.DATA;
8
  buffer_counter++;
9
}
10
11
/****************************************************************************/
12
ISR (PORTA_INT0_vect)
13
{
14
  buffer_counter = 0;
15
}
16
17
/****************************************************************************/
18
void init_usartC0(void)
19
{
20
  PORTC.DIRSET = PIN3_bm;  // PC3 (TXC0) as output.
21
  PORTC.DIRCLR = PIN2_bm; // PC2 (RXC0) as input.
22
    
23
  
24
  // 32 Mhz - B460800
25
  USARTC0.BAUDCTRLA = 107;
26
  USARTC0.BAUDCTRLB = 0b10110000;  
27
  
28
  
29
  USARTC0.CTRLA = USART_RXCINTLVL_HI_gc;
30
  USARTC0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
31
  USARTC0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc;
32
}
33
34
/****************************************************************************/
35
int main(void)
36
{
37
  
38
  system_clocks_init(4);  // 8Mhz * 4 = 32Mhz
39
  
40
  
41
  PORTA.DIRSET = PIN5_bm;  // Output
42
  PORTA.DIRSET = PIN6_bm;  // Output
43
  PORTA.DIRSET = PIN7_bm;  // Output
44
  PORTB.DIRSET = PIN0_bm;  // Output
45
  
46
  
47
  //PORTA.OUTCLR = PIN5_bm;
48
  PORTA.OUTSET = PIN5_bm;  // OFF
49
  PORTA.OUTSET = PIN6_bm;  // OFF
50
  PORTA.OUTSET = PIN7_bm;  // OFF
51
52
  
53
  // PORTA PIN 4 Interrupt einstellen steigende flanke
54
  PORTA.INT0MASK = PIN4_bm;
55
  PORTA.PIN4CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_RISING_gc;  // Pull Down einschalten, ISR steigende Flanke
56
  PORTA.INTCTRL |= PORT_INT0LVL_HI_gc;    // High Level Interrupt
57
58
59
  init_usartC0();
60
  
61
  
62
  // Enable Interrupts
63
  PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;    
64
  sei();
65
  
66
67
  while(1)
68
    {
69
    PORTA.OUTTGL = PIN5_bm;
70
    }
71
}

Danke, Markus

von Markus C. (ljmarkus)


Lesenswert?

Guten Morgen,

mit Hilfe AppNode AVR1510 habe ich den DMA soweit ans laufen bekommen.
Nur mit dem "Restart" des DMA komme ich nicht klar.
Derzeit löse ich es wie in der "ISR (PORTA_INT0_vect)".

Würde aber gerne auf die ISR verzichten und dem DMA einen Restart 
beibringen.

Hat von euch einer eine Idee?

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "clksys_driver.h"
4
#include "dma_driver.h"
5
6
7
#define data_size  600
8
9
static uint8_t Rx_Buf[data_size];
10
11
#define DMA_RX_Channel &DMA.CH0
12
13
/****************************************************************************/
14
ISR (PORTA_INT0_vect)
15
{
16
  SetupReceiveChannel();
17
  DMA_EnableChannel( DMA_RX_Channel );
18
}
19
20
/****************************************************************************/
21
void init_usartC0(void)
22
{
23
  PORTC.DIRSET = PIN3_bm;  // PC3 (TXC0) as output.
24
  PORTC.DIRCLR = PIN2_bm; // PC2 (RXC0) as input.
25
  
26
  // 32 Mhz - B460800
27
  USARTC0.BAUDCTRLA = 107;
28
  USARTC0.BAUDCTRLB = 0b10110000;  
29
  
30
  //USARTC0.CTRLA = USART_RXCINTLVL_HI_gc;
31
  USARTC0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
32
  USARTC0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc;
33
}
34
35
/****************************************************************************/
36
void SetupReceiveChannel(void)
37
{
38
  DMA_SetupBlock(
39
          DMA_RX_Channel,
40
          (void *) &USARTC0.DATA,
41
          DMA_CH_SRCRELOAD_NONE_gc,
42
          DMA_CH_SRCDIR_FIXED_gc,
43
          Rx_Buf,
44
          DMA_CH_DESTRELOAD_NONE_gc,
45
          DMA_CH_DESTDIR_INC_gc,
46
          data_size,
47
          DMA_CH_BURSTLEN_1BYTE_gc,
48
          0, // Perform once
49
          true
50
          );
51
          
52
  DMA_EnableSingleShot(DMA_RX_Channel);
53
  // USART Trigger source, Receive complete
54
  DMA_SetTriggerSource(DMA_RX_Channel, DMA_CH_TRIGSRC_USARTC0_RXC_gc);
55
}
56
57
/****************************************************************************/
58
int main(void)
59
{
60
  system_clocks_init(4);  // 8Mhz * 4 = 32Mhz
61
  
62
  
63
  PORTA.DIRSET = PIN5_bm;  // Output
64
  PORTA.DIRSET = PIN6_bm;  // Output
65
  PORTA.DIRSET = PIN7_bm;  // Output
66
  PORTB.DIRSET = PIN0_bm;  // Output
67
  
68
  
69
  //PORTA.OUTCLR = PIN5_bm;
70
  PORTA.OUTSET = PIN5_bm;  // OFF
71
  PORTA.OUTSET = PIN6_bm;  // OFF
72
  PORTA.OUTSET = PIN7_bm;  // OFF
73
  
74
  _delay_ms(500);
75
  
76
  
77
  // PORTA PIN 4 Interrupt einstellen steigende flanke
78
  PORTA.INT0MASK = PIN4_bm;
79
  PORTA.PIN4CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_RISING_gc;  // Pull Down einschalten, ISR steigende Flanke
80
  PORTA.INTCTRL |= PORT_INT0LVL_HI_gc;    // Low Level Interrupt
81
82
83
  init_usartC0();
84
  
85
  DMA_Enable();
86
  //SetupReceiveChannel();
87
  //DMA_EnableChannel( DMA_RX_Channel );
88
  
89
  
90
  // Enable Interrupts
91
  PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;    
92
  sei();
93
  
94
  
95
  while(1)
96
    {
97
    PORTA.OUTTGL = PIN5_bm;
98
    }
99
}

Danke,
Markus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.