PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Inkonsistente Variable auf ATmega644



Trabukh
16.06.2010, 06:46
Moin,

bei meinem Versuch, einen Kartenleser für einfache Speicherkarten zu entwerfen, bin ich über ein Softwareproblem gestolpert. Es scheint, als würde mein Array mem_main sich ständig verändern.

Hier der Code (relevanter Ausschnitt):

#include <avr/io.h>
#include <util/delay.h>

#include "uart.h"

#define SM_RST PC0
#define SM_CLK PC1
#define SM_IO PC2
#define SM_PORT PORTC
#define SM_PIN PINC
#define SM_DDR DDRC

unsigned char mem_main[256];

int main() {
uart_init();
sm_init();

sm_read();

for (;; _delay_ms(1000)) {
for (unsigned int i = 0; i < 256; i++) {
uart_putc(mem_main[i]);
}
}

return 0;
}

void sm_init() {
SM_DDR = (1 << SM_RST) | (1 << SM_CLK);
SM_DDR &= ~(1 << SM_IO);
SM_PORT = (1 << SM_IO);
}

void sm_read() {
sm_command(0x30, 0x00, 0x00); // Kommando zum Lesen senden
SM_PORT &= ~(1 << SM_CLK);
SM_DDR &= ~(1 << SM_IO);
SM_PORT |= (1 << SM_IO);
_delay_us(100);

for (unsigned int i = 0; i < 256; i++) { // Byte-Schleife
unsigned char temp_byte; // Temporäres Byte
for (unsigned char k = 0; k < 8; k++) { // Bit-Schleife
SM_PORT |= (1 << SM_CLK); // Taktleitung auf H setzen
if (SM_PIN & (1 << SM_IO)) // I/O-Pin abfragen
temp_byte |= (1 << k);
_delay_us(100);
SM_PORT &= ~(1 << SM_CLK); // Taktleitung auf L setzen
_delay_us(100);
}
mem_main[i] = temp_byte; // Temporäres Byte in Hauptspeicher schreiben
}
}

void uart_init() {
UBRR0H = (unsigned char) (UBRR_VAL >> 8);
UBRR0L = (unsigned char) (UBRR_VAL);
UCSR0B = (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Asynchron 8N1
}

void uart_putc(unsigned char c) {
while (!(UCSR0A & (1 << UDRE0))) {
}
UDR0 = c;
}

Seltsamerweise ändern sich vereinzelte Bytes in mem_main[...] anscheinend bei jeder Ausführung von print_mem(), obwohl keine schreibenden Zugriffe mehr stattfinden. Was könnte ich übersehen haben?

TobiKa
16.06.2010, 07:27
Hi

Ich sehe kein print_mem.
Vielleicht mal ein "volatile unsigned char mem_main[256];"
Vielleicht solltest du die Variable nicht nur deklarieren sondern auch initialisieren.

"for (;; _delay_ms(1000))" das meinst du nicht ernst oder?

Trabukh
16.06.2010, 10:34
Erstmal vielen Dank für die Antwort.

Ich sehe kein print_mem.Stimmt, ist beim Zusammenkopieren für das Minimalbeispiel abhanden gekommen, sorry... O:)

Also der bisherige Code sieht so aus:

#include <avr/io.h>
#include <util/delay.h>

#include "reader.h"
#include "uart.h"
#include "smartcard.h"

volatile unsigned char mem_main[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

int main() {
uart_init();
sm_init();
_delay_us(100);

sm_read(); // Dummy readout
_delay_us(500);

sm_read();

for (;; _delay_ms(1000)) {
print_mem();
}

return 0;
}

void sm_init() {
SM_DDR = (1 << SM_RST) | (1 << SM_CLK);
SM_PORT = (1 << SM_IO);
}

void sm_command(unsigned char b, unsigned char a, unsigned char d) {
// gekürzt
}

void sm_read() {
sm_command(0x30, 0x00, 0x00);
SM_PORT &= ~(1 << SM_CLK);
SM_DDR &= ~(1 << SM_IO);
SM_PORT |= (1 << SM_IO);
_delay_us(100);

for (unsigned int byte = 0; byte < 256; byte++) { // Byte-Schleife
unsigned char temp_byte = 0x00; // Temporäres Byte
for (unsigned char bit = 0; bit < 8; bit++) { // Bit-Schleife
SM_PORT |= (1 << SM_CLK); // Taktleitung auf H setzen
if (SM_PIN & (1 << SM_IO)) // I/O-Pin abfragen
temp_byte |= (1 << bit);
_delay_us(100);
SM_PORT &= ~(1 << SM_CLK); // Taktleitung auf L setzen
_delay_us(100);
}
mem_main[byte] = temp_byte; // Temporäres Byte in Hauptspeicher schreiben
}
}

void uart_init() {
// gekürzt
}

void uart_putc(unsigned char c) {
// gekürzt
}

void print_mem() {
for (unsigned int i = 0; i < 256; i++) {
uart_putc(mem_main[i]);
}
}

Ich habe deine Vorschläge umgesetzt, leider ohne Ergebnis. Die Hex Dumps sehen z.B. so aus:

Erster Aufruf von print_mem():
0000: A2 13 10 91 46 0B 81 15 - 42 45 00 23 09 05 5E 2F
0010: 2E AA FF FF FF D2 76 00 - 00 63 01 FF FF FF FF FF
0020: 30 30 30 39 32 36 30 30 - 30 30 30 30 00 00 00 A8
0030: 64 64 00 01 00 B6 E4 D6 - 18 00 3F 02 FF FF FF FF
0040: 11 56 7C 07 04 01 12 58 - 04 0D 00 92 58 08 A0 B2
0050: 4F 00 18 03 04 0D 00 4D - 4A 00 E4 4D 08 00 15 59
0060: 04 0E 12 80 05 32 06 90 - 27 08 14 25 04 0D 00 AC
0070: 05 00 4A 08 00 09 12 24 - 04 0D 00 08 00 00 FD 4E
0080: 08 00 16 00 00 10 00 00 - 00 49 00 90 06 11 15 58
0090: 03 03 14 80 01 00 08 90 - FF FF FF FF FF FF FF FF
00A0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00B0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00C0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00D0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00E0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00F0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF

Zweiter Aufruf von print_mem():
0000: A2 13 10 91 46 0B 81 15 - 42 45 00 23 09 05 5E 2F
0010: 2E AA FF FF FF D2 76 00 - 00 00 00 FF FF FF FF FF
0020: 30 30 30 39 32 36 30 30 - 30 30 30 30 00 00 E0 4C
0030: 08 64 00 4E 08 17 E4 D6 - 18 00 AC 4D 08 00 FF FF
0040: 11 56 7C 07 04 01 12 58 - 04 0D 00 00 A0 21 59 08
0050: A0 B2 4F 00 18 0D 00 52 - 05 00 52 90 05 08 15 59
0060: 04 0E 12 80 05 32 06 90 - 27 08 14 25 04 0D 00 80
0070: 05 00 06 90 01 09 12 24 - 04 0D 00 00 00 00 06 90
0080: 02 11 18 22 03 0B 28 80 - 03 32 06 90 06 11 15 58
0090: 03 03 14 80 01 00 06 90 - FF FF FF FF FF FF FF FF
00A0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00B0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00C0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00D0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00E0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
00F0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF
Eine ganze Reihe an Bytes unterscheidet sich leider.


"for (;; _delay_ms(1000))" das meinst du nicht ernst oder?
Ähm, das war nur auf die Schnelle zum Testen... :-b

sternst
16.06.2010, 12:18
"for (;; _delay_ms(1000))" das meinst du nicht ernst oder?Was bitte soll denn daran auszusetzen sein?


@ Trabukh:

Welcher Controller?
Und den Code für uart_init und uart_putc würde ich auch gerne mal sehen.

TobiKa
16.06.2010, 12:22
Der Code der Funktionen steht oben im ersten Post!

sternst
16.06.2010, 12:47
Der Code der Funktionen steht oben im ersten Post!Ups, übersehen. Ich habe nur unter dem "Also der bisherige Code sieht so aus:" die "gekürzt" gesehen.

EDIT: Und der Controller-Typ steht im Titel. Nicht mein Tag. ;-)

Ich vermute, dass gar nicht wirklich der immer gleiche Speicherinhalt in einer Endlosschleife ausgegeben wird, sondern dass es zwischendurch einen Reset gibt, und dass sich die damit immer neu von der Karte gelesenen Daten unterscheiden. Meine erste Vermutung "Interrupt ohne ISR" hat sich nicht bestätigt. Nächster Versuch: Watchdog?

Trabukh
16.06.2010, 15:32
Leider trifft beides nicht zu. Ich habe aus Jux einfach mal nach dem ersten Aufruf von print_mem() die Speicherkarte herausgezogen, am Ausgang meiner "Experimente" hat das jedoch nichts geändert.

Watchdog habe ich sicherheitshalber auch nochmal überprüft, der ist definitiv aus.

EDIT: Folgender Code läuft im Übrigen anstandlos:

// µC: ATmega644

#include <util/delay.h>
#include <avr/io.h>

#ifndef F_CPU
#define F_CPU 14745600UL
#endif
#define BAUD 9600UL
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)

volatile unsigned char mem_main[256];

int main() {
uart_init();

for (unsigned int i = 0; i < 256; i++) {
mem_main[i] = i;
}

for (;; _delay_ms(1000)) {
for (unsigned int i = 0; i < 256; i++) {
uart_putc(mem_main[i]);
}
}
return 0;
}

void uart_init() {
UBRR0H = (unsigned char) (UBRR_VAL >> 8);
UBRR0L = (unsigned char) (UBRR_VAL);
UCSR0B = (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Asynchron 8N1
}

void uart_putc(unsigned char c) {
while (!(UCSR0A & (1 << UDRE0))) {
}
UDR0 = c;
}

EDIT 2: Wenn ich in meinem Programm die Baudrate auf 300 Stelle, scheint alles korrekt anzukommen. Wie kann sowas sein? :-s

EDIT 3: Zugegeben, ein dritter Edit ist schon peinlich, aber ich wurde das ungute Gefühl nicht los, dass mein Terminalprogramm nichts taugt. Die Vermutung hat sich bestätigt, mit hTerm funktioniert alles, wie es soll. #-o
Ich bitte somit um Verzeihung, dass an der völlig falschen Stelle gesucht werde und danke euch beiden für eure Hilfe. 8-[

TobiKa
16.06.2010, 22:45
Mich wundert das nur ein Teil der Variable falsch übertragen wird...

Wie dem auch sei, ich benutze auch HTerm und das ist einfach das beste.