Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
181 andfri 1
#include "bios_funs.h"
223 andfri 2
#include "avr_cfg.h"
181 andfri 3
#include <inttypes.h>
228 andfri 4
#include <avr/io.h>
181 andfri 5
#include <avr/interrupt.h>
223 andfri 6
#include <avr/wdt.h>
181 andfri 7
#include <avr/pgmspace.h>
8
#include <stdio.h>
228 andfri 9
#include "flash.h"
240 andfri 10
#include "vectors.h" // Must be included after sfr_defs.h but before any ISR()
11
#include "can.h"
181 andfri 12
 
248 arune 13
#define FUNCTmask       0x1E000000
14
#define FUNCTshift      25
15
#define FUNCCmask       0x01FF8000
16
#define FUNCCshift      15
17
#define NIDmask         0x00007E00
18
#define NIDshift        9
19
#define SIDmask         0x000001FF
20
#define SIDshift        0
21
 
22
#define FUNCTbios       0x00
23
 
24
#define FUNCCstartprg   0x81
25
#define FUNCCprgdata    0x82
26
#define FUNCCstopprg    0x83
27
 
28
#define PRG_STATE_IDLE          0
29
#define PRG_STATE_PROGRAMMING   1
30
 
31
 
181 andfri 32
//---------------------------------------------------------------------------
223 andfri 33
// Globals
34
 
35
volatile long gMilliSecTick;
36
 
37
//---------------------------------------------------------------------------
181 andfri 38
// Function definitions for the exported interface
39
 
223 andfri 40
void reset(void) {
41
    //Just loop and let the watchdog reset
42
    cli();
43
    while(1);
44
};
45
 
46
void bios_putchar(char c) {
228 andfri 47
    UART_PUTCHAR(c);
181 andfri 48
};
49
 
223 andfri 50
char bios_getchar(void) {
228 andfri 51
    char c;
52
    UART_GETCHAR(c)
53
    return c;
181 andfri 54
};
55
 
223 andfri 56
long timebase_get(void) {
57
    uint8_t sreg;
58
    long res;
59
 
60
    //Disable interrupts while reading tick count
61
    sreg=SREG;
62
    cli();
63
 
64
    res = gMilliSecTick;
65
 
66
    SREG=sreg;
67
 
68
    return res;
69
}
181 andfri 70
 
71
//---------------------------------------------------------------------------
72
// Function definitions for the private functions
223 andfri 73
 
74
static int console_getchar(FILE *stream) {
228 andfri 75
    return bios_getchar();
223 andfri 76
}
77
 
78
static int console_putchar(char c, FILE *stream) {
228 andfri 79
    bios_putchar(c);
223 andfri 80
    return 0;
81
}
82
 
83
static FILE bios_stdio = FDEV_SETUP_STREAM(console_putchar, console_getchar,
181 andfri 84
                                         _FDEV_SETUP_RW);
85
 
223 andfri 86
 
87
//---------------------------------------------------------------------------
88
// Interrupt Service Routines
89
// Read app_vectors.h!
90
 
91
ISR(TIMEBASE_VECTOR) {
92
    TIMEBASE_COUNTER -= TIMEBASE_RELOAD;
93
    gMilliSecTick++;
94
    wdt_reset();
95
}
96
 
181 andfri 97
int main() {
98
    void (*app_reset)(void) = 0;
223 andfri 99
 
181 andfri 100
    // Setup USART for debug channel
228 andfri 101
    UART_INIT();
181 andfri 102
    stdout = &bios_stdio;
103
    stdin = &bios_stdio;
104
 
223 andfri 105
    // Initialize a suitable hardware timer to create a 1KHz interrupt.
106
    TIMEBASE_INIT();
107
 
108
    // Enable watchdog timer to protect against an application locking the
109
    // node by leaving interrupts disabled. 
110
    wdt_enable(WDTO_500MS);
111
 
112
    // Move interrupt vectors to start of bootloader section and enable interrupts
228 andfri 113
    IVSEL_REG = _BV(IVCE);
114
    IVSEL_REG = _BV(IVSEL);
223 andfri 115
    sei();
116
 
181 andfri 117
    printf("AVR BIOS\n");
118
 
223 andfri 119
 
240 andfri 120
    printf("CanInit...");
121
    if (Can_Init() != CAN_OK) {
122
        printf("FAILED!\n");
123
    }
124
    else {
125
        printf("OK!\n");
126
    }
127
 
128
    uint32_t timeStamp = 0;
129
 
130
    Can_Message_t txMsg;
131
    Can_Message_t rxMsg;
132
    //The databytes are just what happens to be in the memory. They are never set.
133
    txMsg.RemoteFlag = 0;
134
    txMsg.ExtendedFlag = 1;
248 arune 135
 
136
    txMsg.Id = 15;
240 andfri 137
    txMsg.DataLength = 2;
138
 
248 arune 139
    uint16_t address;
140
    uint16_t lastoffset=0x0;
141
    uint8_t prg_state=PRG_STATE_IDLE;
142
 
240 andfri 143
    uint8_t i;
144
    /* main loop */
145
    while (1) {
146
        /* service the CAN routines */
147
        Can_Service();
148
 
149
        /* send CAN message and check for CAN errors once every second */
248 arune 150
        if ((timebase_get() - timeStamp) >= 10000) {
240 andfri 151
            timeStamp = timebase_get();
248 arune 152
 
240 andfri 153
            /* send txMsg */
248 arune 154
            //txMsg.Id++;
240 andfri 155
            Can_Send(&txMsg);
248 arune 156
 
157
            if (prg_state==PRG_STATE_IDLE) {
158
                if (pgm_read_word(0) != 0xffff) {
159
                    printf("Starting application.\n");
160
                    app_reset();
161
                }
162
                printf("No application found.\n");
163
            }
240 andfri 164
        }
165
 
166
        /* check if any messages have been received */
167
        while (Can_Receive(&rxMsg) == CAN_OK) {
168
            printf("BIOS Received: ID=%lx, DLC=%u, EXT=%u, RTR=%u, ", rxMsg.Id, (uint16_t)(rxMsg.DataLength), (uint16_t)(rxMsg.ExtendedFlag), (uint16_t)(rxMsg.RemoteFlag));
169
            printf("data={ ");
170
            for (i=0; i<rxMsg.DataLength; i++) {
171
                printf("%x ", rxMsg.Data.bytes[i]);
172
            }
173
            printf("}\n");
174
 
248 arune 175
            if ((rxMsg.Id & FUNCTmask) == ((uint32_t)FUNCTbios<<FUNCTshift)) {
176
                //printf("Got 'bios package'\n");
177
                //om mottagen data är bois-data (detta borde redan filtrerats i can_receive?)
178
                if ((prg_state==PRG_STATE_IDLE) && ((rxMsg.Id & FUNCCmask) == ((uint32_t)FUNCCstartprg<<FUNCCshift)) && (rxMsg.DataLength == 6)) {
179
                    //om mottagen data har funktionskoden starta programmering
180
 
181
                    //ska kolla om nod-id i IDENT stämmer med nodens id
182
                    //om ok:
183
                    prg_state=PRG_STATE_PROGRAMMING;
184
                    address = rxMsg.Data.bytes[2];
185
                    address |= rxMsg.Data.bytes[3];
186
                    printf("Got 'start programming' at address %x\n", address);
187
                } else if (prg_state==PRG_STATE_PROGRAMMING) {
188
                    if ((rxMsg.Id & FUNCCmask) == ((uint32_t)FUNCCprgdata<<FUNCCshift)) {
189
                        //om mottagen data har funktionskoden programdata
190
                        uint16_t tmpaddress = rxMsg.Data.bytes[0] + (rxMsg.Data.bytes[1] << 8);
191
                        if (tmpaddress >= lastoffset) {
192
                            tmpaddress += address;
193
                            printf("Got 'programdatapacket' at offset %x\n", tmpaddress);
194
                            for (i=2; i<rxMsg.DataLength; i+=2) {
195
                                flash_write_word(tmpaddress, rxMsg.Data.bytes[i] + (rxMsg.Data.bytes[i+1] << 8));
196
                                tmpaddress+=2;
197
                            }
198
                            printf("Setting lastoffset to %x\n", tmpaddress);
199
                            lastoffset = tmpaddress;
200
                        }
201
                    } else if ((rxMsg.Id & FUNCCmask) == ((uint32_t)FUNCCstopprg<<FUNCCshift)) {
202
                        flash_flush_buffer();
203
                        prg_state=PRG_STATE_IDLE;
204
                        lastoffset=0x0;
205
                        //beräkna crc på all programdata mellan address och address+lastoffset
206
                        printf("Got 'end programming'\n");
207
                    }
208
                }
209
            }
210
 
211
            //if (rxMsg.Id % 20 == 19) reset();
240 andfri 212
        }
213
    }
214
 
181 andfri 215
    return 0;
216
}