Files
microchip-application-pec93…/Drivers/PB5700/Device/inc/system_dev.h
T
2026-02-03 11:37:13 +08:00

391 lines
12 KiB
C

/**
* Copyright (c) 2024 Wei-Lun Hsu. All Rights Reserved.
*/
/** @file system_dev.h
*
* @author Wei-Lun Hsu
* @version 0.1
* @date 2024/08/29
* @license
* @description
*/
#ifndef __system_dev_H_wjaCXWfu_lqsX_H0XR_svyC_uj3MxJR5UZzV__
#define __system_dev_H_wjaCXWfu_lqsX_H0XR_svyC_uj3MxJR5UZzV__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
//=============================================================================
// Constant Definition
//=============================================================================
#ifndef SYS_TIMER_FREQ
#define SYS_TIMER_FREQ 32768ul
#endif
#ifndef SYS_MAX_DELAY
#define SYS_MAX_DELAY 0x7FFFFFFFul
#endif
#define SYS_IGNORE_TAG (~0)
/**
* Exception Code
*/
typedef enum EXCPn
{
/* =============== Nuclei N/NX Specific Exception Code =============== */
EXCPn_InsUnalign = 0, /*!< Instruction address misaligned */
EXCPn_InsAccFault = 1, /*!< Instruction access fault */
EXCPn_IlleIns = 2, /*!< Illegal instruction */
EXCPn_Break = 3, /*!< Beakpoint */
EXCPn_LdAddrUnalign = 4, /*!< Load address misaligned */
EXCPn_LdFault = 5, /*!< Load access fault */
EXCPn_StAddrUnalign = 6, /*!< Store or AMO address misaligned */
EXCPn_StAccessFault = 7, /*!< Store or AMO access fault */
EXCPn_UmodeEcall = 8, /*!< Environment call from User mode */
EXCPn_SmodeEcall = 9, /*!< Environment call from S-mode */
EXCPn_MmodeEcall = 11, /*!< Environment call from Machine mode */
#if 1
EXCPn_Total,
#else
EXCPn_InsPageFault = 12, /*!< Instruction page fault */
EXCPn_LdPageFault = 13, /*!< Load page fault */
EXCPn_StPageFault = 15, /*!< Store or AMO page fault */
EXCPn_StackOverflow = 24, /*!< Stack overflow fault */
EXCPn_StackUnderflow = 25, /*!< Stack underflow fault */
EXCPn_Total,
#endif
EXCPn_NMI = 0xfff, /*!< NMI interrupt */
} EXCPn_Type;
/**
* SYS_TIMER_PERIOD with 1ms, 10ms, 100ms
*/
typedef enum sys_tick
{
SYS_TICK_1_MS = 0,
SYS_TICK_10_MS,
SYS_TICK_100_MS,
SYS_TICK_1_SEC,
} sys_tick_t;
#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
typedef enum sys_irq_trigger
{
SYS_IRQ_TRIGGER_LEVEL = ECLIC_LEVEL_TRIGGER, /*!< Level Triggerred */
SYS_IRQ_TRIGGER_POSTIVE_EDGE = ECLIC_POSTIVE_EDGE_TRIGGER, /*!< Postive/Rising Edge Triggered */
SYS_IRQ_TRIGGER_NEGTIVE_EDGE = ECLIC_NEGTIVE_EDGE_TRIGGER, /*!< Negtive/Falling Edge Triggered */
SYS_IRQ_TRIGGER_MAX = ECLIC_MAX_TRIGGER, /*!< MAX Supported Trigger Mode */
} sys_irq_trigger_t;
typedef enum sys_irq_level
{
SYS_IRQ_LEVEL_LL = 0, /*!< Interrupt Level lowest */
SYS_IRQ_LEVEL_L = 1, /*!< Interrupt Level low */
SYS_IRQ_LEVEL_M = 2, /*!< Interrupt Level midden */
SYS_IRQ_LEVEL_H = 3, /*!< Interrupt Level high */
SYS_IRQ_LEVEL_HH = 4, /*!< Interrupt Level highest */
} sys_irq_level_t;
typedef enum sys_irq_priority
{
SYS_IRQ_PRIORITY_LOW = 0, /*!< Interrupt Priority Low */
SYS_IRQ_PRIORITY_MIDDEN = 1, /*!< Interrupt Priority Midden */
SYS_IRQ_PRIORITY_HIGH = 2, /*!< Interrupt Priority High */
} sys_irq_priority_t;
#endif /* __ECLIC_PRESENT */
typedef void (*fp_isr_t)(void);
/**
* Exception Handler Function Typedef
*/
typedef void (*cb_excp_handler_t)(uint32_t cause, uint32_t sp);
//=============================================================================
// Macro Definition
//=============================================================================
/**
* Locate function to specific section
* e.g.
* uint32_t __FASTCODE foo(void) { return 123; }
*/
#define __FASTCODE __attribute__((__section__(".fastcode")))
__STATIC_FORCEINLINE uint32_t* __get_pc(void)
{
uint32_t *pc;
__asm__("auipc %0, 0" : "=r"(pc));
return pc;
}
__STATIC_FORCEINLINE uint32_t* __get_sp(void)
{
uint32_t *sp;
__asm__("move %0, sp" : "=r"(sp));
return sp;
}
//=============================================================================
// Structure Definition
//=============================================================================
typedef struct excp_frame
{
uint32_t ra; /* ra: x1, return address for jump */
uint32_t tp; /* tp: x4, thread pointer */
uint32_t t0; /* t0: x5, temporary register 0 */
uint32_t t1; /* t1: x6, temporary register 1 */
uint32_t t2; /* t2: x7, temporary register 2 */
uint32_t a0; /* a0: x10, return value or function argument 0 */
uint32_t a1; /* a1: x11, return value or function argument 1 */
uint32_t a2; /* a2: x12, function argument 2 */
uint32_t a3; /* a3: x13, function argument 3 */
uint32_t a4; /* a4: x14, function argument 4 */
uint32_t a5; /* a5: x15, function argument 5 */
uint32_t cause; /* cause: machine cause csr register */
uint32_t epc; /* epc: machine exception program counter csr register */
uint32_t msubm; /* msubm: machine sub-mode csr register, nuclei customized */
#ifndef __riscv_32e
uint32_t a6; /* a6: x16, function argument 6 */
uint32_t a7; /* a7: x17, function argument 7 */
uint32_t t3; /* t3: x28, temporary register 3 */
uint32_t t4; /* t4: x29, temporary register 4 */
uint32_t t5; /* t5: x30, temporary register 5 */
uint32_t t6; /* t6: x31, temporary register 6 */
#endif
} excp_frame_t;
typedef struct sys_irq_attr
{
uint8_t trig_mode; /*!< the interrupt trigger mode, @ref sys_irq_trigger_t */
uint8_t disable_vector; /*!< use vector table or not */
uint8_t level; /*!< interupt nested level,
high-level (bigger value) will interrupt low-level, @ref sys_irq_level_t */
uint8_t priority; /*!< interrupt priority,
the priority of the pended interrupts (when the same IRQ level), @ref sys_irq_priority_t
ps. This priority has NOTHING about nested interrup */
} sys_irq_attr_t;
//=============================================================================
// Global Data Definition
//=============================================================================
extern volatile uint32_t g_SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
extern volatile uint32_t g_SysTicks;
extern volatile uint32_t g_SysTickPeriod;
extern volatile uint32_t g_SysTickUnit_MS;
//=============================================================================
// Private Function Definition
//=============================================================================
//=============================================================================
// Public Function Definition
//=============================================================================
/**
* \brief Enable system tick
*/
__STATIC_FORCEINLINE void sys_enable_systick(void)
{
SysTick_Reload(g_SysTickPeriod);
ECLIC_EnableIRQ(SysTimer_IRQn);
SysTimer_Start();
return;
}
/**
* \brief Disable system tick
*/
__STATIC_FORCEINLINE void sys_disable_systick(void)
{
ECLIC_DisableIRQ(SysTimer_IRQn);
SysTimer_Stop();
return;
}
/**
* \brief Trigger software interrupt through system timer
*
* \return None
*/
__STATIC_FORCEINLINE void sys_launch_swi(void)
{
SysTimer_SetSWIRQ();
return;
}
/**
* \brief Clear software interrupt
*
* \return None
*/
__STATIC_FORCEINLINE void sys_clear_swi(void)
{
SysTimer_ClearSWIRQ();
return;
}
/**
* \brief Clear interrupt flags of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return None
*/
__STATIC_FORCEINLINE void sys_clear_IRQFlag(IRQn_Type irq_id)
{
ECLIC_ClearPendingIRQ(irq_id);
return;
}
/**
* \brief Get the pending specific interrupt of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return
* IRQ is pending or not
*
*/
__STATIC_FORCEINLINE int sys_get_IRQPending(IRQn_Type irq_id)
{
return ECLIC_GetPendingIRQ(irq_id);
}
/**
* \brief Get system ticks
*
* \return
* System Ticks
*/
__STATIC_FORCEINLINE uint32_t sys_get_tick(void)
{
return g_SysTicks;
}
/**
* \brief Open interrupt source of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return None
*/
__STATIC_FORCEINLINE void sys_open_IRQ(IRQn_Type irq_id)
{
ECLIC_EnableIRQ(irq_id);
return;
}
/**
* \brief Close interrupt source of interrupt controller
*
* \param [in] irq_id the target IRQ Id, @ref IRQn_Type
* \return None
*/
__STATIC_FORCEINLINE void sys_close_IRQ(IRQn_Type irq_id)
{
ECLIC_DisableIRQ(irq_id);
return;
}
/**
* \brief Enable global interrupt
*
* \return None
*/
__STATIC_FORCEINLINE void sys_enable_girq(void)
{
__enable_irq();
return;
}
/**
* \brief Disable global interrupt
*
* \return None
*/
__STATIC_FORCEINLINE void sys_disable_girq(void)
{
__disable_irq();
return;
}
/**
* \brief system high accuracy delay with systick
*
* \param [in] msec milli-seconds
* \return None
*/
void sys_delay(uint32_t msec);
/**
* \brief system low accuracy delay with the CPU tick
*
* \param [in] ticks the CPU ticks
* \return None
*/
void sys_busy_wait(uint32_t ticks);
/**
* \brief get system frequency
*
* \return the cpu frequency value
*/
uint32_t sys_get_cpu_freq(void);
#if defined(__EXCP_PRESENT) && (__EXCP_PRESENT == 1)
/**
* \brief Register handler to Exception table
*
* \param [in] excp_id exception ID, @ref EXCPn_Type
* \param [in] excp_handler the handler function
* \return
* 0 : ok
* others: fail
*/
int sys_excp_register_handler(EXCPn_Type excp_id, uint32_t excp_handler);
#endif
#if defined(__ECLIC_PRESENT) && (__ECLIC_PRESENT == 1)
/**
* \brief Set the attribute of the target interrupt
*
* \param [in] irq_id the terget IRQ ID, @ref IRQn_Type
* \param [in] pAttr pointer to a attribute of interrupt if necessary, @ref sys_irq_attr_t
* \return
* 0 : ok
* others: fail
*/
int sys_set_IRQAttr(IRQn_Type irq_id, sys_irq_attr_t *pAttr);
/**
* \brief Register ISR to Interrupt
*
* \param [in] irq_id the terget IRQ ID, @ref IRQn_Type
* \param [in] cb_handler the ISR funciotn
* \param [in] pAttr pointer to a attribute of interrupt if necessary, @ref sys_irq_attr_t
* \return
* 0 : ok
* others: fail
*/
int sys_register_IRQ(IRQn_Type irq_id, void *cb_handler, sys_irq_attr_t *pAttr);
#endif /* __ECLIC_PRESENT == 1 */
/**
* \brief Configure system tick
*
* \param [in] ticks period of ticks
* SYS_TICK_1_MS/ SYS_TICK_10_MS/ SYS_TICK_100_MS
*/
void sys_config_systick(uint32_t ticks);
#ifdef __cplusplus
}
#endif
#endif