/**
 ****************************************************************************************************
 * @file        delay.c
 * @author      ԭŶ(ALIENTEK)
 * @version     V1.1
 * @date        2023-02-25
 * @brief       ʹSysTickͨģʽӳٽй(֧ucosii)
 *              ṩdelay_initʼ delay_usdelay_msʱ
 * @license     Copyright (c) 2022-2032, ӿƼ޹˾
 ****************************************************************************************************
 * @attention
 *
 * ʵƽ̨:ԭ STM32F103
 * Ƶ:www.yuanzige.com
 * ̳:www.openedv.com
 * ˾ַ:www.alientek.com
 * ַ:openedv.taobao.com
 *
 * ޸˵
 * V1.0 20230206
 * һη
 * V1.1 20230225
 * ޸SYS_SUPPORT_OSִ, ĬϽ֧UCOSII 2.93.01汾, OSοʵ
 * ޸delay_initʹ8Ƶ,ȫͳһʹMCUʱ
 * ޸delay_usʹʱժȡʱ, OS
 * ޸delay_msֱʹdelay_usʱʵ.
 *
 ****************************************************************************************************
 */

#include "sys.h"
#include "delay.h"


static uint32_t g_fac_us = 0;       /* usʱ */

/* SYS_SUPPORT_OS,˵Ҫ֧OS(UCOS) */
#if SYS_SUPPORT_OS

/* ӹͷļ ( ucosҪõ) */
#include "os.h"

/* g_fac_ms, ʾmsʱı, ÿĵms, (ʹosʱ,Ҫõ) */
static uint16_t g_fac_ms = 0;

/*
 *  delay_us/delay_msҪ֧OSʱҪOSصĺ궨ͺ֧
 *  3궨:
 *      delay_osrunning    :ڱʾOSǰǷ,ԾǷʹغ
 *      delay_ostickspersec:ڱʾOS趨ʱӽ,delay_initʼsystick
 *      delay_osintnesting :ڱʾOSжǶ׼,Ϊж治Ե,delay_msʹøò
 *  Ȼ3:
 *      delay_osschedlock  :OS,ֹ
 *      delay_osschedunlock:ڽOS,¿
 *      delay_ostimedly    :OSʱ,.
 *
 *  ̽UCOSII֧,OS,вοֲ
 */

/* ֧UCOSII */
#define delay_osrunning     OSRunning           /* OSǷб,0,;1, */
#define delay_ostickspersec OS_TICKS_PER_SEC    /* OSʱӽ,ÿȴ */
#define delay_osintnesting  OSIntNesting        /* жǶ׼,жǶ״ */


/**
 * @brief     usʱʱ,ر(ֹusӳ)
 * @param     
 * @retval    
 */
void delay_osschedlock(void)
{
    OSSchedLock();                      /* UCOSIIķʽ,ֹȣֹusʱ */
}

/**
 * @brief     usʱʱ,ָ
 * @param     
 * @retval    
 */
void delay_osschedunlock(void)
{
    OSSchedUnlock();                    /* UCOSIIķʽ,ָ */
}

/**
 * @brief     usʱʱ,ָ
 * @param     ticks: ʱĽ
 * @retval    
 */
void delay_ostimedly(uint32_t ticks)
{
    OSTimeDly(ticks);                               /* UCOSIIʱ */
}

/**
 * @brief     systickжϷ,ʹOSʱõ
 * @param     ticks : ʱĽ  
 * @retval    
 */  
void SysTick_Handler(void)
{
    /* OS ʼ,ִĵȴ */
    if (delay_osrunning == OS_TRUE)
    {
        /*  uC/OS-II  SysTick жϷ */
        OS_CPU_SysTickHandler();
    }
    HAL_IncTick();
}
#endif

/**
 * @brief     ʼӳٺ
 * @param     sysclk: ϵͳʱƵ, CPUƵ(rcc_c_ck), 72MHz
 * @retval    
 */  
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS                                      /* Ҫ֧OS */
    uint32_t reload;
#endif
    g_fac_us = sysclk;                                  /* HAL_InitѶsystickã */
#if SYS_SUPPORT_OS                                      /* Ҫ֧OS. */
    reload = sysclk;                                    /* ÿӵļ λΪM */
    reload *= 1000000 / delay_ostickspersec;            /* delay_ostickspersec趨ʱ,reloadΪ24λ
                                                         * Ĵ,ֵ:16777216,72M,Լ0.233s
                                                         */
    g_fac_ms = 1000 / delay_ostickspersec;              /* OSʱٵλ */
    SysTick->CTRL |= 1 << 1;                            /* SYSTICKж */
    SysTick->LOAD = reload;                             /* ÿ1/delay_ostickspersecжһ */
    SysTick->CTRL |= 1 << 0;                            /* SYSTICK */
#endif 
}

/**
 * @brief     ʱnus
 * @note      ǷʹOS, ʱժȡusʱ
 * @param     nus: Ҫʱus
 * @note      nusȡֵΧ: 0 ~ (2^32 / fac_us) (fac_usһϵͳƵ, )
 * @retval    
 */
void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD;        /* LOADֵ */
    ticks = nus * g_fac_us;                 /* ҪĽ */
    
#if SYS_SUPPORT_OS                          /* Ҫ֧OS */
    delay_osschedlock();                    /*  OS  */
#endif

    told = SysTick->VAL;                    /* սʱļֵ */
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;        /* עһSYSTICKһݼļͿ */
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks) 
            {
                break;                      /* ʱ䳬/Ҫӳٵʱ,˳ */
            }
        }
    }

#if SYS_SUPPORT_OS                          /* Ҫ֧OS */
    delay_osschedunlock();                  /* ָ OS  */
#endif 

}

/**
 * @brief     ʱnms
 * @param     nms: Ҫʱms (0< nms <= (2^32 / fac_us / 1000))(fac_usһϵͳƵ, )
 * @retval    
 */
void delay_ms(uint16_t nms)
{
    
#if SYS_SUPPORT_OS  /* Ҫ֧OS, osʱͷCPU */
    if (delay_osrunning && delay_osintnesting == 0)     /* OSѾ,Ҳж(ж治) */
    {
        if (nms >= g_fac_ms)                            /* ʱʱOSʱ */
        {
            delay_ostimedly(nms / g_fac_ms);            /* OSʱ */
        }

        nms %= g_fac_ms;                                /* OSѾ޷ṩôСʱ,ͨʽʱ */
    }
#endif

    delay_us((uint32_t)(nms * 1000));                   /* ͨʽʱ */
}

/**
 * @brief       HALڲõʱ
 * @note        HALʱĬSystickûпSystickжϻᵼµʱ޷˳
 * @param       Delay : Ҫʱĺ
 * @retval      None
 */
void HAL_Delay(uint32_t Delay)
{
     delay_ms(Delay);
}










