Ich bastel immer noch an meinem twi rum. Nachdem er sich eh bei der
Benutzung der Atmel ASF routinen nach einer gewissen Laufzeit aufhängt
versuche ich seit gestern das senden von Bytes interrupt basiert zu
lösen.
Nachdem ich die routinen eigentlich schon trocken vorgeschrieben hatte,
habe ich das Ganze wieder auf ein Minimum reduzieren müssen, da ich
schon ein grundlegendes Problem habe.
Sobald ich (nach initialisierung des NVIC und des TWI) das interrupt
enable register (IER) beschreibe und dort die Flags TXCOMP und TXRDY
setze bleibt der Prozessor immer in dem TWI0_Handler. Der nachfolgende
Code wird nicht mehr ausgeführt. Steppe ich allerdings im
einzelschrittmodus beim Debuggen durch, wird auch der nachfolgende Code
ausgeführt. Sonst nicht.
Die Flags TXCOMP und TXRDY sind natürlich (automatisch) gesetzt im
Status Register (SR). Aber kommt deshalb der Interrupt andauernt? Ist
das so gedacht? Soll man den in der Handler disabeln und zum Ende des
Handlers, wenn man auf ein bestimmtes Flag wartet, wieder einschalten?!
Ich dachte eher, dass wenn eine !Änderung! im SR vorhanden ist der
Interrupt (wenn die Maske übereinstimmt) auslöst und ich dann das SR
auslese und "gucke" was passiert ist. Und erst dann der nächste
Interrupt ausgelöst wird, wenn sich das SR ändert!
Muss ich den interrupt noch irgendwie bestätigen?! Eigentlich ja nicht
oder? Meine timer interrupts etc. funktionieren ja auch tadellos. Nur
bei dem TWI ist es irgendwie verrückt.
Atmel selbst hält sich auch ziemlich bedeckt im Datenblatt was den TWI
mit Interrupts angeht. Demnach ist es einfach (was ich auch bis gestern
Mittag dachte).
Hier der Code
1 | void TWI0_Handler (void){
|
2 | uint32_t twi_status;
|
3 | twi_status = TWI0->TWI_SR;
|
4 | }
|
5 |
|
6 |
|
7 | int main (void)
|
8 | {
|
9 | enum {IDLE,TX_START,TX_WAIT,RX_WAIT,TX_CMPL,RX_CMPL};
|
10 | uint32_t twi0_state = IDLE;
|
11 | sysclk_init();
|
12 | board_init();
|
13 |
|
14 | NVIC_DisableIRQ(TWI0_IRQn);
|
15 | NVIC_ClearPendingIRQ(TWI0_IRQn);
|
16 | NVIC_SetPriority(TWI0_IRQn , 0);
|
17 | NVIC_EnableIRQ(TWI0_IRQn);
|
18 |
|
19 | twi_master_options_t opt_bus1 = {
|
20 | .speed = 50000,
|
21 | .chip = I2C_BUS0_ADDR_U1,
|
22 | .smbus = 0,
|
23 | .master_clk = sysclk_get_peripheral_bus_hz(TWI0)
|
24 | };
|
25 |
|
26 | twi_master_setup(TWI0, &opt_bus1);
|
27 |
|
28 |
|
29 | //twi_init(); //BUS0 und 1
|
30 | TWI0->TWI_IER = TWI_IER_NACK | TWI_IER_TXCOMP | TWI_IER_TXRDY;
|
31 | //hier kommt der Interrupt, nachstehender Code wird nicht mehr erreicht.
|
32 | twi0_state = IDLE;
|
33 |
|
34 | if (twi_load_write_buffer1()){
|
35 | if (twi0_state == IDLE){
|
36 | twi0_state = TX_START;
|
37 | twi_write_trigger_next_transmission(TWI0);
|
38 | }
|
39 | }
|
40 |
|
41 | while(1){
|
42 |
|
43 | }
|