
#ifndef __CPU_DEF_H__
#define __CPU_DEF_H__

#include "csi_rv32_gcc.h"
#include "core_rv32.h"
#include "system.h"

#ifdef OMW_HAS_SCH
#include "omw_rtos.h"
#endif

#define  ATTRIBUTE_ISR      __attribute__ ((interrupt ("machine")))
#define  __PACKED           __attribute__ ((__packed__))
#define  __WEAK             __attribute__((weak))

#define     __IM     volatile const      /*! Defines 'read only' structure member permissions */
#define     __OM     volatile            /*! Defines 'write only' structure member permissions */
#define     __IOM    volatile            /*! Defines 'read / write' structure member permissions */
/* -------------------------  Interrupt Number Definition  ------------------------ */

#define omw_set_irq_prio     csi_vic_set_prio
#define omw_enable_irq       csi_vic_enable_irq

#define IRQN_OFFSET   16

#define IRQ_CRITICAL_PRIORITY   4
#define IRQ_HIGH_PRIORITY       3
#define IRQ_MED_PRIORITY        2
#define IRQ_LOW_PRIORITY        1

typedef enum IRQn
{
/* -------------------  Processor Exceptions Numbers  ----------------------------- */



  SoftIrq_IRQn                = 3,     /*  SoftIrq Interrupt */



  SysTick_IRQn                = 7,     /*  System tick Interrupt */



  ExtIrq_IRQn                 = 11,     /* ExtIrq Interrupt */




/* -------------------  Processor Interrupt Numbers  ------------------------------ */
  WDT_IRQn                      =   0 + IRQN_OFFSET,
  Interrupt1_IRQn               =   1 + IRQN_OFFSET,
  RADIO_DMA_IRQn                =   2 + IRQN_OFFSET,
  RADIO_TICK_IRQn               =   3 + IRQN_OFFSET,
  Interrupt4_IRQn               =   4 + IRQN_OFFSET,
  Interrupt5_IRQn               =   5 + IRQN_OFFSET,
  Interrupt6_IRQn               =   6 + IRQN_OFFSET,
  Interrupt7_IRQn               =   7 + IRQN_OFFSET,
  UART0_IRQn                    =   8 + IRQN_OFFSET,
  UART1_IRQn                    =   9 + IRQN_OFFSET,
  SPIM0_IRQn                    =   10 + IRQN_OFFSET,
  SPIM1_IRQn                    =   11 + IRQN_OFFSET,
  I2C0_IRQn                     =   12 + IRQN_OFFSET,
  Interrupt13_IRQn              =   13 + IRQN_OFFSET,
  SPIS0_IRQn                    =   14 + IRQN_OFFSET,
  USB_IRQn                      =   15 + IRQN_OFFSET,
  GPIO_IRQn                     =   16 + IRQN_OFFSET,
  QDEC_IRQn                     =   17 + IRQN_OFFSET,
  AES_IRQn                      =   18 + IRQN_OFFSET,
  CAPTURE_IRQn                  =   19 + IRQN_OFFSET,
  CLKCAL_IRQn                   =   20 + IRQN_OFFSET,
  RTC_IRQn                      =   21 + IRQN_OFFSET,
  SDMA_IRQn                     =   22 + IRQN_OFFSET,
  Interrupt23_IRQn              =   23 + IRQN_OFFSET,
  TIMER0_IRQn                   =   24 + IRQN_OFFSET,
  TIMER1_IRQn                   =   25 + IRQN_OFFSET,
  TIMER2_IRQn                   =   26 + IRQN_OFFSET,
  TIMER3_IRQn                   =   27 + IRQN_OFFSET,
  TIMER4_IRQn                   =   28 + IRQN_OFFSET,
  TIMER5_IRQn                   =   29 + IRQN_OFFSET,
  TIMER6_IRQn                   =   30 + IRQN_OFFSET,
  TIMER7_IRQn                   =   31 + IRQN_OFFSET,
  /* Interrupts 10 .. 31 are left out */
} IRQn_Type;

#define  SOFT_IRQ_CTRL_BASE (0xE0000000)
#define  TRIGGER_SOFT_IRQ()   (*(volatile uint32_t *)SOFT_IRQ_CTRL_BASE = 1)
#define  CLR_SOFT_IRQ()       (*(volatile uint32_t *)SOFT_IRQ_CTRL_BASE = 0)

/// Interrupt Enable bit in mstatus register
#define INTE_EN_BIT_POS 3
#define INTE_EN (1 << INTE_EN_BIT_POS)

#define GLOBAL_INT_START()                                                            \
    do                                                                                \
    {                                                                                 \
        int mstatus;                                                                  \
        __asm__ volatile ("csrrsi %0, mstatus, %1" : "=r" (mstatus) : "i" (INTE_EN)); \
    } while (0)

#define GLOBAL_INT_STOP()                                                             \
    do                                                                                \
    {                                                                                 \
        int mstatus;                                                                  \
        __asm__ volatile ("csrrci %0, mstatus, %1" : "=r" (mstatus) : "i" (INTE_EN)); \
    } while (0)

// static inline void
// omw_hw_chk_and_en_irq(void)
// {
//     //work round: for irq issue
//     uint32_t result;
//     result = __get_MSTATUS();

//     if ((result & INTE_EN) == 0){
//         __enable_irq();
//     }
// }

void omw_hw_chk_and_en_irq(void);

#if defined(OMW_BLE_ONLY_V0)// && !defined(OMW_HAS_SCH)
#define ATOMIC_SECTION_BEGIN()                                                         \
    do                                                                                 \
    {                                                                                  \
        int irq_rest;                                                                  \
        __asm__ volatile ("csrrci %0, mstatus, %1" : "=r" (irq_rest) : "i" (INTE_EN));

#define ATOMIC_SECTION_END()                                                  \
    /* Restore mstatus to its previous value */                               \
    __asm__ volatile ("csrw mstatus, %0" : /* no output */ : "r" (irq_rest)); \
    } while (0);

// #define omw_hw_chk_and_en_irq()
#define omw_hw_set_in_irq_flag()
#define omw_hw_clr_in_irq_flag()
#define omw_hw_disable_irq_in_task_context()
#define omw_hw_enable_irq_in_task_context()
#else
#define DISABLE_IRQ_SAVE()     ({int irq_rest; __asm__ volatile ("csrrci %0, mstatus, %1" : "=r" (irq_rest) : "i" (INTE_EN)); irq_rest;})
#define RESTORE_IRQ(ctx)   ({__asm__ volatile ("csrw mstatus, %0" : /* no output */ : "r" (ctx));})

// extern volatile uint8_t g_is_in_critical;
extern volatile uint8_t g_is_in_irq_flag;

//ALL INT ISR which may call bussniess code need to call
//omw_hw_set_in_irq_flag at entry, and omw_hw_clr_in_irq_flag at exit
static inline void
omw_hw_set_in_irq_flag(void)
{
    g_is_in_irq_flag = 1;
}

static inline void
omw_hw_clr_in_irq_flag(void)
{
    g_is_in_irq_flag = 0;
}

static inline uint8_t
omw_hw_is_in_irq_context(void)
{
    return g_is_in_irq_flag;
}

// static inline uint8_t
// omw_hw_is_in_critical(void)
// {
//     return g_is_in_critical;
// }

/* never call this two function nested, like:
    omw_hw_disable_irq_in_task_context();
        ....
        omw_hw_disable_irq_in_task_context();
        ....
        omw_hw_enable_irq_in_task_context();
        ....
    omw_hw_enable_irq_in_task_context();
*/
static inline void
omw_hw_disable_irq_in_task_context(void)
{
    if (!g_is_in_irq_flag) __disable_irq();
}

static inline void
omw_hw_enable_irq_in_task_context(void)
{
    if (!g_is_in_irq_flag) __enable_irq();
}

// uint32_t omw_hw_enter_critical(void);
// void omw_hw_exit_critical(uint32_t ctx);

#define ATOMIC_SECTION_BEGIN()                   \
    uint32_t irq_flag = omw_rtos_enter_critical();  \
    {

#define ATOMIC_SECTION_END()                     \
    }                                            \
    omw_rtos_exit_critical(irq_flag);

/*
#define ATOMIC_SECTION_BEGIN()                   \
    omw_hw_disable_irq_in_task_context();  \
    {

#define ATOMIC_SECTION_END()                     \
    }                                            \
    omw_hw_enable_irq_in_task_context();
*/
#endif
#ifndef FlagStatus
#ifndef IS_FLAG_STATUS_RESET
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
#define IS_FLAG_STATUS_RESET(state) ((state== RESET) || (state == RESET))
#endif
#endif

#ifndef FunctionalState
#ifndef IS_FUNCTIONAL_STATE
typedef enum {DISABLE = 0, ENABLE =1} FunctionalState;
#define IS_FUNCTIONAL_STATE(state) ((state== DISABLE) || (state == ENABLE))
#endif
#endif

typedef enum
{
  SUCCESS = 0,
  ERROR = !SUCCESS
} ErrorStatus;

/**
  * @}
  */


/** @brief Booelan definition */
typedef uint8_t BOOL;

/**@brief TRUE, FALSE definition */
#ifndef Boolean
#ifndef IS_BOOLEAN
typedef enum {FALSE = 0, TRUE =1} Boolean;
#define IS_BOOLEAN(bool) ((bool == FALSE) || (bool == TRUE))
#endif
#endif

#endif
