/*
 * crash_handler.h
 *
 * Created: 10/6/2023 1:48:15 PM
 *  Author: david
 */ 


#ifndef CRASH_HANDLER_H_
#define CRASH_HANDLER_H_


// Memory region to save all of the current processor registers
// Some of these are automatically stacked at exception entry,
// but the rest have to be manually retrieved

#include "crash_handler_asm.h"


// Crash handler HID commands:

#define CRASH_CMD_GET_SW_VER					'*'
#define CRASH_CMD_GET_REASON					'R'
#define CRASH_CMD_GET_PROCESSOR_STATE			'S'
#define CRASH_CMD_GET_TASK_NAME					'T'
#define CRASH_CMD_GET_NUM_MEMORY_REGIONS		'G'
#define CRASH_CMD_GET_MEMORY_REGION_INFO		'I'
#define CRASH_CMD_GET_MEMORY					'M'
#define CRASH_CMD_RESTART						'C'
#define CRASH_CMD_RESTART_IN_BOOTLOADER			'B'

typedef enum {
	CRASH_HARD_FAULT = 0,
	CRASH_UNUSED_HANDLER,
	CRASH_STACK_OVERFLOW
}Crashdump_Crash_Reason;

#pragma pack(push, 1)
__attribute__((aligned(4)))
typedef struct 
{
	uint32_t r0;		// normally stacked at exception entry
	uint32_t r1;		// 
	uint32_t r2;		// 
	uint32_t r3;		// 
	uint32_t r12;		// 
	uint32_t r14_lr;	// 
	uint32_t r15_pc;	// 
	uint32_t xPSR;		// 
	// If FPU was used, S0-S15 and FPSCR will follow these
	uint32_t float_regs_lo[16];
	uint32_t fpscr;
} Crashdump_AutoStackedRegisters;

__attribute__((aligned(4)))
typedef struct 
{
	uint32_t msp;
	uint32_t psp;
	uint32_t exception_xPSR; // program status register of the exception state that called crashdump
	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 exception_r14_lr; // link register of that exception state
	
}Crashdump_ManuallyStackedRegisters;

__attribute__((aligned(4)))
typedef struct  
{
	uint32_t floats[32];
	uint32_t fpscr;
}Crashdump_FPURegisters;

typedef struct 
{
	uint32_t sp;

}Crashdump_Info;

#pragma pack(pop)

inline void crashdump_trigger(void) {
	//NVIC_SetPendingIRQ(TC1_IRQn);
	__builtin_trap();
}

// Assembly function prototypes
void Copy_All_FPU_Regs(void* output_data);
void Copy_Upper_FPU_Regs(void* output_data);


void enable_crashdump(void);
void crashdump_set_irqn(uint32_t ipsr);
void crashdump_set_crashed_task(void *pxTask, signed char *pcTaskName);
void crashdump_set_crash_reason(Crashdump_Crash_Reason rsn);
void crashdump_start(Crashdump_ManuallyStackedRegisters* manualregs);
void crashdump_change_usb_mode(bool cd_mode);
void usbhid_crashdump_set_feature(uint8_t* report);


#endif /* CRASH_HANDLER_H_ */