Forum: Mikrocontroller und Digitale Elektronik DMA Transfer Complete interrupt nach einem Zeichen statt fünf


von Markus G. (the_grue)


Angehängte Dateien:

Lesenswert?

Servus!

Nach meiner Lektüre vom STM32F303 Reference Manual (RM0316) verstehe ich 
den DMA transfer so, daß ein Tranfer-Complete-Interrupt ausgelöst wird, 
wenn der komplette Transfer (also wenn DMA_CNDTRx==0 geworden ist).

Ich verstehe einfach nicht warum, aber bei mir wird die entsprechende 
ISR immer schon aufgerufen, nachdem 1 Zeichen übertragen wurde. Die 
Anwendung ist: Einen Puffer am UART via DMA ausgeben. Damit nicht gleich 
der nächste Transfer gestartet wird, solange der aktuelle nicht fertig 
ist, blockiere ich den Transfer mit einem flag (als pseudo-mutex). Vor'm 
Transfer wird auf flag==0 gewartet, dann flag=1 gesetzt und die ISR soll 
am Transferende flag=0 setzen. Wenn jetzt schon nach dem ersten Zeichen 
das Flag gelöscht wird, rent der Code natürlich in ein HAL_BUSY (oder 
so).

Im beigefügten Oszyllogramm sieht man die (decodierte) TX-Leitung (grün) 
und einen kurzen Peak (rot), wenn die ISR zum falschen Zeitpunkt 
aufgerufen wird.

Ich hab' schon alles mögliche probiert, komme aber nicht dahinter. Könnt 
Ihr mir bitte weiterhelfen? Das ist der Code:
1
int dmaTxMutex = 0;  // Int used as mutex to prevent overlapping DMA transfers
2
3
static UART_HandleTypeDef UART_HandleStructure;
4
static DMA_HandleTypeDef  DMA_Handle;
5
6
#define EMBER_COM_USART_TX_DMA_CHANNEL    DMA1_Channel2
7
#define EMBER_COM_USART_TX_DMA_IRQ        DMA1_Channel2_IRQn
8
#define EMBER_COM_USART_TX_DMA_IRQHANDLER DMA1_Channel2_IRQHandler
9
10
void init()
11
{
12
    //Configure USART TX GPIO as alternate function push-pull
13
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
14
    GPIO_InitStructure.Pin = EMBER_COM_TX_PIN;
15
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
16
    GPIO_InitStructure.Alternate = GPIO_AF7_USART3;
17
    HAL_GPIO_Init(EMBER_COM_TX_PORT, &GPIO_InitStructure);
18
19
    // RX, RTS, CTS omitted
20
21
    //Configure USART
22
    UART_HandleStructure.Instance = USART3;
23
    UART_HandleStructure.Init.BaudRate = 115200;
24
    UART_HandleStructure.Init.WordLength = UART_WORDLENGTH_8B;
25
    UART_HandleStructure.Init.Parity = EMBER_COM_PARITY;
26
    UART_HandleStructure.Init.StopBits = UART_STOPBITS_1;
27
    UART_HandleStructure.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
28
    UART_HandleStructure.Init.Mode = UART_MODE_TX_RX;
29
30
    if(HAL_UART_Init(&UART_HandleStructure) != HAL_OK)
31
    {
32
        ESMxError_SetId( EID_UART );
33
    }
34
35
    __HAL_UART_ENABLE(&UART_HandleStructure);
36
37
    //Enable USART (top level) NVIC interrupt and configure the priority
38
    HAL_NVIC_SetPriority(EMBER_COM_IRQn, 0, 0);
39
    HAL_NVIC_EnableIRQ(EMBER_COM_IRQn);
40
41
    // Configure DMA to send data via UART
42
    DMA_Handle.Instance                 = EMBER_COM_USART_TX_DMA_CHANNEL;
43
    DMA_Handle.Init.Direction           = DMA_MEMORY_TO_PERIPH;
44
    DMA_Handle.Init.PeriphInc           = DMA_PINC_DISABLE;
45
    DMA_Handle.Init.MemInc              = DMA_MINC_ENABLE;
46
    DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
47
    DMA_Handle.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
48
    DMA_Handle.Init.Mode                = DMA_NORMAL;
49
    DMA_Handle.Init.Priority            = DMA_PRIORITY_HIGH;
50
51
    if (HAL_DMA_Init(&DMA_Handle) != HAL_OK)
52
    {
53
        /* Initialization Error */
54
        ESMxError_SetId( EID_DMA );
55
    }
56
57
    __HAL_LINKDMA(&UART_HandleStructure, hdmatx, DMA_Handle);
58
59
    /*##-6- Configure NVIC for DMA transfer complete/error interrupts ##########*/
60
    /* Set Interrupt Group Priority */
61
    HAL_NVIC_SetPriority(EMBER_COM_USART_TX_DMA_IRQ, 0, 0);
62
63
    /* Enable the DMA STREAM global Interrupt */
64
    HAL_NVIC_EnableIRQ(EMBER_COM_USART_TX_DMA_IRQ);
65
66
}
67
68
69
void EMBER_COM_USART_TX_DMA_IRQHANDLER( void )
70
{
71
  DebugPinOn( DBG_RED );
72
73
  // Disable interrupt to avoid infinite loop. Interrups are enabled
74
  // again automaticaly when running HAL_UART_Transmit_DMA
75
  __HAL_DMA_DISABLE_IT( &DMA_Handle, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE );
76
77
  dmaTxMutex = 0;
78
79
80
  DebugPinOff( DBG_RED );
81
}
82
83
//------------------------------------------------------------------------------
84
/// \brief Used to write to the NCP
85
///
86
/// \param handle: ignored
87
/// \param buffer: data to write
88
/// \param size: size of buffer
89
///
90
/// \return number of bytes written
91
//------------------------------------------------------------------------------
92
size_t emberWrite(int handle, const unsigned char * buffer, size_t size)
93
{
94
  HAL_StatusTypeDef status = HAL_OK;
95
96
  while (dmaTxMutex>0 )
97
  {
98
    //OS_Delayus( 32 ); // wake approx. three times per transfered byte
99
    DebugPinToggle( DBG_YELLOW );
100
  }
101
  dmaTxMutex = 1; // take the mutex. dma irq releases it
102
103
  status = HAL_UART_Transmit_DMA(&UART_HandleStructure, (uint8_t*) buffer, size);
104
105
  if ( status != HAL_OK)
106
  {
107
    ESMxError_SetId( EID_DMA );
108
  }
109
110
  return size;
111
}

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.