KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sys.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 KM3NeT Collaboration
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : sys.c
11  * Created : 22 mrt. 2013
12  * Author : Vincent van Beveren
13  */
14 
15 #include "kernel/sys.h"
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include "cfg_soc.h"
22 #include "cfg_board.h"
23 
24 
25 #include "util/checksum.h"
26 #include "lm32soc/lm32.h"
27 #include "lm32soc/dev_soc.h"
28 
29 #include "drv/wb/sdb.h"
30 #include "drv/wb/i2c.h"
31 #include "drv/wb/spi.h"
32 #include "drv/wb/suart.h"
33 #include "drv/wb/acou.h"
34 #include "drv/wb/gpio.h"
35 #include "drv/wb/ticks.h"
36 
37 #include "drv/spi/sflash.h"
38 #include "kernel/update.h"
39 #include "kernel/loghist.h"
40 #include "drv/wb/mboot.h"
41 
42 #include "drv/i2c/max123x.h"
43 
44 #include "drv/wb/wrx.h"
45 #include "drv/wb/watchdog.h"
46 #include "drv/wb/xadc.h"
47 
48 
49 #define STACK_CHECK 0xDEADBEEF
50 
51 // #define CLBV2
52 
53 #ifdef KC705
54 #include "drv/i2c/pca9548.h"
55 #endif
56 
57 #include "util/log.h"
58 
59 #include "kernel/scheduler.h"
60 #include "kernel/timer.h"
61 
62 #ifdef CLBV2
63 #include "modules/power.h"
64 #endif
65 
66 
67 LOG_DEF(System)
68 
69 
70 // Provided in build process, or else wil be NULL.
71 extern char * __dateRev __attribute__((weak));
72 
73 #if !defined(GOLDEN) && defined(DEBUG)
74 
75 uint32_t _flAddr = 0;
76 
77 static bool allFF(uint8_t * ptr, uint32_t len)
78 {
79 
80  while (len-- > 0)
81  {
82  if (*ptr++ != 0xFF)
83  return false;
84  }
85  return true;
86 }
87 
88 
89 static void coreDumpInit()
90 {
91  _flAddr = CRASH_OFFSET;
92  uint8_t mem[32];
93  sfRead( _flAddr, mem, sizeof(mem));
94  uint32_t c =0;
95  while (!allFF(mem, sizeof(mem)))
96  {
97  puts("");
98  _flAddr += CRASH_IMG_SIZE;
99  c += 1;
100 
101  if (_flAddr >= CRASH_OFFSET + CRASH_SIZE)
102  {
103  logWarn("Core dump memory full, can't store any more core dumps");
104  _flAddr = 0;
105  return;
106  }
107 
108  sfRead( _flAddr, mem, sizeof(mem));
109  }
110  logInfo("Core dump memory contains %d of %d images", c, CRASH_SIZE / CRASH_IMG_SIZE);
111 }
112 
113 static volatile bool _coreDumpInProgress = false;
114 
115 void coreDumpClear()
116 {
117  _coreDumpInProgress = true;
118  _flAddr = CRASH_OFFSET;
119  for (_flAddr = CRASH_OFFSET + CRASH_SIZE - BLOCK_BYTES; _flAddr >= CRASH_OFFSET; _flAddr -= BLOCK_BYTES)
120  {
121  wdogFeed();
123 
124  logInfo("Erasing address %08x", _flAddr);
125  sfErase(_flAddr);
126  }
127  _flAddr = CRASH_OFFSET;
128  _coreDumpInProgress = false;
129 }
130 
131 static void coreDump()
132 {
133  if (_flAddr == 0) return;
134  if (_coreDumpInProgress) return;
135  _coreDumpInProgress = true;
136  sfProgXPage(_flAddr, 0, CRASH_IMG_SIZE);
137 
138  _flAddr += CRASH_IMG_SIZE;
139  if (_flAddr >= CRASH_OFFSET + CRASH_SIZE )
140  {
141  logWarn("Core dump memory full, can't store any more crash information");
142  _flAddr = 0;
143  }
144  _coreDumpInProgress = false;
145 }
146 
147 #else
148 static void coreDump()
149 {
150 }
151 static void coreDumpInit()
152 {
153 }
154 
155 
156 void coreDumpClear() {}
157 
158 #endif
159 
160 
161 
162 void _stdOut(int c)
163 {
164  if (c == '\n')
165  {
166  suartTx(CONSOLE_UART,'\r');
167  suartTx(CONSOLE_UART,'\n');
168  } else if (c != '\r')
169  {
170  suartTx(CONSOLE_UART,c);
171  }
172 }
173 
175 {
176  return getchar();
177 }
178 
179 #ifndef UARTBRIDGE
180 
181 int _stdIn()
182 {
183  char c;
184  if (!suartRxReady(CONSOLE_UART)) {
185  return -1;
186  }
187  if (!suartRx(CONSOLE_UART,&c)) {
188  return -1;
189  }
190  return c;
191 }
192 
193 #endif
194 
195 uint32_t _stdTime()
196 {
197  return ticks();
198 }
199 
200 
201 uint32_t _logTime()
202 {
203  uint32_t uptime = (uint32_t) ( 0xFFFFFFFF & wrxUtcTime() );
204  if (uptime == 0) {
205  uptime = ticks() / TICKS_PER_SEC;
206  }
207  return uptime;
208 }
209 
210 #ifdef USE_LEDS
211 
212 static bool _ledOn;
213 
214 #endif
215 
216 // ---------------------------------------------
217 // AutoNeg switch
218 // ---------------------------------------------
219 
220 #define _AN_SWITCH_COUNT 60
221 static int _anCount = _AN_SWITCH_COUNT;
222 
223 static void sysAutoNegSwitch() {
224 
225  if (!wrxUp()) return;
226 
227  uint32_t status = wrxInfo()->status;
228 
229  if (status & WRX_STATUS_LINK_UP) {
230  _anCount = _AN_SWITCH_COUNT;
231  return;
232  }
233  _anCount--;
234  if (_anCount == 0) {
235  if (status & WRX_STATUS_AUTONEG_ON) {
236  wrxSetAutoNeg(false);
237  } else {
238  wrxSetAutoNeg(true);
239  }
240 
241  _anCount = _AN_SWITCH_COUNT;
242  }
243 }
244 
245 
246 #ifdef DEBUG
248 {
249  puts("--- register dump ---");
250  int i;
251  for (i = 0; i < 10; ++i)
252  {
253  printf(" r%-2d: %08x\n", i + 1, pState[i]);
254  }
255  printf(" ra : %08x\n", pState[PSTATE_RA]);
256  printf(" ea : %08x\n", pState[PSTATE_EA]);
257  printf(" ba : %08x\n", pState[PSTATE_BA]);
258 
259  while (1) { };
260 }
261 #endif
262 
263 
264 // Last crash reason?
265 // __attribute__ ((section (".noinit")))
266 
267 // First time, there is a long timeout.
268 static volatile int _count = SYS_CRASH_COUNT * 5;
269 static volatile uint32_t _ppsCount = 0;
270 
271 
272 void IRQ_HANDLER(IRQ_1HZ)
273 {
274  if (_count <= 0)
275  {
276  logError("Program stalled, rebooting...");
277  logError(" r1: %08x r2: %08x r3: %08x r4: %08x r5: %08x ",
278  pState[1],pState[2],pState[3],pState[4],pState[5]);
279  logError(" r6: %08x r7: %08x r8: %08x r9: %08x r10: %08x ",
280  pState[6],pState[7],pState[8],pState[9],pState[10]);
281  logError(" ra: %08x ba: %08x ea: %08x",
283  coreDump();
285  }
286  else
287  {
288  _count--;
289  }
290  _ppsCount++;
291 }
292 
293 
295 {
296  logError("Illegal ROM access!");
297  logError(" r1: %08x r2: %08x r3: %08x r4: %08x r5: %08x ",
298  pState[1],pState[2],pState[3],pState[4],pState[5]);
299  logError(" r6: %08x r7: %08x r8: %08x r9: %08x r10: %08x ",
300  pState[6],pState[7],pState[8],pState[9],pState[10]);
301  logError(" ra: %08x ba: %08x ea: %08x",
303  coreDump();
305 }
306 
307 
308 
309 uint32_t sysPPSCount()
310 {
311  __irqDisable();
312  uint32_t ppsC = _ppsCount;
313  __irqEnable();
314  return ppsC;
315 }
316 
317 
318 void sysCrash() {
319  while (1) {};
320 }
321 
323 {
324  __irqDisable();
325  _count = SYS_CRASH_COUNT;
326  __irqEnable();
327 }
328 
329 
330 
331 
332 static void sysHeartBeat()
333 {
334 #ifdef USE_LEDS
335  gpioPinSet(GPIO_BLINK_LED, _ledOn);
336  _ledOn = !_ledOn;
337 #endif
338 
339  if (_end != STACK_CHECK)
340  {
341  logError("Stack overflow");
342  coreDump();
344  }
345  sysAutoNegSwitch();
347  wdogFeed();
348 }
349 
350 
351 
352 
353 void _logOut(LogLevel level, char * logOut)
354 {
355  /** Output to Log */
356  puts(logOut);
357 
358  // Output to storage
359  lhStore(level, logOut);
360 
361 }
362 
363 
364 
365 
366 void sysLogClearError(const char * doingWhat) {
367  if (!errHas()) return;
368  logError("%s failed: %s (%08x)", doingWhat, errGetDescr(), errGet());
369  errClear();
370 }
371 
372 
373 void sysLoad(uint8_t * values) {
374  uint32_t * t = timerValues();
375  values[0] = ( 100 * t[TIMER_SECT_IDLE] + (TIMER_MAX_COUNT >> 1) ) / TIMER_MAX_COUNT;
376  values[1] = ( 100 * t[TIMER_SECT_TASK] + (TIMER_MAX_COUNT >> 1) ) / TIMER_MAX_COUNT;
377  values[2] = ( 100 * t[TIMER_SECT_IRQ] + (TIMER_MAX_COUNT >> 1) ) / TIMER_MAX_COUNT;
378 }
379 
380 void sysBoardTemp(uint16_t * brdTemp, uint16_t * brdTempFrq)
381 {
382  *brdTemp = wrxInfo()->brdTemp;
383  *brdTempFrq = wrxInfo()->brdTempFrac;
384 }
385 
386 uint32_t sysHwDateRev()
387 {
388  return *DATEREV;
389 }
390 
391 uint32_t sysSwDateRev()
392 {
393  return (uint32_t) (&__dateRev);
394 
395 }
396 
397 
398 
399 extern const char _appName[];
400 
401 static void dInit(bool result, char * name) {
402 
403  if (result) {
404  printf("%-20s [OK]\n", name);
405  } else {
406  printf("%-20s [ERROR:%04x] %s\n", name, errGet(), errGetDescr());
407  errClear();
408  }
409 }
410 
411 #define _SWDATE(DR) ( ( ( DR ) & DATEREV_DATE_MASK ) >> DATEREV_DATE_SHIFT )
412 #define _SWREV(DR) ( ( ( DR ) & DATEREV_REV_MASK ) >> DATEREV_REV_SHIFT )
413 
414 
415 
416 // CRC per-iteration bytes to process
417 #define CRC_BLOCK_SIZE 32
418 
419 static uint32_t _crc32 = CRC32_INIT_VAL;
420 static const uint8_t * _crc32_pos = 0;
421 extern const uint32_t _crc32_;
422 
423 static void doRomScan()
424 {
425  // block calculation
426  if ((_crc32_pos + CRC_BLOCK_SIZE) < &_rom_size)
427  {
428  _crc32 = crc32(_crc32, _crc32_pos, CRC_BLOCK_SIZE, false);
429  _crc32_pos += CRC_BLOCK_SIZE;
430  return;
431  }
432  // calculate tail
433  if (_crc32_pos != &_rom_size)
434  {
435  _crc32 = crc32(_crc32, _crc32_pos, (unsigned int)(&_rom_size-_crc32_pos)-4, false);
436  }
437 
438  // b2ffc393
439  if (_crc32 != _crc32_) {
440  logError("ROM CRC32 error!");
441  coreDump();
443  }
444 
445  // and start over
446  _crc32_pos = &_rom_offset;
447  _crc32 = CRC32_INIT_VAL;
448 }
449 
450 static void initRomTest()
451 {
452  _crc32_pos = &_rom_offset;
453  schdAddIdleTask(doRomScan);
454 }
455 
456 
457 static void sysInitHw()
458 {
459  suartInit(CONSOLE_UART,SUART_BAUDRATE_DEFAULT);
460  puts(""); puts("");
461 
462  logInfo("%s starting...", _appName);
463  logInfo("FW REV. . : %06x - %02d", _SWDATE(sysHwDateRev()), _SWREV(sysHwDateRev()));
464  logInfo("SW REV. . : %06x - %02d", _SWDATE(sysSwDateRev()), _SWREV(sysSwDateRev()));
465 
466 
467  // Initialize IRQ's
468  irqMaskSet(IRQ_1HZ, true);
469  irqMaskSet(IRQ_ROMXS, true);
470 
471  xadcSetAveraging(XADC_CMD_AVERAGE_MODE_NO);
472 
473 #ifdef DEBUG
474  irqMaskSet(IRQ_DEBUG, true);
475 #endif
476  __irqEnable();
477 
478  SpiInit initSpi = SPI_DEFAULT_INIT;
479  initSpi.bitrate = SPI_SPEED;
480  dInit(spiInit(SPI, &initSpi), "SPI");
481  dInit(sfInit(), "Serial Flash");
482  if (!lhFlashInit()) {
483  logWarn("Failed to initialize Flash logger");
484  errPrint(true);
485  }
486  coreDumpInit();
487  initRomTest();
488 
489  //puts("\nLoading devices / peripherals");
490  // initialize SDB
491  dInit(sdbInit(), "Self Describing Bus");
492 
493  // initialize gpio
494  gpioInit();
495 
496  // initialize I2C
497  dInit(i2cInit(I2C, I2C_SPEED), "I2C");
498 
499 
500 
501  dInit(updInit(), "Update System");
502 
503 #ifdef KC705
504  // This does not seem to work anymore... ?
505 // dInit(pca9548_select(I2C3, I2C_ADR_PCA9548, 1), "Switch I2C1 Mux HPC FMC");
506 #endif
507 
508  puts("");
509  // if any error occurred during start up, report it.
510  if (errHas()) {
511  errPrint(true);
512  }
513 }
514 
515 void sysReboot()
516 {
517  reboot();
518 }
519 
520 uint32_t sysClockTicks() {
521  return ticks();
522 }
523 
524 
525 #define RESET_MAGIC 0x100FF5E7
526 static volatile uint32_t _reset_detect __attribute__ ((section (".noinit")));
527 
528 int main(int argc, char **argv)
529 {
530  // Reconfigure CPU when a reset was issued.
531  if (_reset_detect == 0x100FF5E7)
532  {
533  MBOOT->WBSTAR = 0;
534  MBOOT->CMD = MBOOT_CMD_IPROG;
535  while (1) {};
536  }
537  _reset_detect = 0x100FF5E7;
538 
539  _end = STACK_CHECK;
540 
541  sysInitHw();
542 
543 
544  _appInit();
545 
546  // Reboot if not fed for 60 seconds...
547  wdogSetTopCount(60);
548 
549  int id;
550  schdRegister(sysHeartBeat, false, &id);
551  schdRunPeriodic(id, 500);
552  schdRunForever();
553  return 0;
554 }
555 
#define TIMER_SECT_IRQ
time spend in IRQs
Definition: timer.h:35
SPI initialization structure.
Definition: spi.h:91
Implements search functionality for the self-describing bus.
bool errHas()
Returns whether there is an error pending.
Definition: err.c:52
#define PSTATE_RA
return address (from IRQ = PC at the moment or interrupt)
Definition: lm32.h:132
#define IRQ_1HZ
1Hz IRQ for watchdog-like feature
Definition: cfg_soc.h:104
#define MBOOT_GOLDEN
The golden image index position.
Definition: mboot.h:31
This module provides access to the peripherals on the power board.
Defines the configuration of the LM32 SOC for the CLBv2.
#define I2C_SPEED
Unfortunately 90K is set because AHRS messes up otherwise.
Definition: cfg_soc.h:127
bool sfInit()
Initializes the Serial Flash.
Definition: sflash.c:435
void _appInit()
Prototype to be implemented by higher-level function to start the application.
Definition: app.c:45
void coreDumpClear()
Clears core dump information.
Definition: sys.c:156
void schdRunPeriodic(int taskId, int interval)
Schedule a task to run periodically.
Definition: scheduler.c:212
void mbootLoad(int imgNo)
Boots a specific image.
Definition: mboot.c:38
uint32_t sysHwDateRev()
Returns the Hardware date revision.
Definition: sys.c:386
static void __irqEnable()
Enabled IRQ&#39;s on a global level.
Definition: lm32.h:75
GPIO Driver.
void schdRunForever()
Invoked in the main, starts the scheduler.
Definition: scheduler.c:268
bool lhFlashInit()
Initializes the flash storage (may take a while).
Definition: loghist.c:110
Low level routines for LM32, including interrupt handling.
#define PSTATE_BA
break pointer address
Definition: lm32.h:134
White Rabbit simple timer &#39;Ticks&#39; driver.
bool schdRegister(SchdTaskF task, bool priority, int *taskId)
Register a task with the scheduler.
Definition: scheduler.c:95
System start up and management.
uint32_t _logTime()
Stub function, which should return the current time in seconds, since whatever.
Definition: sys.c:201
void sysReboot()
Reboot the system.
Definition: sys.c:515
#define DATEREV
Date/Revision Device.
Definition: dev_soc.h:68
#define TIMER_SECT_IDLE
time spend being idle
Definition: timer.h:33
int _shellChar()
Stub function.
Definition: sys.c:174
static void wdogSetTopCount(uint16_t counterValue)
Set the watchdog top-counter in seconds.
Definition: watchdog.h:50
#define TICKS_PER_SEC
Timer is in milliseconds.
Definition: ticks.h:29
static void __irqDisable()
Disables IRQ&#39;s on a global level.
Definition: lm32.h:62
#define SPI
SPI memory mapped structure.
Definition: dev_soc.h:69
Watchdog driver.
bool updInit()
Initializes the update module.
Definition: update.c:64
White Rabbit Simple UART Driver.
XADC Driver.
void lhStore(LogLevel level, char *msg)
Stores a line in the buffer, and in flash if activated.
Definition: loghist.c:316
const char * errGetDescr()
Returns the last error description, if any, else null.
Definition: err.c:57
Simple task scheduler for tasks.
#define MBOOT
Multiboot base pointer.
Definition: dev_soc.h:60
This driver wraps the functions of the OpenCores SPI master.
uint64_t wrxUtcTime()
Returns the UTC time, or 0 if not available.
Definition: wrx.c:111
bool sdbInit()
Initializes the self-describing bus.
Definition: sdb.c:310
#define SUART_BAUDRATE_DEFAULT
Default Baudrate.
Definition: suart.h:45
void sysLogClearError(const char *doingWhat)
Logs an error in the context of what the application is doing.
Definition: sys.c:366
Multiboot Driver, exposes one function, mbootLoad.
static uint32_t ticks()
Nr of ticks since device start up.
Definition: ticks.h:37
#define GPIO_BLINK_LED
Led which blink to say I&#39;m alive.
Definition: gpio.h:43
LogLevel
Logging levels.
Definition: log.h:68
#define I2C
Real OpenCores I2C.
Definition: dev_soc.h:63
#define IRQ_HANDLER(IRQ)
Defines an IRQ handler.
Definition: lm32.h:47
#define PSTATE_EA
exception address
Definition: lm32.h:133
void suartInit(SUART_Descriptor *desc, unsigned int baudrate)
Initializes the simple UART.
Definition: suart.c:44
#define logWarn(MSG,...)
Format a log message with warning level.
Definition: log.h:219
void gpioPinSet(int pin, bool high)
Sets the pin state.
Definition: gpio.c:35
#define MBOOT_CMD_IPROG
Trigger reconfiguration.
Definition: dev_mboot.h:32
void irqMaskSet(int irq, bool set)
Set/clear the interrupt mask for the specified IRQ.
Definition: lm32.c:77
PCA9548 I2C mux driver.
uint32_t * timerValues()
Returns.
Definition: timer.c:71
uint32_t bitrate
Bit-rate.
Definition: spi.h:93
bool sfErase(uint32_t address)
Erase a sector in flash.
Definition: sflash.c:564
uint32_t * pState
Program state before IRQ.
Definition: lm32.c:28
MAX123x multichannel ADC driver.
bool i2cInit(I2C_Device *dev, uint32_t bitrate)
Initializes the I2C device with the specified bitrate.
Definition: i2c.c:122
void errPrint(bool clear)
Prints the last error.
Definition: err.c:79
bool spiInit(SPI_Device *dev, SpiInit *init)
Initializes the specified SPI device with the specified parameters.
Definition: spi.c:39
bool schdAddIdleTask(SchdTaskF idleTask)
Adds an idle task, the task which is executed when there is nothing else to do.
Definition: scheduler.c:135
Stores logging history.
#define CRC32_INIT_VAL
Value to which the CRC32 checksum should be initialized.
Definition: checksum.h:32
void sysBoardTemp(uint16_t *brdTemp, uint16_t *brdTempFrq)
Returns the board temperature with a fractional part.
Definition: sys.c:380
#define IRQ_ROMXS
Triggered when there is ROM access.
Definition: cfg_soc.h:105
bool wrxUp()
Returns whether or not the WhiteRabbit interface is up and running.
Definition: wrx.c:58
void gpioInit()
Initializes the GPIO.
Definition: gpio.c:21
void errClear()
Clears the current error.
Definition: err.c:46
bool sfProgXPage(uint32_t address, uint8_t *data, uint32_t count)
Program cross pages.
Definition: sflash.c:547
volatile WrxInfo * wrxInfo()
Returns the whiteRabbit information structure if available, else NULL.
Definition: wrx.c:63
void sysClearCrashDetect()
Clear crash detect.
Definition: sys.c:322
#define IRQ_DEBUG
Debug button pressed.
Definition: cfg_soc.h:96
uint32_t errGet()
Returns the last error code, or null.
Definition: err.c:74
bool suartRx(SUART_Descriptor *desc, char *c)
Receives a character.
Definition: suart.c:73
void reboot()
Soft reboot the LM32.
Definition: lm32.c:112
uint32_t crc32(uint32_t crc, const uint8_t *ptr, int cnt, bool dbg)
Lightweight CRC32 algorithm, using Ethernet polynomial.
Definition: checksum.c:57
#define SYS_CRASH_COUNT
After 10 seconds of no main-loop activity, reboot CLB.
Definition: cfg_soc.h:107
#define SPI_DEFAULT_INIT
Default initialization structure.
Definition: spi.h:104
#define logError(MSG,...)
Format a log message with fatal level.
Definition: log.h:232
#define LOG_DEF(NAME,...)
Define a logger for a module.
Definition: log.h:129
bool sfRead(uint32_t address, uint8_t *data, uint32_t count)
Read from a specific address in flash.
Definition: sflash.c:491
bool wrxSetAutoNeg(bool on)
Returns autonegotation on or off.
Definition: wrx.c:97
uint32_t sysSwDateRev()
Returns the Software date revision.
Definition: sys.c:391
This module provides checksum functions.
static bool suartRxReady(SUART_Descriptor *desc)
Returns whether or not the RX buffer has data.
Definition: suart.h:104
This file assigns all device structures to memory mapped structures.
This driver implements access to the Serial Flash.
bool suartTx(SUART_Descriptor *desc, char c)
Transmits a character.
Definition: suart.c:58
#define TIMER_SECT_TASK
time spend executing a task
Definition: timer.h:34
static void wdogFeed()
Feed the watchdog.
Definition: watchdog.h:32
void _logOut(LogLevel level, char *logLine)
External dependency function.
Definition: sys.c:353
Implements a generic logger facility.
void sysLoad(uint8_t *values)
Gives the system load in percentage.
Definition: sys.c:373
WhiteRabbit exchange exchanges information between the 2nd LM32 and WhiteRabbit though a small client...
#define logInfo(MSG,...)
Write a log message with formatting on info level.
Definition: log.h:202
#define SPI_SPEED
Maximum SPI speed = half WB speed.
Definition: cfg_soc.h:126
Configures the board-specific peripherals, like I2C, SPI etc...
Acoustic Driver.
Facilitates the update process.
OpenCores I2C device driver.