Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
px4_flash.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) Kevin van Hecke
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
28 //#include "subsystems/datalink/downlink.h"
30 #include "mcu_periph/sys_time_arch.h"
32 
33 // Serial Port
34 #include "mcu_periph/uart.h"
35 #include "mcu_periph/usb_serial.h"
36 
37 #include "led.h"
38 
39 #include "libopencm3/cm3/scb.h"
40 
41 #include "mcu_periph/sys_time.h"
43 
44 // define coms link for px4io f1
45 #define PX4IO_PORT (&((PX4IO_UART).device))
46 #define FLASH_PORT (&((FLASH_UART).device))
47 
48 // weird that these below are not in protocol.h, which is from the firmware px4 repo
49 // below is copied from qgroundcontrol:
50 #define PROTO_INSYNC 0x12
51 #define PROTO_EOC 0x20
52 // Reply bytes
53 #define PROTO_OK 0x10
54 #define PROTO_FAILED 0x11
55 #define PROTO_INVALID 0x13
56 // Command bytes
57 #define PROTO_GET_SYNC 0x21
58 #define PROTO_GET_DEVICE 0x22
59 #define PROTO_CHIP_ERASE 0x23
60 #define PROTO_LOAD_ADDRESS 0x24
61 #define PROTO_PROG_MULTI 0x27
62 #define PROTO_GET_CRC 0x29
63 #define PROTO_BOOT 0x30
64 
67 
68 void px4flash_init(void)
69 {
70  setToBootloaderMode = false;
71  px4ioRebootTimeout = false;
72  px4iobl_tid = sys_time_register_timer(15.0, NULL); //20 (fbw pprz bl timeout)-5 (px4 fmu bl timeout)
73 }
74 
75 void px4flash_event(void)
76 {
80  //for unknown reasons, 1500000 baud does not work reliably after prolonged times.
81  //I suspect a temperature related issue, combined with the fbw f1 crystal which is out of specs
82  //After a initial period on 1500000, revert to 230400
83  //We still start at 1500000 to remain compatible with original PX4 firmware. (which always runs at 1500000)
85  }
86  if (PX4IO_PORT->char_available(PX4IO_PORT->periph)) {
87  if (!setToBootloaderMode) {
88  //ignore anything coming from IO if not in bootloader mode (which should be nothing)
89  } else {
90  //relay everything from IO to the laptop
91  while (PX4IO_PORT->char_available(PX4IO_PORT->periph)) {
92  unsigned char b = PX4IO_PORT->get_byte(PX4IO_PORT->periph);
93  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, b);
94  }
95  }
96  }
97 
98  //TODO: check if bootloader timeout was surpassed
99  if (FLASH_PORT->char_available(FLASH_PORT->periph) && !setToBootloaderMode) {
100  // TMP TEST
101  // while (FLASH_PORT->char_available(FLASH_PORT->periph)) {
102  // unsigned char bla = FLASH_PORT->get_byte(FLASH_PORT->periph);
103  // FLASH_PORT->put_byte(FLASH_PORT->periph, 0,bla);
104  // }
105  // return;
106 
107  //check whether this is flash related communication, and for who (ap/fbw)
108  int state = 0;
109  while (state < 4 && FLASH_PORT->char_available(FLASH_PORT->periph)) {
110  unsigned char b = FLASH_PORT->get_byte(FLASH_PORT->periph);
111  switch (state) {
112  case (0) :
113  if (b == 'p') { state++; } else { return; }
114  break;
115  case (1) :
116  if (b == 'p') { state++; } else { return; }
117  break;
118  case (2) :
119  if (b == 'r') { state++; } else { return; }
120  break;
121  case (3) :
122  if (b == 'z') { state++; } else { return; }
123  break;
124  default :
125  break;
126  }
127  }
128 
129  if (state != 4) {return;}
130  //TODO: check if/how this interferes with flashing original PX4 firmware
131  unsigned char target = FLASH_PORT->get_byte(FLASH_PORT->periph);
132  if (target == '1') { //target ap
133  //the target is the ap, so reboot to PX4 bootloader
134  scb_reset_system();
135 
136  } else { // target fbw
137  //the target is the fbw, so reboot the fbw and switch to relay mode
138 
139  //first check if the bootloader has not timeout:
140  if (px4ioRebootTimeout) {
141  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'T');
142  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'I');
143  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'M');
144  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'E');
145  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'O');
146  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'U');
147  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'T'); // use 7 chars as answer
148  return;
149  } { // FBW OK OK hollay hollay :)
150  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'F');
151  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'B');
152  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'W');
153  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'O');
154  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'K');
155  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'O');
156  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'K'); // use 7 chars as answer
157  }
158 
159 
160  //stop all intermcu communication:
162 
163  px4iobl_tid = sys_time_register_timer(5.0, NULL); //10 (fbw pprz bl timeout)-5 (px4 fmu bl timeout)
164  /*
165  * The forceprog define is very usefull, if for whatever reason the (normal, not bootloader) firmware on the IO chip became disfunct.
166  * In that case:
167  * 1. enable this define
168  * 2. build and upload the fmu f4 chip (ap target in pprz center)
169  * 3. build the io code, and convert the firmware using the following command:
170  * Optional 5&6:
171  * 5a. Either, boot the Pixhawk (reconnect usb) holding the IO reset button until the FMU led stops blinking fast (i.e. exits its own bootloader)
172  * 5b Or, press the IO reset button on the pixhawk
173  * 6. Watch the output of the command of step 4, it should recognize the IO bootloader and start flashing. If not try repeating step 5a.
174  * 7. Don forget to disable the define and upload the ap again :)
175  */
176  //#define forceprog
177 
178 #ifndef forceprog
179  //send the reboot to bootloader command:
180  static struct IOPacket dma_packet;
181  dma_packet.count_code = 0x40 + 0x01;
182  dma_packet.crc = 0;
183  dma_packet.page = PX4IO_PAGE_SETUP;
184  dma_packet.offset = PX4IO_P_SETUP_REBOOT_BL;
185  dma_packet.regs[0] = PX4IO_REBOOT_BL_MAGIC;
186  dma_packet.crc = crc_packet(&dma_packet);
187  struct IOPacket *pkt = &dma_packet;
188  uint8_t *p = (uint8_t *)pkt;
189  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, p[0]);
190  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, p[1]);
191  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, p[2]);
192  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, p[3]);
193  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, p[4]);
194  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, p[5]);
195 
196  sys_time_usleep(5000); // this seems to be close to the minimum delay necessary to process this packet at the IO side
197  //the pixhawk IO chip should respond with:
198  // 0x00 ( PKT_CODE_SUCCESS )
199  // 0xe5
200  // 0x32
201  // 0x0a
202  //After that, the IO chips reboots into bootloader mode, in which it will stay for a short period
203  //The baudrate in bootloader mode ic changed to 115200 (normal operating baud is 1500000, at least for original pixhawk fmu firmware)
204 
205  //state machine
206  state = 0;
207  while (state < 4 && PX4IO_PORT->char_available(PX4IO_PORT->periph)) {
208 
209  unsigned char b = PX4IO_PORT->get_byte(PX4IO_PORT->periph);
210  switch (state) {
211  case (0) :
212  if (b == PKT_CODE_SUCCESS) { state++; } else { state = 0; }
213  break;
214  case (1) :
215  if (b == 0xe5) { state++; } else { state = 0; }
216  break;
217  case (2) :
218  if (b == 0x32) { state++; } else { state = 0; }
219  break;
220  case (3) :
221  if (b == 0x0a) { state++; } else { state = 0; }
222  break;
223  default :
224  break;
225  }
226  }
227 #else
228  int state = 4;
229 #endif
230  if (state == 4) {
232  /* look for the bootloader for 150 ms */
233  int ret = 0;
234  for (int i = 0; i < 15 && !ret ; i++) {
235  sys_time_usleep(10000);
236 
237  //send a get_sync command in order to keep the io in bootloader mode
238  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, PROTO_GET_SYNC);
239  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, PROTO_EOC);
240 
241  //get_sync should be replied with, so check if that happens and
242  //all other bytes are discarded, hopefully those were not important
243  //(they may be caused by sending multiple syncs)
244  while (PX4IO_PORT->char_available(PX4IO_PORT->periph)) {
245  unsigned char b = PX4IO_PORT->get_byte(PX4IO_PORT->periph);
246 
247  if (b == PROTO_INSYNC) {
248  setToBootloaderMode = true;
249  ret = 1;
250  break;
251  }
252  }
253  }
254  if (setToBootloaderMode) {
255  //if successfully entered bootloader mode, clear any remaining bytes (which may have a function, but I did not check)
256  while (PX4IO_PORT->char_available(PX4IO_PORT->periph)) {PX4IO_PORT->get_byte(PX4IO_PORT->periph);}
257  }
258  } else {
259  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'E'); //TODO: find out what the PX4 protocol for error feedback is...
260  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'R');
261  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'R');
262  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'O');
263  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, 'R');
264  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, '!');
265  FLASH_PORT->put_byte(FLASH_PORT->periph, 0, ' '); // use 7 chars as answer
266 
267  }
268  }
269  } else if (FLASH_PORT->char_available(FLASH_PORT->periph)) {
270  //already in bootloader mode, just directly relay data
271  while (FLASH_PORT->char_available(FLASH_PORT->periph)) {
272  unsigned char b = FLASH_PORT->get_byte(FLASH_PORT->periph);
273  PX4IO_PORT->put_byte(PX4IO_PORT->periph, 0, b);
274  }
275  }
276 }
277 
#define PKT_CODE_SUCCESS
Definition: protocol.h:331
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
#define PX4IO_P_SETUP_REBOOT_BL
Definition: protocol.h:224
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
Set baudrate.
Definition: uart_arch.c:838
#define PX4IO_PORT
Definition: px4_flash.c:45
#define PROTO_GET_SYNC
NOP for re-establishing sync.
Definition: px4_flash.c:57
void intermcu_set_enabled(bool value)
Definition: intermcu_ap.c:85
#define PX4IO_PAGE_SETUP
Definition: protocol.h:177
void px4flash_init(void)
Definition: px4_flash.c:68
uint8_t count_code
Definition: protocol.h:321
#define FLASH_PORT
Definition: px4_flash.c:46
#define B115200
Definition: uart_arch.h:48
void sys_time_cancel_timer(tid_t id)
Cancel a system timer by id.
Definition: sys_time.c:60
uint8_t offset
Definition: protocol.h:324
#define PROTO_EOC
end of command
Definition: px4_flash.c:51
uint8_t page
Definition: protocol.h:323
#define FALSE
Definition: std.h:5
void px4flash_event(void)
Definition: px4_flash.c:75
#define B230400
Definition: uart_arch.h:49
#define PROTO_INSYNC
'in sync' byte sent before status
Definition: px4_flash.c:50
void sys_time_usleep(uint32_t us)
sys_time_usleep(uint32_t us)
Definition: sys_time_arch.c:95
static uint8_t crc_packet(struct IOPacket *pkt)
Definition: protocol.h:379
#define TRUE
Definition: std.h:4
Architecture independent timing functions.
int8_t tid_t
sys_time timer id type
Definition: sys_time.h:60
bool px4ioRebootTimeout
Definition: px4_flash.c:66
Rotorcraft Inter-MCU on the autopilot.
bool setToBootloaderMode
Definition: px4_flash.c:65
tid_t px4iobl_tid
id for time out of the px4 bootloader reset
Definition: px4_flash.c:42
unsigned char uint8_t
Definition: types.h:14
static bool sys_time_check_and_ack_timer(tid_t id)
Check if timer has elapsed.
Definition: sys_time.h:114
uint8_t crc
Definition: protocol.h:322
uint16_t regs[PKT_MAX_REGS]
Definition: protocol.h:325
arch independent LED (Light Emitting Diodes) API
static float p[2][2]
struct FloatVect2 target
#define PX4IO_REBOOT_BL_MAGIC
Definition: protocol.h:225
struct State state
Definition: state.c:36
tid_t sys_time_register_timer(float duration, sys_time_cb cb)
Register a new system timer.
Definition: sys_time.c:43
arch independent USB API