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>
4
#include <avr/interrupt.h>
223 andfri 5
#include <avr/wdt.h>
6
#include <avr/boot.h>
181 andfri 7
#include <avr/pgmspace.h>
8
#include <avr/io.h>
9
#include <stdio.h>
223 andfri 10
#include "app_vectors.h"
181 andfri 11
 
12
//---------------------------------------------------------------------------
223 andfri 13
// Globals
14
 
15
volatile long gMilliSecTick;
16
 
17
//---------------------------------------------------------------------------
181 andfri 18
// Function definitions for the exported interface
19
 
223 andfri 20
void reset(void) {
21
    //Just loop and let the watchdog reset
22
    cli();
23
    while(1);
24
};
25
 
26
void bios_putchar(char c) {
225 arune 27
    #if defined(__AVR_ATmega8__)
181 andfri 28
    loop_until_bit_is_set(UCSRA, UDRE);
29
    UDR = c;
225 arune 30
    #elif defined(__AVR_ATmega88__)
31
    loop_until_bit_is_set(UCSR0A, UDRE0);
32
    UDR0 = c;
33
    #endif
181 andfri 34
};
35
 
223 andfri 36
char bios_getchar(void) {
225 arune 37
    #if defined(__AVR_ATmega8__)
181 andfri 38
    loop_until_bit_is_set(UCSRA, RXC);
39
    return UDR;
225 arune 40
    #elif defined(__AVR_ATmega88__)
41
    loop_until_bit_is_set(UCSR0A, RXC0);
42
    return UDR0;
43
    #endif
181 andfri 44
};
45
 
223 andfri 46
long timebase_get(void) {
47
    uint8_t sreg;
48
    long res;
49
 
50
    //Disable interrupts while reading tick count
51
    sreg=SREG;
52
    cli();
53
 
54
    res = gMilliSecTick;
55
 
56
    SREG=sreg;
57
 
58
    return res;
59
}
181 andfri 60
 
61
//---------------------------------------------------------------------------
62
// Function definitions for the private functions
223 andfri 63
 
64
static uint16_t flash_prev_addr;
65
 
66
void flash_flush_buffer() {
181 andfri 67
    uint8_t sreg;
223 andfri 68
 
181 andfri 69
    // Disable interrupts.
223 andfri 70
 
181 andfri 71
    sreg = SREG;
72
    cli();
223 andfri 73
 
74
    eeprom_busy_wait();
75
 
76
    boot_page_erase(flash_prev_addr);
77
    boot_spm_busy_wait();      // Wait until the memory is erased.
78
 
79
    boot_page_write(flash_prev_addr);     // Store buffer in flash page.
181 andfri 80
    boot_spm_busy_wait();       // Wait until the memory is written.
81
 
82
    // Reenable RWW-section again. We need this if we want to jump back
83
    // to the application after bootloading.
84
 
85
    boot_rww_enable ();
86
 
87
    // Re-enable interrupts (if they were ever enabled).
88
 
89
    SREG = sreg;
90
}
91
 
223 andfri 92
void flash_load_buffer(uint16_t addr) {
93
    //TODO: Load current flash page contents into temporary buffer to implement
94
    // flash read-modify-writes with word granularity. (If possible, the data
95
    // sheet is a little fuzzy about this.)
96
}
97
 
98
void flash_write_word(uint16_t addr, uint16_t word) {
99
 
100
    if ((addr / SPM_PAGESIZE) != (flash_prev_addr / SPM_PAGESIZE)) {
101
        flash_flush_buffer();
102
        flash_load_buffer(addr);
103
    }
104
 
105
    boot_page_fill(addr, word);
106
    flash_prev_addr = addr;
107
}    
108
 
109
void flash_init() {
110
    flash_prev_addr = 0xffff;
111
}
112
 
113
static int console_getchar(FILE *stream) {
114
    return bios->can_receive();
115
}
116
 
117
static int console_putchar(char c, FILE *stream) {
118
    bios->can_send(c);
119
    return 0;
120
}
121
 
122
static FILE bios_stdio = FDEV_SETUP_STREAM(console_putchar, console_getchar,
181 andfri 123
                                         _FDEV_SETUP_RW);
124
 
223 andfri 125
 
126
//---------------------------------------------------------------------------
127
// Interrupt Service Routines
128
// Read app_vectors.h!
129
 
130
ISR(TIMEBASE_VECTOR) {
131
    TIMEBASE_COUNTER -= TIMEBASE_RELOAD;
132
    gMilliSecTick++;
133
    wdt_reset();
134
}
135
 
181 andfri 136
int main() {
137
    void (*app_reset)(void) = 0;
223 andfri 138
 
181 andfri 139
    // Setup USART for debug channel
225 arune 140
    #if defined(__AVR_ATmega8__)
181 andfri 141
    UCSRB = _BV(RXEN)|_BV(TXEN);
142
    UBRRL = (F_CPU / 16 / F_BAUD) - 1;
225 arune 143
    #elif defined(__AVR_ATmega88__)
144
    UCSR0B = _BV(RXEN0)|_BV(TXEN0);
145
    UBRR0L = (F_CPU / 16 / F_BAUD) - 1;
146
    #endif
181 andfri 147
    stdout = &bios_stdio;
148
    stdin = &bios_stdio;
149
 
223 andfri 150
    // Initialize a suitable hardware timer to create a 1KHz interrupt.
151
    TIMEBASE_INIT();
152
 
153
    // Enable watchdog timer to protect against an application locking the
154
    // node by leaving interrupts disabled. 
155
    wdt_enable(WDTO_500MS);
156
 
157
    // Move interrupt vectors to start of bootloader section and enable interrupts
225 arune 158
    #if defined(__AVR_ATmega8__)
223 andfri 159
    GICR = _BV(IVCE);
160
    GICR = _BV(IVSEL);
225 arune 161
    #elif defined(__AVR_ATmega88__)
162
    MCUCR = _BV(IVCE);
163
    MCUCR = _BV(IVSEL);
164
    #endif
223 andfri 165
    sei();
166
 
181 andfri 167
    printf("AVR BIOS\n");
168
 
223 andfri 169
    if (pgm_read_word(0) != 0xffff) {
170
        printf("Starting application.\n");
171
        app_reset();
172
    }
173
 
174
    printf("No application found.\n");
181 andfri 175
    return 0;
176
}