Forum: Mikrocontroller und Digitale Elektronik AVR, Atmega644 SPI im Bootloader kein output


von Florian (tuxlein)


Lesenswert?

Hallo Ihr,

ich verwende schon länger den CAN-Bus Bootloader von Fabian Greif und 
hab ihn erweitert.
Hauptsächlich verwende ich die ATMEGA328 und jetzt habe ich ihn auf den 
ATmega644 und 1282 erweitern wollen nur leider kommen keine Daten aus 
dem SPI raus (Oszi).

Ich habe mal die spi_putc ausgelagert in eine C-Funktion um mit LED 
auszugeben was sache ist. Habe auch die Register SPCR überprüft ob diese 
anderst stehen es ist aber so wie gewolt.

So schwer ist doch der SPI nicht ist doch super simple. Ach ich habe 
einen Externen 16 MHz Quarz, aber auch mit dem Internen funktioniert es 
nicht. Es wird einfach keine Daten rausgeschoben auf der SPI 
Schnitstelle, die LED und CS Funktionieren.

Das lustige an dem Ganzen ist ja das mein eigentliches Programm über 
CAN-Bus wie es soll kommuniziert und hier ist die Initalisierung auch 
nicht wirklich anderst.

Hier die Fuse Bits: (E:FF, H:12, L:F7)

Vielen dank schon mal für eure Hilfe und Zeit.

Hier mal der Code von mir:
1
void boot(void) \
2
    __attribute__((naked)) \
3
    __attribute__((section(".vectors")));
4
5
void boot(void)
6
{
7
  __asm__ __volatile__ ("rjmp  init" "\n\t");
8
}
9
10
// ----------------------------------------------------------------------------
11
void
12
init(void) \
13
    __attribute__((naked)) \
14
    __attribute__((section(".init3")));
15
16
void init(void)
17
{
18
    uint8_t status;
19
    uint16_t temp;
20
  // Clear r1 (__zero_reg__) and initialize the stack
21
  __asm__ __volatile__ (
22
      "eor  r1, r1"    "\n\t"
23
      "out  0x3f, r1"  "\n\t"
24
      "ldi  r28, 0xFF" "\n\t"
25
      "ldi  r29, 0x04" "\n\t"
26
      "out  0x3e, r29" "\n\t"
27
      "out  0x3d, r28" "\n\t");
28
  
29
#ifdef GPIOR0
30
  // Save MCUSR so that the main program can access if later
31
  GPIOR0 = MCUSR;
32
#endif
33
34
    status = MCUSR;                    // save MCUC(S)R reset status at very first
35
    MCUSR = status & 0xF0;             // then clear reset status, before touching the watchdog
36
  
37
  // Disable the watchdog timer
38
  // see http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html
39
  // 
40
  // The orignal implementation uses additional commands to disable
41
  // interrupts. As we never enable interrupts this is not needed here.
42
  __asm__ __volatile__ (  \
43
      "sts %0, %1" "\n\t" \
44
      "sts %0, __zero_reg__" "\n\t" \
45
       : /* no outputs */ \
46
       : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
47
         "r" ((uint8_t) ((1 << _WD_CHANGE_BIT) | (1 << WDE))) \
48
       : "r0");
49
50
    MCUCR = (1<<IVCE);                 // enable interruptvectors change
51
    MCUCR = (1<<IVSEL);                // move interruptvectors to the Boot-Sector
52
}
53
54
// ----------------------------------------------------------------------------
55
int main(void) __attribute__((naked)) \
56
    __attribute__((section(".init9")));
57
58
int main(void) 
59
....
60
61
uint8_t spi_putc_c(uint8_t data)
62
{
63
   // put byte in send-buffer
64
    SPDR = data;
65
    
66
    // wait until byte was send
67
    while( !( SPSR & (1 << SPIF) ) )
68
    {
69
        BOOT_LED2_TOGGLE;
70
        if( SPDR != data )
71
        {
72
            SPDR = data;
73
            BOOT_LED_OFF;
74
        }
75
        else
76
        {
77
            BOOT_LED_ON;
78
        }
79
        _delay_ms(100);
80
    }
81
    
82
    return SPDR;
83
}
84
85
86
void mcp2515_init(void)   _attribute__((naked))           __attribute__((section(".init5")));
87
void mcp2515_init(void)
88
{
89
        BOOT_LED2_SET_OUTPUT;
90
  BOOT_LED_SET_OUTPUT;
91
        BOOT_LED_ON;
92
        BOOT_LED2_ON;
93
94
        uart_puts( "Hallo\r\n" );
95
96
  // Aktivieren der Pins fuer das SPI Interface
97
  DDRB = _BV( DDB2 ) | _BV( DDB5 ) | _BV( DDB7 );
98
        
99
        SET(MCP2515_CS);
100
101
        BOOT_LED_OFF;
102
  
103
  // Aktivieren des SPI Master Interfaces
104
  SPCR = 0x91;//(1 << SPIE)  | (1 << SPE) | (1 << MSTR) |  ( 1 << SPR0 ) | (1 << CPHA); //R_SPCR;
105
  SPSR = 0; //R_SPSR;
106
  
107
  _delay_us(250);
108
109
  // MCP2515 per Software Reset zuruecksetzten,
110
  // danach ist er automatisch im Konfigurations Modus
111
  RESET(MCP2515_CS);
112
  spi_putc_c(SPI_RESET);
113
  _delay_us(10);
114
  SET(MCP2515_CS);
115
.......

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

> SPCR = 0x91;//(1 << SPIE)  | (1 << SPE) | (1 << MSTR) |
>  ( 1 << SPR0 ) | (1 << CPHA); //R_SPCR;

In der Konstanten stehen 3 Bits, im Kommentar jedoch 5?
  Und ja, SPE wird nicht gesetzt.

(Den ganzen Rest habe ich mir nicht näher angeschaut - zu ungewohnt, um 
es vorsichtig auszudrücken)

von Peter D. (peda)


Lesenswert?

Florian schrieb:
> Es wird einfach keine Daten rausgeschoben auf der SPI
> Schnitstelle

Standardfehler ist, /SS nicht vor allen anderen als Ausgang zu setzen.

von Peter D. (peda)


Lesenswert?

Florian schrieb:
> SPCR = 0x91;//(1 << SPIE)  | (1 << SPE) | (1 << MSTR) |  ( 1 << SPR0 ) |
> (1 << CPHA); //R_SPCR;

Wer macht denn solchen Blödsinn, lesbare Ausdrücke durch magische 
Nummern zu ersetzen?
Da kannst Du keine Hilfe erwarten.

von Florian (tuxlein)


Lesenswert?

Peter D. schrieb:
> Wer macht denn solchen Blödsinn, lesbare Ausdrücke durch magische
> Nummern zu ersetzen?
> Da kannst Du keine Hilfe erwarten.

sehr schön, dann weis ich ja wer keine Fehler macht und wo ich was 
lernen kann.
Danke für die Sachliche Antwort.

Hier handelt es sich um SPI Master und CS wird als erstes gesetzt. Wie 
ich geschrieben habe habe ich schon länger SPI im einsatz und der 
Bootloader lief auf dem Atmega328/168...

Danke für den Hinweis, ich habe das hard codiert, da es durch das setzen 
der einzelnen Bits auch nicht ging. Wie es auch immer noch nicht geht. 
In meiner eigentlichen Firmware funktioniert der SPI-CAN Chip wie er 
soll somit ist es nicht die Hardware.

Es wird das WCOL bit gesetzt und es gibt auf den SPI Pins auch kein 
Signal , das habe ich davor ausgetestet. Wie gesagt der Bootloader 
setzte ich schon lange ein bei einigen Modulen nur mit dem mega328/168.

Weiter man sieht wie der SPI die MOSI und SPI in anspruch nimmt 
(High-Low-High) je nachdem wie man es setzt war als test selbst high 
getrieben.
Auf der SCK gibt es kein Signal.

Was mich wundert, dass es auf meiner FW ohne Probleme läuft nur im 
Bootloader gibt es mit dem 644 problme mit dem 328 geht es einwandfrei.
1
  SET_OUTPUT(MCP2515_CS);
2
  SET(MCP2515_CS);
3
4
  PORT_SPI &=  ~((1 << PIN_NUM(P_SCK)) | (1 << PIN_NUM(P_MOSI)));
5
  DDR_SPI |= (1 << PIN_NUM(P_SCK)) | (1 << PIN_NUM(P_MOSI));
6
       
7
  SET(MCP2515_CS);
8
        BOOT_LED_OFF;
9
  
10
  SPCR =  (1 << SPIE) | (1 << SPE) | (1 << MSTR); //R_SPCR;
11
  SPSR = _BV( SPI2X );

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Florian schrieb:
> Hier handelt es sich um SPI Master und CS wird als erstes gesetzt.

Ich sprach aber von /SS (= PB4).

Florian schrieb:
> Es wird das WCOL bit gesetzt

Dann machst Du was falsch. Mehr kann man ohne Code nicht dazu sagen.

Warum zeigst Du nicht einfach den realen, compilierbaren Code als 
Anhang, anstatt diese zusammenhanglosen Schnipselchen im Post.

Beitrag #7405923 wurde vom Autor gelöscht.
Beitrag #7405931 wurde vom Autor gelöscht.
von Peter D. (peda)


Lesenswert?

15.3.2 Master Mode
When the SPI is configured as a Master (MSTR in SPCR is set), the user 
can determine the direction of the SS pin.
If SS is configured as an output, the pin is a general output pin which 
does not affect the SPI system. Typically, the pin will be driving the 
SS pin of the SPI Slave.
If SS is configured as an input, it must be held high to ensure Master 
SPI operation. If the SS pin is driven low by peripheral circuitry when 
the SPI is configured as a Master with the SS pin defined as an input, 
the SPI system interprets this as another master selecting the SPI as a 
slave"

von S. L. (sldt)


Lesenswert?

> ... wie der SPI die MOSI  ...
> Auf der SCK gibt es kein Signal.

Dann nehme ich ganz naiv an, dass 'PIN_NUM(P_SCK)' nicht PB7 ist oder 
nicht auf PB7 gemessen wird.

von S. L. (sldt)


Lesenswert?

Um es überdeutlich zu formulieren (Peter Dannegger möge entschuldigen):

Im eingangs gezeigten Programmausschnitt sieht es so aus, als sei 
vergessen worden, /SS von ATmega328.PB2 auf ATmega644.PB4 umzuziehen.
  Wenn nun PB4 auf der Reset-Einstellung 'Eingang' geblieben ist und, 
wie auch immer, von außen auf Low gezogen wird, dann führt ein Laden von 
SPDR direkt zu besagtem gesetzten WCOL.

von Peter D. (peda)


Lesenswert?

Statt diesem Multimasterfeature, was ich noch nie in der Praxis irgendwo 
gesehen habe, hätte man besser einen Sendepuffer spendieren sollen, was 
insbesondere als Slave einen erheblichen Nutzen gebracht hätte.

von Florian (tuxlein)


Lesenswert?

ja hab den fehler gefunden es war wirklich der SS den ich da nicht mit 
um gezogen habe.
Offt sind die Offentlichsten dinge die am meisten Zeit kosten und wo man 
rein fällt.

@Peter D. man kann viel machen und sich überall verkünsteln und alles 
selbst Entwerfen, so dass man zu dem eigentlichen Thema kaum Zeit hat 
das alles möglich. Wie gesagt der Bootloader ist grundlegend bzw die 
Variante von Kreativen Chaos seite und bin ihm dankbar das er mir da 
Arbeit abgenommen hat.

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.