Forum: Mikrocontroller und Digitale Elektronik STM32 USART1 TXE wird nicht gesetzt?


von Schaulus Tiger (Gast)


Lesenswert?

hallo!

auf einem STM32F205RC benutze ich nur das USART1, RX mit 
Interrupt-Routine, TX wird gepollt:
1
int
2
putchar (int c1)
3
{
4
  if (c1 == '\n')  putchar ('\r');
5
  while ((USART1->SR & USART_SR_TXE) == 0);
6
  USART1->DR = c1;
7
  return c1;
8
}
Gelegentlich bleibt das Teil in der while-Schleife hängen. Hat man schon 
mal von so einem Dreckeffekt gehört? In den errata vom Dezember 2013 
finde ich nichts.

Es kommen nur selten einzelne RX-Interrupts, da gibt es keinen 
zeitlichen Zusammenhang. DMA-Controller sind zwar für I2C initialisiert, 
aber das wird z.Zt. nicht benutzt. Die Initialisierung scheint mir auch 
unspektakulär:
1
void
2
usart1_init (int baud)
3
{
4
int  brr;
5
6
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
7
  brr = (((16000000 / 16) * 16) + (baud / 2)) / baud;
8
  USART1->BRR = brr;
9
  USART1->CR2 = USART_CR2_STOP_1;
10
  USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE
11
              | USART_CR1_M | USART_CR1_PCE | USART_CR1_RXNEIE;
12
  NVIC->ISER[(53 - 16) / 32] |= 1 << ((53 - 16) % 32);
13
}

Aber jetzt kommt's: es ist nicht rein zufällig, ein (auch viele) 
putchar() vor und nach einer beep()-Funktion funktioniert, ein putchar 
in der beep() hängt sich zuverlässig auf, egal, ob vor oder nach dem 
einschalten des Timers. Na klar, Timer und Uart geht nicht 
gleichzeitig!?
1
  putchar ('+');  /* ok */
2
  beep (0, 5, 200);
3
  putchar ('+');  /* ok */
4
5
6
void
7
beep (int tone, int octave, int ms)
8
{
9
static const int div12[] = {
10
  2273, 2145, 2025, 1911, 1804, 1703, 1607, 1517, 1432, 1351, 1276, 1204 };
11
int  psc;
12
13
  putchar ('!');  /* geht nicht */
14
  if (octave < 3)  octave = 3;
15
  if (octave > 7)  octave = 7;
16
  if (tone < 0 || tone > 11)  tone = 11;
17
  psc = (div12[tone] * (1 << (7 - octave))) / 2;
18
  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
19
  TIM3->PSC = psc;
20
  TIM3->ARR = 2;
21
  TIM3->CCR4 = 1;
22
  TIM3->CCMR2 = 6 << 12;
23
  TIM3->CCER = TIM_CCER_CC4E;
24
  TIM3->CR1 = TIM_CR1_ARPE;
25
  TIM3->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN;
26
//  TIM3->EGR = TIM_EGR_UG;
27
  sleep (ms);
28
  TIM3->CCR4 = 0;
29
  putchar ('!');  /* geht nicht */
30
}

Momentan hab' ich der while-Schleife einen Time-Out spendiert, das 
sollte man ja immer machen, deshalb bleibt der auch drin. Aber falls 
jemand eine Idee hat, was da passiert wäre ich dankbar für einen Tipp.

von Jim M. (turboj)


Lesenswert?

Schau mal nach, ob der Interrupt Handler nicht das TXE Bit löscht.
1
NVIC->ISER[(53 - 16) / 32] |= 1 << ((53 - 16) % 32);

Bitte verwende NVIC_EnableIRQ() aus dem CMSIS. So kann das keiner lesen,
und es ist extrem fehleranfällig.

von Schaulus Tiger (Gast)


Lesenswert?

Äh, entschuldigen Sie bitte die Störung, kann man den Thread bitte 
löschen?

Es war natürlich ein Layer 8 Problem. beep() wird vor uart_init() 
aufgerufen. Was ja total o.k. ist, solange man kein debug-printf in die 
beep() schreibt...


Jim Meba schrieb:
> Schau mal nach, ob der Interrupt Handler nicht das TXE Bit löscht.

danke, aber selbst wenn der Interrupt Handler ein Echo senden würde, 
wäre das TXE ja nur kurzzeitig 0. Ansonsten ist TXE ja read-only -- laut 
Handbuch und laut gesundem Menschenverstand ;)

>
1
> NVIC->ISER[(53 - 16) / 32] |= 1 << ((53 - 16) % 32);
2
>
>
> Bitte verwende NVIC_EnableIRQ() aus dem CMSIS. So kann das keiner lesen,
> und es ist extrem fehleranfällig.

O.K., die Zeile ist ausbaufähig, aber die CMSIS-Funktionen müssen nun 
wirklich nicht sein. Das ist mein größtes Problem mit den Cortex-M, 
entweder kann ich es lesen oder der Rest der Welt. Ich bin schon froh, 
dass ich mich allmählich an die ewig langen Bit-Namen gewöhne und an die 
Großschreibung der Register (wie krank ist das denn?). Ich hatte schon 
angefangen, eigene stm32fxx.h zu schreiben.

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.