Problem mit simplem FiFo

OP #1979075
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
#1979105
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren