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