Forum: Compiler & IDEs Problem mit simplem FiFo


von Sven S. (schwerminator)


Lesenswert?

Moin Moin,
ich versuche zur Zeit einen einfachen FIFO zu implementieren. Dazu habe 
ich einen externen SRAM-Baustein im Einsatz, der 16 Speicherbänke à 32kB 
beherbergt. Eine Testfunktion, die alles mit fortlaufenden Nummern 
beschreibt und später wieder kontrolliert, funktioniert einwandfrei.

Nun versuche ich eine Eingabe über UART zu realisieren, bei der zunächst 
beliebig viele Zeichen in den FIFO geschrieben werden und bei Eingabe 
eines '#' die ersten hundert Zeichen im FIFO ausgegeben werden sollen. 
Leider bleibt die Ausgabe immer bei Zeichen 98 hängen. Nun weiß ich 
nicht, wo der Fehler liegt, bei der FIFO-Routine, die im vorherigen Test 
ja reibungslos funktioniert hat, oder bei der UART-Ausgabe (P. Fleury), 
die ja eigentlich auch erprobt ist... Vielleicht könnt ihr mir ja 
weiterhelfen...
1
#define UART_BAUD_RATE 9600
2
#define XMEM_OFFSET 0x2200
3
#define XMEM_BANK_SIZE 0x8000
4
5
struct {
6
  uint16_t address;
7
  uint8_t bank;
8
} fifo_read, fifo_write;
9
10
void fifo_init(void){
11
  XMCRA |= (1<<SRE);
12
  XMCRB |= (1<<XMM0);
13
14
  DDRF |= 0xF0;
15
  PORTF &= 0x0F;
16
17
  fifo_read.address = XMEM_OFFSET;
18
  fifo_read.bank = 0;
19
20
  fifo_write.address = XMEM_OFFSET;
21
  fifo_write.bank = 0;
22
}
23
24
void fifo_putc(char c){
25
  PORTF = (fifo_write.bank << 4) | (PORTF & 0x0F);
26
  *((char*) fifo_write.address) = c;
27
28
  if(++fifo_write.address == XMEM_BANK_SIZE+XMEM_OFFSET){
29
    fifo_write.address = XMEM_OFFSET;
30
    if(++fifo_write.bank == 0x10)
31
      fifo_write.bank = 0;
32
  }
33
}
34
35
char fifo_getc(void){
36
  PORTF = (fifo_read.bank << 4) | (PORTF & 0x0F);
37
  uint8_t rtrn = *((char*) fifo_read.address);
38
39
  if(++fifo_read.address == XMEM_BANK_SIZE+XMEM_OFFSET){
40
    fifo_read.address = XMEM_OFFSET;
41
    if(++fifo_read.bank == 0x10)
42
      fifo_read.bank = 0;
43
  }
44
45
  return rtrn;
46
}
47
48
int main(void){
49
  uint16_t c;
50
51
  sei();
52
53
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU));
54
  fifo_init();
55
56
  fdevopen(uart_putc, NULL);
57
58
  while(1){
59
    c = uart_getc();
60
    
61
    if(!(c & UART_NO_DATA)){
62
      if((char) c != '#'){
63
        fifo_putc((char)c);
64
        uart_putc('X');
65
      }
66
      else{
67
        printf("End-Zeichen erhalten!\n");
68
        break;
69
      }
70
    }
71
  }
72
  
73
  for(uint8_t i=0; i<100; i++){
74
    printf("Zeichen %d: %c\n", i, fifo_getc());
75
  }
76
77
  return 0;
78
79
}

Danke und Gruß
Sven

von Karl H. (kbuchegg)


Lesenswert?

Häng entweder deine Ausgabe noch mit in die Endlosschleife mit rein, 
oder mach noch eine Endlosschleife hinter deine Ausgabe.

Dein Programm darf main() nie verlassen!
Tut es dass, dann sorgt die C-Runtime dafür, dass zb Interrupts 
abgeschaltet werden und damit steht dann auch deine Ausgabefunktion, die 
die Zeichen im Hintergrund per Interrupt an den Mann bringt.

Die bessere Lösung ist es, wenn du dich daran gewöhnst, dass sich deine 
Programmlogik immer innerhalb der einzigen
1
  while( 1 ) {
2
3
    ....
4
  }

Schleife in main abspielt. Und zwar nur dort! Ein µC beendet sein 
Programm nie!
Auch wenn das heißt, dass du deinen jetzigen Code dazu etwas umbauen 
musst.

von Sven S. (schwerminator)


Lesenswert?

Hoppla! Ich danke dir :)

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.