/**************************************************************************//**
 * @item     CosyOS-III 例程（服务应用）
 * @file     event_binary.c
 * @brief    事件同步_二值信号量
 * @details  通过二值信号量的{给予->获取}，实现中断对任务的事件同步。
 * @note     事件处理线程（task_1）中，可以实现超时处理机制。
 * @author   迟凯峰
 * @version  V1.0.0
 * @date     2026.07.31
 ******************************************************************************/

/*-------------------------------------------------------*
 | 服务                | 描述                            |
 |---------------------+---------------------------------|
 | uTakeBin(bin, tick) | 任务中获取二值信号量            |
 |---------------------+---------------------------------|
 | iGiveBin(bin)       | 中断中给予二值信号量 - FIFO服务 |
 |---------------------+---------------------------------|
 | pGiveBin(bin)       | 中断中给予二值信号量 - FLAG服务 |
 *-------------------------------------------------------*/

#if 0 /* 编译开关 */

#include "CosyOS.H"

uCreateBin(bin_1, false); // 创建二值信号量，用于事件同步，初值为false（任务中首次获取时不能立即成功获取而阻塞）
bool give_bin_1 = false; // 给予bin_1标志位，用于FLAG服务，初值为false

/**
 * \brief    task_1
 * \details  协作处理更为耗时的事务。
 */
uCreateTask(task_1, 1, 384, 0, 0)
{
    while(1){
        if(uTakeBin(bin_1, xTick_ms(500))){ // 如果超时时间为~0，任务将进入无尽的阻塞（直到成功获取后转为就绪），不再支持超时处理
            /* 处理事件 开始 */
            
            /* 处理事件 结束 */
        }
        else{
            /* 超时处理 开始 */
            
            /* 超时处理 结束 */
        }
    }
}

/**
 * \brief    某中断
 * \details  先对事件做必要的紧急处理，再同步至task_1 做后续处理。
 */
void XXXx_IRQHandler(void) // interrupt XXXx_VECTOR
{
    /* 清中断标志位 开始 */
    
    /* 清中断标志位 结束 */
    /* 紧急处理事件 开始 */
    
    /* 紧急处理事件 结束 */
    /* 同步至task_1 开始 */// 可采用 FIFO服务 或 FLAG服务
    /* 采用 FIFO服务 */
    iGiveBin(bin_1);       // 给予bin_1
    /* 采用 FLAG服务 */
////give_bin_1 = true;     // 先设置标志位
////iPendSV_Set();         // 再触发PendSV，而后在 pendsv_hook 中调用并执行服务
    /* 同步至task_1 结束 */
}

/**
 * \brief    挂起服务钩子
 * \details  当需要在中断中完成特定的服务功能时，可先设置一个标志位，再触发 PendSV；
             而后在 pendsv_hook 中查询该标志位，为真就清除标志位，而后调用相应服务。
 * \note     此处应调用前缀为“p”的中断挂起服务。
 */
void pendsv_hook(void) MCUCFG_OSIT_ATTRIBUTE
{
    if(give_bin_1){ // 查询标志位
        give_bin_1 = false; // 清除标志位
        pGiveBin(bin_1);    // 给予bin_1
    }
}

/** 启动钩子 */
void start_hook(void)
{
    uStartTask_Ready(task_1); // 启动task_1，初始状态为就绪状态
}

#endif
