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\r\n",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

 

posted @ 2015-04-16 22:43  邓小俊  阅读(2449)  评论(0编辑  收藏  举报