Merge companion and firmware notes, and get them from the server (#5530)
[opentx.git] / radio / src / loadboot.cpp
blobae687e980517e6b84ea0189254b090185400deb8
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
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.
21 #include "opentx.h"
23 #if defined(PCBSKY9X)
24 #include "AT91SAM3S4.h"
25 #else
26 #include "targets/taranis/board.h"
27 #endif
29 #if defined(PCBTARANIS)
30 void bwdt_reset()
32 IWDG->KR = 0xAAAA; // reload
34 #endif
36 #if defined(PCBTARANIS)
37 // TODO needed?
38 __attribute__ ((section(".bootrodata"), used))
39 void _bootStart(void);
40 #endif
42 #if defined(PCBTARANIS)
43 __attribute__ ((section(".isr_boot_vector"), used))
44 const uint32_t BootVectors[] = {
45 (uint32_t) &_estack,
46 (uint32_t) (void (*)(void)) ((unsigned long) &_bootStart) };
47 #endif
49 #if defined(PCBTARANIS)
50 __attribute__ ((section(".bootrodata.*"), used))
51 #elif defined(PCBSKY9X)
52 __attribute__ ((section(".bootrodata"), used))
53 #endif
55 const uint8_t BootCode[] = {
56 #include "bootloader.lbm"
59 #if defined(PCBTARANIS)
60 __attribute__ ((section(".bootrodata"), used))
61 void _bootStart()
63 #if defined(PCBX9E)
64 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIODEN;
65 #else
66 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIODEN;
67 #endif
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;
89 #if defined(PCBX9E)
90 GPIOG->PUPDR = 0x00000001;
91 #else
92 GPIOE->PUPDR = 0x00000040;
93 #endif
95 // wait for inputs to stabilize
96 for (uint32_t i = 0; i < 50000; i += 1) {
97 bwdt_reset();
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) {
108 bwdt_reset();
112 if (!(TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR) && !(TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)) {
113 // Bootloader needed
114 const uint8_t *src;
115 uint8_t *dest;
116 uint32_t size;
118 bwdt_reset();
119 size = sizeof(BootCode);
120 src = BootCode;
121 dest = (uint8_t *) 0x20000000;
123 for (; size; size -= 1) {
124 *dest++ = *src++;
126 // Could check for a valid copy to RAM here
127 // Go execute bootloader
128 bwdt_reset();
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");
137 // 0x8000000
138 asm(" add.w r1, #32768");
139 // 0x8000
141 asm(" movw r0, #60680");
142 // 0xED08
143 asm(" movt r0, #57344");
144 // 0xE000
145 asm(" str r1, [r0, #0]");
146 // Set the VTOR
148 asm("ldr r0, [r1, #0]");
149 // Stack pointer value
150 asm("msr msp, r0");
151 // Set it
152 asm("ldr r0, [r1, #4]");
153 // Reset address
154 asm("mov.w r1, #1");
155 asm("orr r0, r1");
156 // Set lsbit
157 asm("bx r0");
158 // Execute application
160 #endif