5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
24 #include "AT91SAM3S4.h"
26 #include "targets/taranis/board.h"
29 #if defined(PCBTARANIS)
32 IWDG
->KR
= 0xAAAA; // reload
36 #if defined(PCBTARANIS)
38 __attribute__ ((section(".bootrodata"), used
))
39 void _bootStart(void);
42 #if defined(PCBTARANIS)
43 __attribute__ ((section(".isr_boot_vector"), used
))
44 const uint32_t BootVectors
[] = {
46 (uint32_t) (void (*)(void)) ((unsigned long) &_bootStart
) };
49 #if defined(PCBTARANIS)
50 __attribute__ ((section(".bootrodata.*"), used
))
51 #elif defined(PCBSKY9X)
52 __attribute__ ((section(".bootrodata"), used
))
55 const uint8_t BootCode
[] = {
56 #include "bootloader.lbm"
59 #if defined(PCBTARANIS)
60 __attribute__ ((section(".bootrodata"), used
))
64 RCC
->AHB1ENR
|= RCC_AHB1ENR_GPIOCEN
| RCC_AHB1ENR_GPIOGEN
| RCC_AHB1ENR_GPIODEN
;
66 RCC
->AHB1ENR
|= RCC_AHB1ENR_GPIOCEN
| RCC_AHB1ENR_GPIOEEN
| RCC_AHB1ENR_GPIODEN
;
69 // these two NOPs are needed (see STM32F errata sheet) before the peripheral
70 // register can be written after the peripheral clock was enabled
71 __ASM
volatile ("nop");
72 __ASM
volatile ("nop");
74 // Turn soft power ON now, but only if we got started because of the watchdog
75 // or software reset. If the radio was started by user pressing the power button
76 // then that button is providing power and we don't need to enable it here.
78 // If we were to turn it on here indiscriminately, then the radio can go into the
79 // power on/off loop after being powered off by the user. (issue #2790)
80 if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
81 GPIOD
->BSRRL
= 1; // set PWR_ON_GPIO_PIN pin to 1
82 GPIOD
->MODER
= (GPIOD
->MODER
& 0xFFFFFFFC) | 1; // General purpose output mode
85 // TRIMS_GPIO_PIN_LHR is on PG0 on X9E and on PE3 on Taranis
86 // TRIMS_GPIO_PIN_RHL is on PC1 on all versions
87 // turn on pull-ups on trim keys
88 GPIOC
->PUPDR
= 0x00000004;
90 GPIOG
->PUPDR
= 0x00000001;
92 GPIOE
->PUPDR
= 0x00000040;
95 // wait for inputs to stabilize
96 for (uint32_t i
= 0; i
< 50000; i
+= 1) {
100 // now the second part of power on sequence
101 // If we got here and the radio was not started by the watchdog/software reset,
102 // then we must have a power button pressed. If not then we are in power on/off loop
103 // and to terminate it, just wait here without turning on PWR pin. The power supply will
104 // eventually exhaust and the radio will turn off.
105 if (!WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
106 // wait here until the power key is pressed
107 while (GPIOD
->IDR
& PWR_SWITCH_GPIO_PIN
) {
112 if (!(TRIMS_GPIO_REG_LHR
& TRIMS_GPIO_PIN_LHR
) && !(TRIMS_GPIO_REG_RHL
& TRIMS_GPIO_PIN_RHL
)) {
119 size
= sizeof(BootCode
);
121 dest
= (uint8_t *) 0x20000000;
123 for (; size
; size
-= 1) {
126 // Could check for a valid copy to RAM here
127 // Go execute bootloader
130 uint32_t address
= *(uint32_t *) 0x20000004;
132 ((void (*)(void)) (address
))(); // Go execute the loaded application
135 // run_application() ;
136 asm(" mov.w r1, #134217728");
138 asm(" add.w r1, #32768");
141 asm(" movw r0, #60680");
143 asm(" movt r0, #57344");
145 asm(" str r1, [r0, #0]");
148 asm("ldr r0, [r1, #0]");
149 // Stack pointer value
152 asm("ldr r0, [r1, #4]");
158 // Execute application