1
+ /*
2
+ MYSBootloader 1.3pre3
3
+ OTA RF24 bootloader for MySensors: http://www.mysensors.org
4
+ Based on MySensors library 2.1
5
+ Developed and maintained by tekka 2016
6
+ */
7
+
8
+ #ifndef HW_H
9
+ #define HW_H
10
+
11
+ // hardware
12
+ # define UART_SRA UCSR0A
13
+ # define UART_SRB UCSR0B
14
+ # define UART_SRC UCSR0C
15
+ # define UART_SRL UBRR0L
16
+ # define UART_UDR UDR0
17
+
18
+
19
+ #ifndef BAUD_RATE
20
+ #if F_CPU >= 16000000L
21
+ #define BAUD_RATE 115200
22
+ #elif F_CPU >= 8000000L
23
+ #define BAUD_RATE 38400L
24
+ #elif F_CPU >= 1000000L
25
+ #define BAUD_RATE 9600L
26
+ #elif F_CPU >= 128000L
27
+ #define BAUD_RATE 4800L
28
+ #else
29
+ #define BAUD_RATE 1200L
30
+ #endif
31
+ #endif
32
+
33
+ #ifndef UART
34
+ #define UART 0
35
+ #endif
36
+
37
+ #define BAUD_SETTING (( (F_CPU + BAUD_RATE * 4L) / ((BAUD_RATE * 8L))) - 1 )
38
+ #define BAUD_ACTUAL (F_CPU/(8 * ((BAUD_SETTING)+1)))
39
+ #if BAUD_ACTUAL <= BAUD_RATE
40
+ #define BAUD_ERROR (( 100*(BAUD_RATE - BAUD_ACTUAL) ) / BAUD_RATE)
41
+ #if BAUD_ERROR >= 5
42
+ #error BAUD_RATE error greater than -5%
43
+ #elif BAUD_ERROR >= 2
44
+ #warning BAUD_RATE error greater than -2%
45
+ #endif
46
+ #else
47
+ #define BAUD_ERROR (( 100*(BAUD_ACTUAL - BAUD_RATE) ) / BAUD_RATE)
48
+ #if BAUD_ERROR >= 5
49
+ #error BAUD_RATE error greater than 5%
50
+ #elif BAUD_ERROR >= 2
51
+ #warning BAUD_RATE error greater than 2%
52
+ #endif
53
+ #endif
54
+
55
+ #if (F_CPU + BAUD_RATE * 4L ) / (BAUD_RATE * 8L ) - 1 > 250
56
+ #error Unachievable baud rate (too slow) BAUD_RATE
57
+ #endif // baud rate slow check
58
+ #if (F_CPU + BAUD_RATE * 4L ) / (BAUD_RATE * 8L ) - 1 < 3
59
+ #if BAUD_ERROR != 0 // permit high bitrates (ie 1Mbps@16MHz) if error is zero
60
+ #error Unachievable baud rate (too fast) BAUD_RATE
61
+ #endif
62
+ #endif
63
+
64
+ #ifndef UART
65
+ #define UART 0
66
+ #endif
67
+
68
+
69
+ // Watchdog definitions and functions
70
+ #define WATCHDOG_OFF (0)
71
+ #define WATCHDOG_16MS (_BV(WDE))
72
+ #define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
73
+ #define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
74
+ #define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
75
+ #define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
76
+ #define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
77
+ #define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
78
+ #define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
79
+ #define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
80
+ #define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
81
+
82
+
83
+ static inline void watchdogReset () {
84
+ __asm__ __volatile__ ("wdr\n" );
85
+ }
86
+
87
+ void watchdogConfig (const uint8_t x ) {
88
+ WDTCSR = _BV (WDCE ) | _BV (WDE );
89
+ WDTCSR = x ;
90
+ }
91
+
92
+
93
+ // SPI communication
94
+ #define SPI_PORT PORTB //
95
+ #define SPI_DDR DDRB //
96
+ #define SPI_SCLK PB5 // Arduino Pin 13 <-> Bit 5 of port B
97
+ #define SPI_MISO PB4 // Arduino Pin 12 <-> Bit 4 of port B
98
+ #define SPI_MOSI PB3 // Arduino Pin 11 <-> Bit 3 of port B
99
+
100
+ #if defined(SPI_PINS_CE9_CSN10 )
101
+ #define CSN_PORT PORTB // port for CSN
102
+ #define CSN_DDR DDRB // DDR for CSN
103
+ #define CSN_PIN PB2 // Arduino Pin 10 <-> Bit 2 of port B
104
+
105
+ #define CE_PORT PORTB // port for CE
106
+ #define CE_DDR DDRB // DDR for CE
107
+ #define CE_PIN PB1 // Arduino Pin 9 <-> Bit 1 of port B
108
+ #elif defined(SPI_PINS_CSN7_CE8 )
109
+ #define CSN_PORT PORTD // port for CSN
110
+ #define CSN_DDR DDRD // DDR for CSN
111
+ #define CSN_PIN PD7 // Arduino Pin 7 <-> Bit 7 of port D
112
+
113
+ #define CE_PORT PORTB // port for CE
114
+ #define CE_DDR DDRB // DDR for CE
115
+ #define CE_PIN PB0 // Arduino Pin 8 <-> Bit 0 of port B
116
+ #endif
117
+
118
+ #define CSN_LOW () CSN_PORT &= ~_BV(CSN_PIN)
119
+ #define CSN_HIGH () CSN_PORT |= _BV(CSN_PIN)
120
+ #define CE_LOW () CE_PORT &= ~_BV(CE_PIN)
121
+ #define CE_HIGH () CE_PORT |= _BV(CE_PIN)
122
+
123
+
124
+ static void initSPI (void ) {
125
+ // Initialize the SPI pins: SCK, MOSI, CE, CSN as outputs, MISO as input
126
+ #if defined(SPI_PINS_CE9_CSN10 )
127
+ // CSN_PIN (=PB2) is SS pin and set as output
128
+ SPI_DDR = _BV (SPI_MOSI ) | _BV (SPI_SCLK ) | _BV (CE_PIN ) | _BV (CSN_PIN );
129
+ #elif defined(SPI_PINS_CSN7_CE8 )
130
+ // PB2 is SS pin has to be defined as OUTPUT, else SPI goes to slave mode
131
+ SPI_DDR = _BV (SPI_MOSI ) | _BV (SPI_SCLK ) | _BV (CE_PIN ) | _BV (PB2 );
132
+ CSN_DDR = _BV (CSN_PIN );
133
+ #endif
134
+
135
+ // SPE = SPI enable
136
+ // SPIE = SPI interrupt enable
137
+ // DORD = data order (0:MSB first, 1:LSB first)
138
+ // MSTR = Master/Slave select
139
+ // SPR1 = SPI clock rate bit 1
140
+ // SPR0 = SPI clock rate bit 0; 0,0=osc/4, 0,1=osc/16, 1,0=osc/64, 1,1=osc/128
141
+ // CPOL = clock polarity idle (0:low, 1:high)
142
+ // CPHA = clock phase edge sampling (0:leading, 1:trailing)
143
+
144
+ // SPI speed setting, nRF24L01P max. 10Mhz
145
+ #if (F_CPU >= 16000000 )
146
+ // DIV 16 = 1 Mhz
147
+ SPCR = _BV (SPE ) | _BV (MSTR ) | _BV (SPR0 );
148
+ #elif (F_CPU >= 8000000 )
149
+ // DIV 8 = 1 Mhz
150
+ SPCR = _BV (SPE ) | _BV (MSTR ) | _BV (SPR0 );
151
+ SPSR = _BV (SPI2X );
152
+ #elif (F_CPU >= 4000000 )
153
+ // DIV 4 = 1Mhz
154
+ SPCR = _BV (SPE ) | _BV (MSTR );
155
+ #elif (F_CPU >= 2000000 )
156
+ // DIV 2 = 1 Mhz
157
+ SPCR = _BV (SPE ) | _BV (MSTR ) | _BV (SPR0 );
158
+ SPSR = _BV (SPI2X );
159
+ #else
160
+ // DIV 2 <= 0.5 Mhz
161
+ SPCR = _BV (SPE ) | _BV (MSTR );
162
+ SPSR = _BV (SPI2X );
163
+ #endif
164
+
165
+ }
166
+ static uint8_t SPItransfer (const uint8_t value ) {
167
+ SPDR = value ;
168
+ while (!(SPSR & _BV (SPIF ))); // wait until transmitted
169
+ return SPDR ;
170
+ }
171
+ inline void SPIclose (void ) {
172
+ // disable hardware SPI
173
+ SPCR = 0 ;
174
+ }
175
+
176
+
177
+ // UART
178
+ static void initUART (void ) {
179
+ UART_SRA = _BV (U2X0 ); //Double speed mode USART0
180
+ UART_SRB = _BV (RXEN0 ) | _BV (TXEN0 );
181
+ UART_SRC = _BV (UCSZ00 ) | _BV (UCSZ01 );
182
+ UART_SRL = (uint8_t )( (F_CPU + BAUD_RATE * 4L ) / (BAUD_RATE * 8L ) - 1 );
183
+ }
184
+
185
+ void putch (const uint8_t ch ) {
186
+ while (!(UART_SRA & _BV (UDRE0 )));
187
+ UART_UDR = ch ;
188
+ }
189
+
190
+ uint8_t getch (void ) {
191
+ // wait until char received
192
+ while (!(UART_SRA & _BV (RXC0 )));
193
+ // 10 bytes
194
+ // framing error?
195
+ if (!(UART_SRA & _BV (FE0 ))) {
196
+ watchdogReset ();
197
+ }
198
+ return UART_UDR ;
199
+ }
200
+
201
+ static void writeTemporaryBuffer (const uint16_t address , const uint16_t data ) {
202
+ // fill temporary page buffer
203
+ __boot_page_fill_short (address , data );
204
+ }
205
+
206
+ static void programPage (const uint16_t page ){
207
+ __boot_page_erase_short (page ); // erase page
208
+ boot_spm_busy_wait ();
209
+ __boot_page_write_short (page ); // program page
210
+ boot_spm_busy_wait ();
211
+ __boot_rww_enable_short (); // re-enable RWW
212
+ }
213
+
214
+ static uint16_t crc16_update (uint16_t crc , const uint8_t data ) {
215
+ crc ^= data ;
216
+ for (uint8_t i = 0 ; i < 8 ; ++ i ) {
217
+ crc = (crc >> 1 ) ^ (- (int16_t )(crc & 1 ) & 0xA001 );
218
+ }
219
+ return crc ;
220
+ }
221
+
222
+ static uint16_t calcCRCrom (const uint16_t len ) {
223
+
224
+ uint16_t _internal_crc = 0xFFFF ; // init
225
+ uint16_t address = 0x0000 ;
226
+ uint16_t count = len ;
227
+
228
+ // prevent overflow
229
+ if (count > BOOTLOADER_START_ADDRESS ) {
230
+ count = BOOTLOADER_START_ADDRESS ;
231
+ }
232
+
233
+ // calc
234
+ while (count ) {
235
+ uint8_t _rom_byte ;
236
+ // read a flash byte and increment the address
237
+ __asm__ ("lpm %0,Z+\n" : "=r" (_rom_byte ), "=z" (address ): "1" (address ));
238
+ _internal_crc = crc16_update (_internal_crc ,_rom_byte );
239
+ count -- ;
240
+ }
241
+ return _internal_crc ;
242
+ }
243
+
244
+ static void blinkLed (void ) {
245
+ LED_DDR |= _BV (LED_PIN );
246
+ //300ms total
247
+ uint8_t count = 6 ;
248
+ do {
249
+ LED_PORT ^= _BV (LED_PIN );
250
+ _delay_ms (50 );
251
+ } while (-- count );
252
+ }
253
+
254
+
255
+ #endif // HW_H
0 commit comments