⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osportco.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
字号:
/*
 * FILENAME: osportco.c
 *
 * Copyright  2002 By InterNiche Technologies Inc. All rights reserved
 *
 *    Code to map NicheTask "TK_" macros and other port routines
 * to CronOS RTOS on Samsung/ARM SNDS300 board. 
 *
 * MODULE: SNDS300
 *
 * PORTABLE: no
 */



#include "includes.h"      /* from ChronOS directory */

#include "ipport.h"        /* from Interniche directory */
#include "osport.h"
#include "zprint.h"

#ifndef CHRONOS
#error - must define CHRONOS in ipport.h to use this file
#endif

#include "in_utils.h"
#include "memwrap.h"


int      rcvdq_semaphore;  /* fake semaphore */
int      freeq_semaphore;  /* fake semaphore */

void *   net_task_sem_ptr = NULL;
void *   receiveq_sem_ptr;
void *   freeq_sem_ptr;

/* state of ints, saved by XXlock_net_res() */
int   netq_intmask;

INT8U    netmain_prio = 0;    /* ID of netmain task, for SignalPktDemux() */

extern void samsung_setup(void);
extern int  netmain(void);

/* Define C code main entry point.  */

void
cmain(void)
{
  // signed short result;
   
   samsung_setup();             /* must add */
//   OSInit();     /* Init uCOS */
  Printu_Net("test printf\r\n");
   /* get the uCOS semaphore used for LOCK_NET_RESOURCE(RESID_NET) */
   net_task_sem_ptr = (void*)OSSemCreate(1);
   if (!net_task_sem_ptr)
      panic("net_task_sem_ptr create err"); 

   /* set fake semaphore pointers for RESID_FREEQ and RESID_RCVDQ */
   receiveq_sem_ptr = &rcvdq_semaphore;
   freeq_sem_ptr = &freeq_semaphore;

   /* We have to lock scheduler while creating net tasks. Even though the RTOS
    * technically running yet, the ISR hooks to change tasks don't know this.
    * Since the UART uses interrupts heavly, we have to resort to this to
    * get console output during net_init.
    */
// OSLockNesting++;
   OSSchedLock();
 if(0 !=  netmain()) panic("<<<netmain critcal error>>>");        /* Create net tasks */
   OSSchedUnlock();
// OSLockNesting--;
// OSStart();        /* Jump to CronOS - Start system; never returns */
// panic("uCOS returned");
}


u_char
uCOS_self(void)
{
   /* Return uCOS currently running task ID */
   return(OSTCBCur->OSTCBPrio);
}

int rcvdq_locks = 0;
int freeq_locks = 0;

void
LOCK_NET_RESOURCE(void * semptr)
{
   INT8U error;

   if(semptr == net_task_sem_ptr)
   {
      /* net task needs a real semaphore */
      OSSemPend((OS_EVENT *)net_task_sem_ptr, 0, &error);
      if(error)
      {
         int errct = 0;

         /* sometimes we get a "timeout" error even though we passed a zero
          * to indicate we'll wait forever. When this happens, try again:
          */
         while(error == 10)
         {
            if(errct++ > 1000)
            {
               dtrap("osportco 0\n");    /* fatal? */
               return;
            }
            OSSemPend((OS_EVENT *)net_task_sem_ptr, 0, &error);
         }
      }
   }
   else if(semptr == receiveq_sem_ptr)
   {

   /* Other two cases are for locking the rcvdq or free queues.  It
    * turns out to work fine to just disable ints around queue put|get
    * operation. This allows the lock to be done from an ISR, which should
    * not be playing with real semaphores. It is only called when an item
    * added to the head or delated from the tail of a queue (both very fast)
    * so this design does not compromise realtime performance.
    */

      rcvdq_locks++;
/*      netq_intmask = INTMASK;        save interrupt state */
/*      INTMASK |= GLOBAL_INT;         disable all interrupts (global bit) */
/*      EA = 0;                        disable all interrupts */  
      OSSchedLock();
   }
   else if (semptr == freeq_sem_ptr)
   {
      freeq_locks++;
/*      netq_intmask = INTMASK;        save interrupt state */
/*      INTMASK |= GLOBAL_INT;         disable all interrupts (global bit) */
/*      EA = 0;                       disable all interrupts */
      OSSchedLock();
   }

   return;
}



void
UNLOCK_NET_RESOURCE(void * semptr)
{
   INT8U error;
   
   if(semptr == net_task_sem_ptr)
   {
      /* net task uses a real semaphore */
      error = OSSemPost((OS_EVENT *)net_task_sem_ptr);
      if(error)
      {
         dtrap("osportco 1\n");
      }
   }
   else if (semptr == receiveq_sem_ptr)
   {
      rcvdq_locks--;
      OSSchedUnlock();
   }
   else if (semptr == freeq_sem_ptr)
   {
      freeq_locks--;
      OSSchedUnlock();
   }

   if((freeq_locks + rcvdq_locks) == 0)
/*      INTMASK &= ~GLOBAL_INT;        enable global interrupt bit */
/*      EA = 1;                           enable global interrupt bit */

   return;
}


/*
 * Here's the workaround to an unusual quirk of ChonOS - It
 * cannot have multiple tasks of the same priority. Networking systems
 * are best done with a few threads which have equal priority and thus 
 * ensure fair CPU sharing without convoluted priority balancing. This 
 * means we have to guess a priority for each of our net tasks and then
 * code tk_yield() to force a non-zero delay (one tick), to ensure that all
 * the network tasks get a round-robin slot to do their thing. Of course
 * we could alter the code's design to be optimized for a stricly
 * prioritized RTOS, but that would penalize all the non-preemptive and
 * non-prioritized systems we also support.
 */

extern TK_ENTRY(tk_netmain);        /* in netmain.c */
extern long     netmain_wakes;
extern TK_ENTRY(tk_keyboard);       /* in netmain.c */
extern long     keyboard_wakes;
extern TK_ENTRY(tk_nettick);        /* in netmain.c */
extern long     nettick_wakes;


#define TASK_ARRAY_SIZE 10

/* Build a local array to configure priorities and  */
struct prio_map {
   TK_ENTRY_PTR(entry);
   u_char priority;
} prio_tab[TASK_ARRAY_SIZE] =
{
    &(tk_netmain),  17
   ,&(tk_nettick),  18
/* (yaxon add) */
#ifdef TK_STDIN_DEVICE
   ,&(tk_keyboard), 19
#endif
};

INT8U app_priority = 8;    /* first/next priority to try for application */


int
TK_NEWTASK(struct inet_taskinfo * nettask)
{
   INT8U    error;
   INT8U    priority;
   OS_STK * stack;
   int      task_index;

   stack = (OS_STK*)npalloc(nettask->stacksize);
   if(!stack)
      panic("stack alloc");

again:   /* retry entry point if we don't get the ID we want */

   /* get priority/ID for this task. First see if it's on t of the
    * pre-assigned priorities in the prioty[] table; ifnot then give
    * it the next application priority.
    */
   priority = app_priority++;    /* default to app priority */
   for(task_index = 0; task_index < TASK_ARRAY_SIZE; task_index++)
   {
      if(prio_tab[task_index].entry == nettask->entry)
      {
         priority = prio_tab[task_index].priority;    /* assign priority for table */
         app_priority--;                     /* un-used app priority */
         break;
      }
   }

   error = OSTaskCreate(
      nettask->entry,
      NULL,
/*    stack + (nettask->stacksize/4),*/ /* note */
      stack + (nettask->stacksize/sizeof(OS_STK)),
      priority);

   if(error == OS_PRIO_EXIST)
      goto again;

   /* All other errors are fatal */
   if(error)
   {
      Printu_Net("Task create error %d on %s\n", nettask->name);
      return -1;
   }

   nettask->stackbase = (char*)stack;
   nettask->priority = priority;
   *nettask->tk_ptr = priority;  

   Printu_Net("Created %s task, prio: %d\n",
         (char *)nettask->name, priority);

   /* Remember netmain task Id/Priority for SignalPktDemux() */
   if(nettask->entry == tk_netmain)
      netmain_prio = priority;

   return 0;
}

/* rest of file is excluded unkless we're doing lock_net checking */
#ifdef LOCKNET_CHECKING

#include "q.h"       /* InterNiche queue defines */

/* locally define external items involved in checking locks */
extern queue rcvdq;
extern queue bigfreeq;
extern queue lilfreeq;
extern int iniche_net_ready;
extern queue mfreeq;


/* FUNCTION: LOCKNET_CHECK()
 *
 * If the passed queue is one of the sensitive ones then make sure
 * the related resource is locked.
 *
 * PARAM1: queue * q
 *
 * RETURNS: nothing, panics if test fails
 */

void
LOCKNET_CHECK(struct queue * q)
{

   /* Don't start checking until the net is up */
   if(!iniche_net_ready)
      return;

#ifdef INCLUDE_TCP
#ifndef MINI_TCP
   /* On uCOS/Nichestack/TCP builds, check the mbuf free queue is locked
    * by the NET_RESID semaphore. If it's not we panic().
    */
   if(q == &mfreeq)
   {
      /* A non-zero from OSSemAccept() means the semaphore was NOT locked */
      if(OSSemAccept((OS_EVENT *)net_task_sem_ptr) != 0)
      {
         panic("net lock");
      }
   }
#endif /* not MINI_TCP */
#endif /* INCLUDE_TCP */

   /* quick return if it's not one of the other sensitive queues */
   if((q != &rcvdq) &&
      (q != &bigfreeq) &&
      (q != &lilfreeq))
   {
      return;
   }

   /* Since the MPC860 build uses interrupt disabling to protect these
    * queues, we just need to check the Interrupt state. We use IntrDis()
    * to get currentinterrupt state. This disables ints, but we don't
    * care about that - if they were already disabled it will have no
    * effect, and if they were not then we are going to panic().
    */

   if(IntrDis())    /* Get current interupt state */
   {
      panic("lock");
   }
   return;
}

#endif /* LOCKNET_CHECKING */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -