#include "stm32f10x.h"
#include "includes.h"

//定义启动任务的优先级
#define START_TASK_PRIO                          3

/*************************************************************************************************************/
//UCOSIII中以下优先级用户程序不能使用,ALIENTEK
//将这些优先级分配给了UCOSIII的5个系统内部任务
//优先级0:中断服务服务管理任务 OS_IntQTask()
//优先级1:时钟节拍任务 OS_TickTask()
//优先级2:定时任务 OS_TmrTask()
//优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()
//优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()
//定义任务的优先级
#define  APP_TASK_1_PRIO                         4
#define  APP_TASK_2_PRIO                         5
#define  APP_TASK_3_PRIO                         6
#define  APP_TASK_4_PRIO                         7
#define  APP_TASK_5_PRIO                         8
#define  APP_TASK_6_PRIO                         9
#define  APP_TASK_7_PRIO                         10
#define  APP_TASK_8_PRIO                         11
#define  APP_TASK_9_PRIO                         12
#define  APP_TASK_10_PRIO                        13
#define  APP_TASK_11_PRIO                        14
#define  APP_TASK_12_PRIO                        15

//定义启动任务堆栈的大小
#define START_TASK_SIZE                          64

//定义任务堆栈的大小
#define  APP_TASK_1_STK_SIZE                     64
#define  APP_TASK_2_STK_SIZE                     64
#define  APP_TASK_3_STK_SIZE                     64
#define  APP_TASK_4_STK_SIZE                     64
#define  APP_TASK_5_STK_SIZE                     128
#define  APP_TASK_6_STK_SIZE                     128
#define  APP_TASK_7_STK_SIZE                     128
#define  APP_TASK_8_STK_SIZE                     128
#define  APP_TASK_9_STK_SIZE                     256
#define  APP_TASK_10_STK_SIZE                    256
#define  APP_TASK_11_STK_SIZE                    512
#define  APP_TASK_12_STK_SIZE                    512

/*定义启动任务控制块*/
static OS_TCB StartTaskTcb;

/*定义任务控制块*/
static OS_TCB       AppTask1TCB;
static OS_TCB       AppTask2TCB;
static OS_TCB       AppTask3TCB;
static OS_TCB       AppTask4TCB;
static OS_TCB       AppTask5TCB;
static OS_TCB       AppTask6TCB;
static OS_TCB       AppTask7TCB;
static OS_TCB       AppTask8TCB;
static OS_TCB       AppTask9TCB;
static OS_TCB       AppTask10TCB;
static OS_TCB       AppTask11TCB;
static OS_TCB       AppTask12TCB;

////定义启动任务堆栈
static CPU_STK START_TASK_STK[START_TASK_SIZE];

/**定义任务堆栈     堆栈的大小一定要合适,太大会撑爆内存导致死机,但是至少64,否则这个任务也添加不成功不会执行 **/
static CPU_STK      AppTask1STK[APP_TASK_1_STK_SIZE];
static CPU_STK      AppTask2STK[APP_TASK_2_STK_SIZE];
static CPU_STK      AppTask3STK[APP_TASK_3_STK_SIZE];
static CPU_STK      AppTask4STK[APP_TASK_4_STK_SIZE];
static CPU_STK      AppTask5STK[APP_TASK_5_STK_SIZE];
static CPU_STK      AppTask6STK[APP_TASK_6_STK_SIZE];
static CPU_STK      AppTask7STK[APP_TASK_7_STK_SIZE];
static CPU_STK      AppTask8STK[APP_TASK_8_STK_SIZE];
static CPU_STK      AppTask9STK[APP_TASK_9_STK_SIZE];
static CPU_STK      AppTask10STK[APP_TASK_10_STK_SIZE];
static CPU_STK      AppTask11STK[APP_TASK_11_STK_SIZE];
static CPU_STK      AppTask12STK[APP_TASK_12_STK_SIZE];


/*定义定时器1*/
OS_TMR tmr1;

/*定义定时器1*/
OS_TMR tmr2;

/*定义定时器1*/
OS_TMR tmr3;

//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{
    if (OSRunning == 1)  //OS是否运行标记,0,不运行;1,在运行 OS开始跑了,才执行正常的调度处理
    {
        OSIntEnter();           //进入中断
        OSTimeTick();            //调用ucos的时钟服务程序
        OSIntExit();              //触发任务切换软中断
    }
}

void led_init() {

    GPIO_InitTypeDef GPIO_InitStructure1;//定义结构体
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);//GPIOB外部时钟使能,特别重要!!!
    GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_All;//设置IO口
    GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_Out_PP;//设置为普通推挽输出
    GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;//频率50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure1);//初始化
    GPIO_SetBits(GPIOA, GPIO_Pin_All);

    GPIO_InitTypeDef GPIO_InitStructure2;//定义结构体
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);//GPIOB外部时钟使能,特别重要!!!
    GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_All;//设置IO口
    GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_Out_PP;//设置为普通推挽输出
    GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;//频率50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure2);//初始化
    GPIO_SetBits(GPIOB, GPIO_Pin_All);
}

//定时器1回调函数
void tmr1_callback(void *p_tmr, void *p_arg)
{
    if( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0)
        GPIO_SetBits(GPIOA, GPIO_Pin_0);
    else  GPIO_ResetBits(GPIOA, GPIO_Pin_0);
}

//定时器1回调函数
void tmr2_callback(void *p_tmr, void *p_arg)
{
    if( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)==0)
        GPIO_SetBits(GPIOA, GPIO_Pin_1);
    else  GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

//定时器1回调函数
void tmr3_callback(void *p_tmr, void *p_arg)
{
   if( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==0)
        GPIO_SetBits(GPIOA, GPIO_Pin_2);
    else  GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}

/***********************************************void tmrx_callback(void *p_tmr, void *p_arg).......********************************************/


/*Task1*/
void task_1(void * parm) {
    OS_ERR err;// 错误的返回
    (void )parm;

    while(1) {
        OSTimeDly(15, OS_OPT_TIME_DLY, &err);
        GPIO_SetBits(GPIOB, GPIO_Pin_0); //  高电平
        OSTimeDly(15, OS_OPT_TIME_DLY, &err);
        GPIO_ResetBits(GPIOB, GPIO_Pin_0); //  低电平
    }
}

/*Task2*/
void task_2(void * parm) {
    OS_ERR err;// 错误的返回
    (void )parm;

    while(1) {
        OSTimeDly(10, OS_OPT_TIME_DLY, &err);
        GPIO_SetBits(GPIOC, GPIO_Pin_1); //  高电平
        OSTimeDly(10, OS_OPT_TIME_DLY, &err);
        GPIO_ResetBits(GPIOC, GPIO_Pin_1); //  低电平
    }
}

/*Task3*/
void task_3(void * parm) {
      OS_ERR err;// 错误的返回
    (void )parm;

    while(1) {
        OSTimeDly(5, OS_OPT_TIME_DLY, &err);
        GPIO_SetBits(GPIOC, GPIO_Pin_2); //  高电平
        OSTimeDly(5, OS_OPT_TIME_DLY, &err);
        GPIO_ResetBits(GPIOC, GPIO_Pin_2); //  低电平
    }
}

/***********************************************void task_x(void * parm) .......********************************************/


//开始任务控制函数
void start_task(volatile void *p_arg)
{
    OS_ERR err;// 错误的返回
    p_arg = p_arg;

#if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&err);   //统计任务
#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN  //如果使能了测量中断关闭时间
    CPU_IntDisMeasMaxCurReset();
#endif

#if OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
    //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
    OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif

    CPU_SR_ALLOC();
    OS_CRITICAL_ENTER();//进入临界区代码保护

    /*创建软件定时器1*************************************************************************/
    OSTmrCreate ((OS_TMR             *)&tmr1,
                 (CPU_CHAR             *)"tmr1_led",
                 (OS_TICK               )0,//初始延迟为1*10ms
                 (OS_TICK               )50,//定时周期为50*10ms
                 (OS_OPT                )OS_OPT_TMR_PERIODIC,//周期模式
                 (OS_TMR_CALLBACK_PTR   )tmr1_callback,
                 (void                 *)0,
                 (OS_ERR               *)&err);
    OSTmrStart(&tmr1,&err);
    /*创建软件定时器1*************************************************************************/
        
        
    /*创建软件定时器1*************************************************************************/
    OSTmrCreate ((OS_TMR             *)&tmr2,
                 (CPU_CHAR             *)"tmr2_led",
                 (OS_TICK               )0,//初始延迟为1*10ms
                 (OS_TICK               )50,//定时周期为50*10ms
                 (OS_OPT                )OS_OPT_TMR_PERIODIC,//周期模式
                 (OS_TMR_CALLBACK_PTR   )tmr2_callback,
                 (void                 *)0,
                 (OS_ERR               *)&err);
    OSTmrStart(&tmr2,&err);
    /*创建软件定时器1*************************************************************************/
        
        
    /*创建软件定时器1*************************************************************************/
    OSTmrCreate ((OS_TMR             *)&tmr3,
                 (CPU_CHAR             *)"tmr3_led",
                 (OS_TICK               )0,//初始延迟为1*10ms
                 (OS_TICK               )2,//定时周期为50*10ms
                 (OS_OPT                )OS_OPT_TMR_PERIODIC,//周期模式
                 (OS_TMR_CALLBACK_PTR   )tmr3_callback,
                 (void                 *)0,
                 (OS_ERR               *)&err);
    OSTmrStart(&tmr3,&err);
    /*创建软件定时器1*************************************************************************/


    /*tast1**********************************************************************************/
    OSTaskCreate((OS_TCB     *)&AppTask1TCB, /**任务控制快*/
                 (CPU_CHAR   *)"start_task",/**任务名字*/
                 (OS_TASK_PTR ) task_1,/**任务函数*/
                 (void       *) 0,/**传递给任务函数的参数,通常不用这个参数,设置为0*/
                 (OS_PRIO     ) APP_TASK_1_PRIO,/**任务优先级*/
                 (CPU_STK    *)&AppTask1STK[0],/**任务堆栈基地址*/
                 (CPU_STK_SIZE) APP_TASK_1_STK_SIZE / 10,/**任务堆栈界限,一般为1/10*/
                 (CPU_STK_SIZE) APP_TASK_1_STK_SIZE,/**任务堆栈大小*/
                 (OS_MSG_QTY  ) 5u,/**任务内部消息队列可以接受的最大消息数目,为0时禁止接受,这个参数具体使用,看消息队列的讲解*/
                 (OS_TICK     ) 0u,/**时间片轮转时的时间片数,为0时为默认长度,具体看时间片的讲解*/
                 (void       *) 0,/**用户补充的存储区,一般不用*/
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),/**任务选项*/
                 (OS_ERR     *)&err);/**保存错误返回值,当创建不成功时会返回错误类型*/
    /*tast1**********************************************************************************/

    /*tast2**********************************************************************************/
    OSTaskCreate((OS_TCB     *)&AppTask2TCB, /**任务控制快*/
                 (CPU_CHAR   *)"start_task",/**任务名字*/
                 (OS_TASK_PTR ) task_2,/**任务函数*/
                 (void       *) 0,/**传递给任务函数的参数,通常不用这个参数,设置为0*/
                 (OS_PRIO     ) APP_TASK_2_PRIO,/**任务优先级*/
                 (CPU_STK    *)&AppTask2STK[0],/**任务堆栈基地址*/
                 (CPU_STK_SIZE) APP_TASK_2_STK_SIZE / 10,/**任务堆栈界限,一般为1/10*/
                 (CPU_STK_SIZE) APP_TASK_2_STK_SIZE,/**任务堆栈大小*/
                 (OS_MSG_QTY  ) 5u,/**任务内部消息队列可以接受的最大消息数目,为0时禁止接受,这个参数具体使用,看消息队列的讲解*/
                 (OS_TICK     ) 0u,/**时间片轮转时的时间片数,为0时为默认长度,具体看时间片的讲解*/
                 (void       *) 0,/**用户补充的存储区,一般不用*/
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),/**任务选项*/
                 (OS_ERR     *)&err);/**保存错误返回值,当创建不成功时会返回错误类型*/
    /*tast2**********************************************************************************/

    /*tast3**********************************************************************************/
    OSTaskCreate((OS_TCB     *)&AppTask3TCB, /**任务控制快*/
                 (CPU_CHAR   *)"start_task",/**任务名字*/
                 (OS_TASK_PTR ) task_3,/**任务函数*/
                 (void       *) 0,/**传递给任务函数的参数,通常不用这个参数,设置为0*/
                 (OS_PRIO     ) APP_TASK_3_PRIO,/**任务优先级*/
                 (CPU_STK    *)&AppTask3STK[0],/**任务堆栈基地址*/
                 (CPU_STK_SIZE) APP_TASK_3_STK_SIZE / 10,/**任务堆栈界限,一般为1/10*/
                 (CPU_STK_SIZE) APP_TASK_3_STK_SIZE,/**任务堆栈大小*/
                 (OS_MSG_QTY  ) 5u,/**任务内部消息队列可以接受的最大消息数目,为0时禁止接受,这个参数具体使用,看消息队列的讲解*/
                 (OS_TICK     ) 0u,/**时间片轮转时的时间片数,为0时为默认长度,具体看时间片的讲解*/
                 (void       *) 0,/**用户补充的存储区,一般不用*/
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),/**任务选项*/
                 (OS_ERR     *)&err);/**保存错误返回值,当创建不成功时会返回错误类型*/
    /*tast3**********************************************************************************/

    OS_CRITICAL_EXIT();//退出临界区代码保护

    // OSTaskDel((OS_TCB*)&StartTaskTcb, (OS_ERR*)&err);//删除指定任务
    OSTaskDel(0, &err);//删除当前任务
}


int main(void)
{
    OS_ERR err;// 错误的返回
    OSInit(&err);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

   // CPU_Init();
   // Mem_Init();
    OS_CPU_SysTickInit(BSP_CPU_ClkFreq()/(CPU_INT32U)OSCfg_TickRate_Hz);

    led_init();

    CPU_SR_ALLOC();
    OS_CRITICAL_ENTER();//进入临界区代码保护

    /*创建启动任务 由启动任务创建其他子任务*/
    OSTaskCreate((OS_TCB     *)&StartTaskTcb, /**任务控制快*/
                 (CPU_CHAR   *)"start_task",/**任务名字*/
                 (OS_TASK_PTR ) start_task,/**任务函数*/
                 (void       *) 0,/**传递给任务函数的参数,通常不用这个参数,设置为0*/
                 (OS_PRIO     ) START_TASK_PRIO,/**任务优先级*/
                 (CPU_STK    *)&START_TASK_STK[0],/**任务堆栈基地址*/
                 (CPU_STK_SIZE) START_TASK_SIZE / 10,/**任务堆栈界限,一般为1/10*/
                 (CPU_STK_SIZE) START_TASK_SIZE,/**任务堆栈大小*/
                 (OS_MSG_QTY  ) 5u,/**任务内部消息队列可以接受的最大消息数目,为0时禁止接受,这个参数具体使用,看消息队列的讲解*/
                 (OS_TICK     ) 0u,/**时间片轮转时的时间片数,为0时为默认长度,具体看时间片的讲解*/
                 (void       *) 0,/**用户补充的存储区,一般不用*/
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),/**任务选项*/
                 (OS_ERR     *)&err);/**保存错误返回值,当创建不成功时会返回错误类型*/

    OS_CRITICAL_EXIT();//退出临界区代码保护
    OSStart(&err);//启动操作系统,开始调度

    // while(1);
}