zoukankan      html  css  js  c++  java
  • stm32-ucos移植lwip-1(raw)

        之前在裸机环境下移植了lwip,功能还是很强大的,但是就我看来,这和uip其实差别也不大,其实lwip更强大的功能需要在操作系统之下才能发挥出来,今天就来做这个

        首先我们需要移植操作系统,系统选择ucos2.91,移植过程网上都有,我就写点不同的

        配置文件修改如下

    /* ---------------------- MISCELLANEOUS ----------------------- */
    #define OS_APP_HOOKS_EN           0u   /* Application-defined hooks are called from the uC/OS-II hooks */
    #define OS_ARG_CHK_EN             0u   /* Enable (1) or Disable (0) argument checking                  */
    #define OS_CPU_HOOKS_EN           1u   /* uC/OS-II hooks are found in the processor port files         */
    
    #define OS_DEBUG_EN               0u   /* Enable(1) debug variables                                    */
    
    #define OS_EVENT_MULTI_EN         0u   /* Include code for OSEventPendMulti()                          */
    #define OS_EVENT_NAME_EN          0u   /* Enable names for Sem, Mutex, Mbox and Q                      */
    
    #define OS_LOWEST_PRIO           63u   /* Defines the lowest priority that can be assigned ...         */
                                           /* ... MUST NEVER be higher than 254!                           */
    
    #define OS_MAX_EVENTS            10u   /* Max. number of event control blocks in your application      */
    #define OS_MAX_FLAGS              5u   /* Max. number of Event Flag Groups    in your application      */
    #define OS_MAX_MEM_PART           0u   /* Max. number of memory partitions                             */
    #define OS_MAX_QS                 5u   /* Max. number of queue control blocks in your application      */
    #define OS_MAX_TASKS             10u   /* Max. number of tasks in your application, MUST be >= 2       */
    
    #define OS_SCHED_LOCK_EN          1u   /* Include code for OSSchedLock() and OSSchedUnlock()           */
    
    #define OS_TICK_STEP_EN           1u   /* Enable tick stepping feature for uC/OS-View                  */
    #define OS_TICKS_PER_SEC           200u   /* Set the number of ticks in one second 1000/200 = 5 5ms中断一次 */
    
    
                                           /* --------------------- TASK STACK SIZE ---------------------- */
    #define OS_TASK_TMR_STK_SIZE    128u   /* Timer      task stack size (# of OS_STK wide entries)        */
    #define OS_TASK_STAT_STK_SIZE   128u   /* Statistics task stack size (# of OS_STK wide entries)        */
    #define OS_TASK_IDLE_STK_SIZE   128u   /* Idle       task stack size (# of OS_STK wide entries)        */
    
    
                                           /* --------------------- TASK MANAGEMENT ---------------------- */
    #define OS_TASK_CHANGE_PRIO_EN    1u   /*     Include code for OSTaskChangePrio()                      */
    #define OS_TASK_CREATE_EN         1u   /*     Include code for OSTaskCreate()                          */
    #define OS_TASK_CREATE_EXT_EN     1u   /*     Include code for OSTaskCreateExt()                       */
    #define OS_TASK_DEL_EN            1u   /*     Include code for OSTaskDel()                             */
    #define OS_TASK_NAME_EN           1u   /*     Enable task names                                        */
    #define OS_TASK_PROFILE_EN        1u   /*     Include variables in OS_TCB for profiling                */
    #define OS_TASK_QUERY_EN          1u   /*     Include code for OSTaskQuery()                           */
    #define OS_TASK_REG_TBL_SIZE      1u   /*     Size of task variables array (#of INT32U entries)        */
    #define OS_TASK_STAT_EN           1u   /*     Enable (1) or Disable(0) the statistics task             */
    #define OS_TASK_STAT_STK_CHK_EN   1u   /*     Check task stacks from statistic task                    */
    #define OS_TASK_SUSPEND_EN        1u   /*     Include code for OSTaskSuspend() and OSTaskResume()      */
    #define OS_TASK_SW_HOOK_EN        1u   /*     Include code for OSTaskSwHook()                          */
    
    
                                           /* ----------------------- EVENT FLAGS ------------------------ */
    #define OS_FLAG_EN                1u   /* Enable (1) or Disable (0) code generation for EVENT FLAGS    */
    #define OS_FLAG_ACCEPT_EN         1u   /*     Include code for OSFlagAccept()                          */
    #define OS_FLAG_DEL_EN            1u   /*     Include code for OSFlagDel()                             */
    #define OS_FLAG_NAME_EN           1u   /*     Enable names for event flag group                        */
    #define OS_FLAG_QUERY_EN          1u   /*     Include code for OSFlagQuery()                           */
    #define OS_FLAG_WAIT_CLR_EN       1u   /* Include code for Wait on Clear EVENT FLAGS                   */
    #define OS_FLAGS_NBITS           16u   /* Size in #bits of OS_FLAGS data type (8, 16 or 32)            */
    
    
                                           /* -------------------- MESSAGE MAILBOXES --------------------- */
    #define OS_MBOX_EN                1u   /* Enable (1) or Disable (0) code generation for MAILBOXES      */
    #define OS_MBOX_ACCEPT_EN         1u   /*     Include code for OSMboxAccept()                          */
    #define OS_MBOX_DEL_EN            1u   /*     Include code for OSMboxDel()                             */
    #define OS_MBOX_PEND_ABORT_EN     1u   /*     Include code for OSMboxPendAbort()                       */
    #define OS_MBOX_POST_EN           1u   /*     Include code for OSMboxPost()                            */
    #define OS_MBOX_POST_OPT_EN       1u   /*     Include code for OSMboxPostOpt()                         */
    #define OS_MBOX_QUERY_EN          1u   /*     Include code for OSMboxQuery()                           */
    
    
                                           /* --------------------- MEMORY MANAGEMENT -------------------- */
    #define OS_MEM_EN                 1u   /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */
    #define OS_MEM_NAME_EN            1u   /*     Enable memory partition names                            */
    #define OS_MEM_QUERY_EN           1u   /*     Include code for OSMemQuery()                            */
    
    
                                           /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */
    #define OS_MUTEX_EN               1u   /* Enable (1) or Disable (0) code generation for MUTEX          */
    #define OS_MUTEX_ACCEPT_EN        1u   /*     Include code for OSMutexAccept()                         */
    #define OS_MUTEX_DEL_EN           1u   /*     Include code for OSMutexDel()                            */
    #define OS_MUTEX_QUERY_EN         1u   /*     Include code for OSMutexQuery()                          */
    
    
                                           /* ---------------------- MESSAGE QUEUES ---------------------- */
    #define OS_Q_EN                   1u   /* Enable (1) or Disable (0) code generation for QUEUES         */
    #define OS_Q_ACCEPT_EN            1u   /*     Include code for OSQAccept()                             */
    #define OS_Q_DEL_EN               1u   /*     Include code for OSQDel()                                */
    #define OS_Q_FLUSH_EN             1u   /*     Include code for OSQFlush()                              */
    #define OS_Q_PEND_ABORT_EN        1u   /*     Include code for OSQPendAbort()                          */
    #define OS_Q_POST_EN              1u   /*     Include code for OSQPost()                               */
    #define OS_Q_POST_FRONT_EN        1u   /*     Include code for OSQPostFront()                          */
    #define OS_Q_POST_OPT_EN          1u   /*     Include code for OSQPostOpt()                            */
    #define OS_Q_QUERY_EN             1u   /*     Include code for OSQQuery()                              */
    
    
                                           /* ------------------------ SEMAPHORES ------------------------ */
    #define OS_SEM_EN                 1u   /* Enable (1) or Disable (0) code generation for SEMAPHORES     */
    #define OS_SEM_ACCEPT_EN          1u   /*    Include code for OSSemAccept()                            */
    #define OS_SEM_DEL_EN             1u   /*    Include code for OSSemDel()                               */
    #define OS_SEM_PEND_ABORT_EN      1u   /*    Include code for OSSemPendAbort()                         */
    #define OS_SEM_QUERY_EN           1u   /*    Include code for OSSemQuery()                             */
    #define OS_SEM_SET_EN             1u   /*    Include code for OSSemSet()                               */
    
    
                                           /* --------------------- TIME MANAGEMENT ---------------------- */
    #define OS_TIME_DLY_HMSM_EN       1u   /*     Include code for OSTimeDlyHMSM()                         */
    #define OS_TIME_DLY_RESUME_EN     1u   /*     Include code for OSTimeDlyResume()                       */
    #define OS_TIME_GET_SET_EN        1u   /*     Include code for OSTimeGet() and OSTimeSet()             */
    #define OS_TIME_TICK_HOOK_EN      1u   /*     Include code for OSTimeTickHook()                        */
    
    
                                           /* --------------------- TIMER MANAGEMENT --------------------- */
    #define OS_TMR_EN                 0u   /* Enable (1) or Disable (0) code generation for TIMERS         */
    #define OS_TMR_CFG_MAX           16u   /*     Maximum number of timers                                 */
    #define OS_TMR_CFG_NAME_EN        1u   /*     Determine timer names                                    */
    #define OS_TMR_CFG_WHEEL_SIZE     8u   /*     Size of timer wheel (#Spokes)                            */
    #define OS_TMR_CFG_TICKS_PER_SEC 10u   /*     Rate at which timer management task runs (Hz)            */

        因为之前我们有一个lwip_timer的变量,代表了网络系统的时钟心跳,使用的是定时器6,这时候定时器6被操作系统占用了,我们就设置一个新的定时器7作为网络心跳定时器,如下

    //定时器6中断服务程序     
    void TIM6_IRQHandler(void)
    {     
        OSIntEnter();        //进入中断
        if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
        {
            TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源     
            OSTimeTick();       //调用ucos的时钟服务程序               
                
        }     
        OSIntExit();        //触发任务切换软中断
    }
     
    
    
    
    
    //基本定时器6中断初始化
    //这里时钟选择为APB1的2倍,而APB1为36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器3!
    void TIM6_Int_Init(u16 arr,u16 psc)
    {    
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //时钟使能
    
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值     计数到5000为500ms
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
     
        TIM_ITConfig( TIM6,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//使能定时器6更新触发中断
     
        TIM_Cmd(TIM6, ENABLE);  //使能TIMx外设
         
          NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器                                  
    }
    
    
    
    
    //基本定时器7中断初始化
    //这里时钟选择为APB1的2倍,而APB1为36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器7!
    void TIM7_Int_Init(u16 arr,u16 psc)
    {    
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); //时钟使能
    
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值     计数到5000为500ms
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
     
        TIM_ITConfig( TIM7,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//使能定时器6更新触发中断
     
        TIM_Cmd(TIM7, ENABLE);  //使能TIMx外设
         
          NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器                                  
    }
    
    u32 lwip_timer=0;//lwip 计时器,每10ms增加1.
    
    
    //定时器7中断服务程序     
    void TIM7_IRQHandler(void)
    {     
        OSIntEnter();        //进入中断
        if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
        {
            TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源     
            lwip_timer++;//lwip计时器增加1    
        }     
        OSIntExit();        //触发任务切换软中断
    }

        到这里基本上就可以跑系统了(系统具体移植参见之前的文章)

        接下来就是创建任务

    void start_task(void *pdata)
    {
        OS_CPU_SR cpu_sr=0;
        pdata = pdata; 
        OSStatInit();                    //初始化统计任务.这里会延时1秒钟左右    
         OS_ENTER_CRITICAL();            //进入临界区(无法被中断打断)    
         OSTaskCreate(led1_task,(void *)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);                           
         OSTaskCreate(led2_task,(void *)0,(OS_STK*)&LED2_TASK_STK[LED2_STK_SIZE-1],LED2_TASK_PRIO);
        OSTaskCreate(lwip_task,(void *)0,(OS_STK*)&LWIP_TASK_STK[LWIP_STK_SIZE-1],LWIP_TASK_PRIO);
        OSTaskSuspend(START_TASK_PRIO);    //挂起起始任务.
        OS_EXIT_CRITICAL();                //退出临界区(可以被中断打断)
    }

        我们将lwip创建成为了一个单独的任务,该任务的运行代码如下

    //创建任务堆栈空间    
    OS_STK LWIP_TASK_STK[LWIP_STK_SIZE];
    
    
    #define CLOCKTICKS_PER_MS 10    //定义时钟节拍
    
    static ip_addr_t ipaddr, netmask, gw;     //定义IP地址
    struct netif enc28j60_netif;              //定义网络接口
    u32_t input_time;
    u32_t last_arp_time;            
    u32_t last_tcp_time;    
    u32_t last_ipreass_time;
    
    u32_t last_dhcp_fine_time;            
    u32_t last_dhcp_coarse_time;  
    u32 dhcp_ip=0;
    
    //LWIP查询
    void LWIP_Polling(void)
    {
        if(timer_expired(&input_time,5)) //接收包,周期处理函数
        {
            ethernetif_input(&enc28j60_netif); 
        }
        if(timer_expired(&last_tcp_time,TCP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//TCP处理定时器处理函数
        {
            tcp_tmr();
        }
        if(timer_expired(&last_arp_time,ARP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//ARP处理定时器
        {
            etharp_tmr();
        }
        if(timer_expired(&last_ipreass_time,IP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//IP重新组装定时器
        { 
            ip_reass_tmr();
        }                                   
    }
    
    
    
    void lwip_task(void *pdata)
    {
        u8 t_client_cnt = 0;
        IP4_ADDR(&ipaddr, 192, 168, 1, 110);          //设置本地ip地址
        IP4_ADDR(&gw, 192, 168, 1, 1);            //网关
        IP4_ADDR(&netmask, 255, 255, 255, 0);        //子网掩码    
        //初始化LWIP定时器
        init_lwip_timer();  
        //初始化LWIP协议栈,执行检查用户所有可配置的值,初始化所有的模块
        lwip_init();
        //添加网络接口
        while((netif_add(&enc28j60_netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input)==NULL))
        {
            LCD_ShowString(0,0,240,320,(u8*)"ENC28J60 Init Failed             ",LCD_BLACK);
            OSTimeDly(20);
            LCD_ShowString(0,0,240,320,(u8*)"                                 ",LCD_BLACK);
            OSTimeDly(20);
        }
        LCD_ShowString(0,0,240,320,(u8*)"ENC28J60 Init OK                     ",LCD_BLACK);
        //注册默认的网络接口
        netif_set_default(&enc28j60_netif);
        //建立网络接口用于处理通信
        netif_set_up(&enc28j60_netif); 
        
        Tcp_Client_Init();//初始化tcp客户端
        
        LCD_ShowString(0,12,240,320,(u8*)"TCP CLIENT INIT                      ",LCD_BLACK);
        LCD_ShowString(0,24,240,320,(u8*)"TCP CLIENT Disconnect                ",LCD_BLACK);
        LCD_ShowString(0,36,240,320,(u8*)"RX:                                  ",LCD_BLACK);
        LCD_ShowString(0,48,240,320,(u8*)"TX:                                  ",LCD_BLACK);
        
        while(1)
        {
            OSTimeDly(2);//注意这个延时,和定时器7初始化的时间必须一致,CLOCKTICKS_PER_MS一致
            LWIP_Polling();
            if((lwip_tcp_client_flag&LWIP_CONNECTED)==LWIP_CONNECTED)
            {
                LCD_ShowString(0,24,240,320,(u8*)"TCP CLIENT Connect                     ",LCD_BLACK);
                if(keyValue == KEY_RIGHT)
                {
                    t_client_cnt++;
                    sprintf((char*)lwip_client_buf,"tcp_client send %d
    ",t_client_cnt);    
                    LCD_ShowString(18,48,240,320,(u8*)lwip_client_buf,LCD_BLACK);//显示当前发送数据
                    lwip_tcp_client_flag |= LWIP_SEND_DATA;            //标记有数据需要发送
                    keyValue = 0;
                }
            }
            else
            {
    //            Tcp_Client_Connect_Remotehost();//没有连接上,此时处于TCP客户端模式,则尝试重新连接
            }
            
            if((lwip_tcp_client_flag&LWIP_NEW_DATA)==LWIP_NEW_DATA)
            {
                LCD_ShowString(18,36,240,320,(u8*)lwip_client_buf,LCD_BLACK);
                lwip_tcp_client_flag &=~LWIP_NEW_DATA;        //清除接受数据的标志
            }
        }
    }

         和之前的raw模式不带系统差不多,这一章只是一个引导,不想这么玩的可以看下一章直接使用netconn,好了到此为止

    哦对了,代码链接在下面

    http://download.csdn.net/detail/dengrengong/8599061
  • 相关阅读:
    Splay板子
    HZOI帝国2019欢乐时刻
    数据分析体系 — 用户粘性的两个计算指标(DAU/MAU和月人均活跃天数)
    mysql—MySQL数据库中10位时间戳转换为标准时间后,如何对标准时间进行加减X天处理
    每日一题力扣575 分糖果
    每日一题力扣455 小饼干和孩子
    每日一题力扣561
    每日一题力扣121 最佳买股票
    每日一题力扣605 种花问题
    每日一题力扣605 种花问题
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4433556.html
Copyright © 2011-2022 走看看