text: /****************************************************************************
   *
   *   Copyright (C) 2015 PX4 Development Team. All rights reserved.
   *   Author: @author David Sidrane <david_s5@nscdg.com>
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 3. Neither the name PX4 nor the names of its contributors may be
   *    used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   *
   ****************************************************************************/
  #pragma once
  /****************************************************************************
   * Included Files
   ****************************************************************************/
  #include <systemlib/px4_macros.h>
  #include <stm32_bbsram.h>
  
  /****************************************************************************
   * Pre-processor Definitions
   ****************************************************************************/
  #define HARDFAULT_FILENO 3
  #define HARDFAULT_PATH BBSRAM_PATH""STRINGIFY(HARDFAULT_FILENO)
  #define HARDFAULT_REBOOT_FILENO 0
  #define HARDFAULT_REBOOT_PATH BBSRAM_PATH""STRINGIFY(HARDFAULT_REBOOT_FILENO)
  
  
  #define BBSRAM_SIZE_FN0 (sizeof(int))
  #define BBSRAM_SIZE_FN1 384     /* greater then 2.5 times the size of vehicle_status_s */
  #define BBSRAM_SIZE_FN2 384     /* greater then 2.5 times the size of vehicle_status_s */
  #define BBSRAM_SIZE_FN3 -1
  
  /* The following guides in the amount of the user and interrupt stack
   * data we can save. The amount of storage left will dictate the actual
   * number of entries of the user stack data saved. If it is too big
   * It will be truncated by the call to stm32_bbsram_savepanic
   */
  #define BBSRAM_HEADER_SIZE 20 /* This is an assumption */
  #define BBSRAM_USED ((4*BBSRAM_HEADER_SIZE)+(BBSRAM_SIZE_FN0+BBSRAM_SIZE_FN1+BBSRAM_SIZE_FN2))
  #define BBSRAM_REAMINING (PX4_BBSRAM_SIZE-BBSRAM_USED)
  #if CONFIG_ARCH_INTERRUPTSTACK <= 3
  #  define BBSRAM_NUMBER_STACKS 1
  #else
  #  define BBSRAM_NUMBER_STACKS 2
  #endif
  #define BBSRAM_FIXED_ELEMENTS_SIZE (sizeof(info_s))
  #define BBSRAM_LEFTOVER (BBSRAM_REAMINING-BBSRAM_FIXED_ELEMENTS_SIZE)
  
  #define CONFIG_ISTACK_SIZE (BBSRAM_LEFTOVER/BBSRAM_NUMBER_STACKS/sizeof(stack_word_t))
  #define CONFIG_USTACK_SIZE (BBSRAM_LEFTOVER/BBSRAM_NUMBER_STACKS/sizeof(stack_word_t))
  
  /* The path to the Battery Backed up SRAM */
  #define BBSRAM_PATH "/fs/bbr"
  /* The sizes of the files to create (-1) use rest of BBSRAM memory */
  #define BSRAM_FILE_SIZES { \
  		BBSRAM_SIZE_FN0,   /* For Time stamp only */                  \
  		BBSRAM_SIZE_FN1,   /* For Current Flight Parameters Copy A */ \
  		BBSRAM_SIZE_FN2,   /* For Current Flight Parameters Copy B*/  \
  		BBSRAM_SIZE_FN3,   /* For the Panic Log use rest of space */  \
  		0                  /* End of table marker */                  \
  	}
  
  /* For Assert keep this much of the file name*/
  #define MAX_FILE_PATH_LENGTH 40
  
  
  /* Fixed size strings
   * To change a format add the number of chars not represented by the format
   * Specifier to the xxxx_NUM definei.e %Y is YYYY so add 2 and %s is -2
   * Also xxxxTIME_FMT need to match in size. See CCASERT in hardfault_log.c
   */
  #define LOG_PATH_BASE       "/fs/microsd/"
  #define LOG_PATH_BASE_LEN    ((arraySize(LOG_PATH_BASE))-1)
  
  #define LOG_NAME_FMT        "fault_%s.log"
  #define LOG_NAME_NUM         (     -2    )
  #define LOG_NAME_LEN         ((arraySize(LOG_NAME_FMT)-1) + LOG_NAME_NUM)
  
  #define TIME_FMT             "%Y_%m_%d_%H_%M_%S"
  #define TIME_FMT_NUM         (2+ 0+ 0+ 0+ 0+ 0)
  #define TIME_FMT_LEN         (((arraySize(TIME_FMT)-1) + TIME_FMT_NUM))
  
  #define LOG_PATH_LEN         ((LOG_PATH_BASE_LEN + LOG_NAME_LEN + TIME_FMT_LEN))
  
  #define HEADER_TIME_FMT      "%Y-%m-%d-%H:%M:%S"
  #define HEADER_TIME_FMT_NUM  (2+ 0+ 0+ 0+ 0+ 0)
  #define HEADER_TIME_FMT_LEN  (((arraySize(HEADER_TIME_FMT)-1) + HEADER_TIME_FMT_NUM))
  
  /* Select which format to use. On a terminal the details are at the bottom
   * and in a file they are at the top
   */
  #define HARDFAULT_DISPLAY_FORMAT 1
  #define HARDFAULT_FILE_FORMAT    0
  
  /****************************************************************************
   * Public Types
   ****************************************************************************/
  
  /* Used for stack frame storage */
  typedef uint32_t stack_word_t;
  
  /* Stack related data */
  
  typedef struct {
  	uint32_t sp;
  	uint32_t top;
  	uint32_t size;
  
  } _stack_s;
  
  typedef struct {
  	_stack_s user;
  #if CONFIG_ARCH_INTERRUPTSTACK > 3
  	_stack_s interrupt;
  #endif
  
  } stack_t;
  
  /* Not Used for reference only */
  
  typedef struct {
  	uint32_t r0;
  	uint32_t r1;
  	uint32_t r2;
  	uint32_t r3;
  	uint32_t r4;
  	uint32_t r5;
  	uint32_t r6;
  	uint32_t r7;
  	uint32_t r8;
  	uint32_t r9;
  	uint32_t r10;
  	uint32_t r11;
  	uint32_t r12;
  	uint32_t sp;
  	uint32_t lr;
  	uint32_t pc;
  	uint32_t xpsr;
  	uint32_t d0;
  	uint32_t d1;
  	uint32_t d2;
  	uint32_t d3;
  	uint32_t d4;
  	uint32_t d5;
  	uint32_t d6;
  	uint32_t d7;
  	uint32_t d8;
  	uint32_t d9;
  	uint32_t d10;
  	uint32_t d11;
  	uint32_t d12;
  	uint32_t d13;
  	uint32_t d14;
  	uint32_t d15;
  	uint32_t fpscr;
  	uint32_t sp_main;
  	uint32_t sp_process;
  	uint32_t apsr;
  	uint32_t ipsr;
  	uint32_t epsr;
  	uint32_t primask;
  	uint32_t basepri;
  	uint32_t faultmask;
  	uint32_t control;
  	uint32_t s0;
  	uint32_t s1;
  	uint32_t s2;
  	uint32_t s3;
  	uint32_t s4;
  	uint32_t s5;
  	uint32_t s6;
  	uint32_t s7;
  	uint32_t s8;
  	uint32_t s9;
  	uint32_t s10;
  	uint32_t s11;
  	uint32_t s12;
  	uint32_t s13;
  	uint32_t s14;
  	uint32_t s15;
  	uint32_t s16;
  	uint32_t s17;
  	uint32_t s18;
  	uint32_t s19;
  	uint32_t s20;
  	uint32_t s21;
  	uint32_t s22;
  	uint32_t s23;
  	uint32_t s24;
  	uint32_t s25;
  	uint32_t s26;
  	uint32_t s27;
  	uint32_t s28;
  	uint32_t s29;
  	uint32_t s30;
  	uint32_t s31;
  } proc_regs_s;
  
  
  /* Flags to identify what is in the dump */
  typedef enum {
  	eRegsPresent          = 0x01,
  	eUserStackPresent     = 0x02,
  	eIntStackPresent      = 0x04,
  	eInvalidUserStackPtr  = 0x20,
  	eInvalidIntStackPrt   = 0x40,
  } fault_flags_t;
  
  typedef struct {
  	fault_flags_t         flags;                  /* What is in the dump */
  	uintptr_t             current_regs;           /* Used to validate the dump */
  	int                   lineno;                 /* __LINE__ to up_assert */
  	int                   pid;                    /* Process ID */
  	uint32_t              regs[XCPTCONTEXT_REGS]; /* Interrupt register save
  											 * area */
  	stack_t               stacks;                 /* Stack info */
  #if CONFIG_TASK_NAME_SIZE > 0
  	char                  name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL
  													* terminator) */
  #endif
  	char                  filename[MAX_FILE_PATH_LENGTH]; /* the Last of chars in
  												  * __FILE__ to up_assert */
  } info_s;
  
  typedef struct {
  	info_s    info;                       /* The info */
  #if CONFIG_ARCH_INTERRUPTSTACK > 3      /* The amount of stack data is compile time
  									 * sized backed on what is left after the
  									 * other BBSRAM files are defined
  									 * The order is such that only the
  									 * ustack should be truncated
  									 */
  	stack_word_t istack[CONFIG_USTACK_SIZE];
  #endif
  	stack_word_t ustack[CONFIG_ISTACK_SIZE];
  } fullcontext_s;
  
  __BEGIN_DECLS
  /****************************************************************************
   * Name: hardfault_check_status
   *
   * Description:
   *      Check the status of the BBSRAM hard fault file which can be in
   *      one of two states Armed, Valid or Broken.
   *
   *      Armed - The file in the armed state is not accessible in the fs
   *              the act of unlinking it is what arms it.
   *
   *      Valid - The file in the armed state is not accessible in the fs
   *              the act of unlinking it is what arms it.
   *
   * Inputs:
   *   - caller:  A label to display in syslog output
   *
   *  Returned Value:
   *   -ENOENT    Armed - The file in the armed state
   *    OK        Valid - The file contains data from a fault that has not
   *                      been committed to disk (see write_hardfault).
   *   -  Any < 0 Broken - Should not happen
   *
   ****************************************************************************/
  int hardfault_check_status(char *caller) weak_function;
  
  /****************************************************************************
   * Name: hardfault_write
   *
   * Description:
   *      Will parse and write a human readable output of the data
   *      in the BBSRAM file. Once
   *
   *
   * Inputs:
   *   - caller:  A label to display in syslog output
   *   - fd:      An FD to write the data to
   *   - format:  Select which format to use.
   *
   *              HARDFAULT_DISPLAY_FORMAT  On the console the details are
   *                                        at the bottom
   *              HARDFAULT_FILE_FORMAT     In a file details are at the top
   *                                        of the log file
   *
   *    - rearm: If true will move the file to the Armed state, if
   *             false the file is not armed and can be read again
   *
   *  Returned Value:
   *
   *    OK  or errno
   *
   *
   ****************************************************************************/
  int hardfault_write(char *caller, int fd, int format, bool rearm) weak_function;
  
  /****************************************************************************
   * Name: hardfault_rearm
   *
   * Description:
   *      Will move the file to the Armed state
   *
   *
   * Inputs:
   *   - caller:  A label to display in syslog output
   *
   *  Returned Value:
   *
   *    OK  or errno
   *
   *
   ****************************************************************************/
  int hardfault_rearm(char *caller) weak_function;
  
  /****************************************************************************
   * Name: hardfault_increment_reboot
   *
   * Description:
   *      Will increment the reboot counter. The reboot counter will help
   *      detect reboot loops.
   *
   *
   * Inputs:
   *   - caller:  A label to display in syslog output
   *   - reset :  when set will reset the reboot counter to 0.
   *
   *  Returned Value:
   *
   *    The current value of the reboot counter (post increment).
   *
   *
   ****************************************************************************/
  int hardfault_increment_reboot(char *caller, bool reset) weak_function;
  
  __END_DECLS
  