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

📄 debugknl.cpp

📁 一个嵌入式系统的C代码
💻 CPP
字号:
//*************************************************************************//  MODULE : Kernel - The RCOS message switching centre.		  *//  AUTHOR : Ron Chernich                                                 *//  PURPOSE: Supply a single point which receives and dispatches messages *//	     and runs applications when it has nothing else to do..	  *//  HISTORY:                                                              *//   31-MAR-93	First (MSC/C++ 7.00) version				  *//   04-APR-93	Port concept with pointers to function members introduced *//   20-APR-94  Memory leak in Run and Destructor plugged (10 byte MSG)   *//*************************************************************************#include "kernel.hpp"#include "exec.hpp"#define DEBUG#ifdef DEBUG# include <stdio.h>  static FILE *flog;#endif//////////////////////////////////////////////////////////////////////////// Constructor for Port class must set its ID and register with// the Kernel..//port::port (UINT16 id, UINT16 cls, Knl *pK){  uID = id;  pTx = pK;  MSG Msg(uID, KM_Register, cls, (void*)(this));  pTx->SendMsg(ID_Kernel, &Msg);}///////////////////////// Port routine to simplify sending error messages to its manager.// <nErr> is a device specific code (positive) which can be used by// "support" to trace reason for failure.  <bFatal> is a flag for// degree - set if Fatal.//void port::DevError (INT16 nErr, BOOL bFatal){  MSG Msg(uID, KM_DevError, ((bFatal) ? (0x8000 | nErr) : nErr));  pTx->SendMsg(ID_Kernel, &Msg);}//////////////////////////////////////////////////////////////////////////// Since the class exports its <run> member, all of Kernel is considered// critical and must be protected in the time honored way.//Knl::Knl (void){  inCrit = 0;  pTask = new Exec(this);# ifdef DEBUG  flog = fopen("debug.log", "wt");# endif}////////////// Close down the operating system - free up any memory occupied by// structures in the linked lists that the list class won't be able// to release, and close down the Exec Instance.//Knl::~Knl (void){  PQMSG pM;  while (pM = (PQMSG)Msg.DblGetHead()) {    if (pM->pMsg->pBody)      delete [] pM->pMsg->pBody;    if (pM->pMsg)      delete pM->pMsg;    Msg.DblDelete();  }  delete pTask;# ifdef DEBUG  fclose(flog);# endif}//////////////////// Scan the list of ports known to us for one matching the passed ID// RETURNS: pointer to structure, or NULL if not in list//PDEVLST Knl::GetPort (UINT16 uPortID){  PDEVLST pD = (PDEVLST)Dev.DblGetHead();  while (pD)    if (pD->uID == uPortID)      break;    else      pD = (PDEVLST)Dev.DblGetNext();  return pD;}/////////////////////// Dispatch the message at the head of the queue: if it's a KERNEL service// request, dispatch direct; if it's for a device which does not exist,// disgard it; if the destination is legal and its status is "Ready", invoke// the port's receive member. If the port is Inhibited or Busy, call our own// "Post" member, effectively putting the message to the back of the queue.// If the destination is a process which is sleeping on this message, place// the message in the process PCB and remove the block on the process.// If there are no messages, see if we have a ready process and execute its// next p-code.	Failing all the above, just exit .. something will happen// eventually.//// Late breaking thought: on the above logic, if we have a message for a port// which is continually busy, <Run> will spend ALL its time re-posting the// message and no p-codes will ever get executed! So, in this event we must// call the dispatcher as well as sending the message to the back of the Q.//							 arcy .. 20-APR-94//// RETURNS: TRUE  .. Single-step procedure (if active) can continue//	    FALSE .. A p-code has been executed; deactivte s-step.//BOOL Knl::Run (void){  BOOL bStep = TRUE;  if (inCrit == 0) {    --inCrit;    PQMSG pM = (PQMSG)Msg.DblGetHead();    if (pM == NULL)      bStep = pTask->Dispatch();    else {      if (pM->wDest == ID_Kernel)	Service(pM->pMsg);      else {	PDEVLST pD = GetPort(pM->wDest);	if (pD) {#ifdef DEBUG  fprintf(flog, "message at %04X:%04X\n", _FP_SEG(pM->pMsg), _FP_OFF(pM->pMsg));  fprintf(flog, "   %04X, %04X, %04X,", pM->pMsg->wSender, pM->pMsg->wMsgType, pM->pMsg->wParam);  fprintf(flog, " %04X:%04X\n\n", _FP_SEG(pM->pMsg->pBody), _FP_OFF(pM->pMsg->pBody));  fflush(flog);#endif	  if (pD->uStatus == STAT_Ready)	    pD->pP->RxPort(pM->pMsg);	  else {	    PostMsg(pD->uID, pM->pMsg);	    bStep = pTask->Dispatch();	  }	}      }      pM = (PQMSG)Msg.DblGetHead();      if (pM->pMsg->pBody)	delete [] pM->pMsg->pBody;      if (pM->pMsg)        delete pM->pMsg;      Msg.DblDelete();    }    ++inCrit;  }  return bStep;}////////////////// This function acts like a direct call to the destination device,// effectively allowing any device to make a synchronous call to// another driver.  If the destination don't exist, nothing happens.//void Knl::SendMsg (UINT16 dest, PMSG pMsg){  if (dest == ID_Kernel)    Service(pMsg);  else {    PDEVLST pD = GetPort(dest);    if (pD) {      pMsg->wMsgType |= MM_Sync;      pD->pP->RxPort(pMsg);    }  }}///////////////// This function effects an asynchronous call to the destination device or// process.  If the destination is a process, we ask Exec to attach it to// the message input queue for the process (causing it to become un-blocked// if it had previously blocked on a PostMsg).	All other messages are added// to our message FIFO queue.  Some checking for destination validity must// be done somewhere, but not here - we can leave that until this message// reaches the head and is about to be dispatched.  Finally, if the sender// is a process, we get Exec to block the process until a reply for this// message returns.//void Knl::PostMsg (UINT16 uDest, PMSG pMsg){  if (uDest < MAX_PROC)    pTask->PostReply(uDest, pMsg);  else {    QMSG temp;    temp.wDest = uDest;    temp.pMsg = new MSG(*pMsg);    Msg.DblAppend((void*)&temp, sizeof(QMSG));    if (pMsg->wSender < MAX_PROC)      pTask->Block();  }}//////////////////// allows a port to "peek" at it's next message without actually// retrieving it from the queue..//void Knl::PeekMsg (UINT16 uDest, PMSG *p){  PQMSG pM = (PQMSG)Msg.DblGetHead();  while (pM && (pM->wDest != uDest))    pM = (PQMSG)Msg.DblGetNext();  *p = (pM) ? pM->pMsg : NULL;}///////////////////// Process a Kernel services message -//   Adds new ports to the list provide that the ID is unique//   Allows a port to change it's status//   Displays Device errors/failures on console (unless it's failed!)//void Knl::Service (PMSG pM){  PDEVLST pD = GetPort(pM->wSender);  static char *szEmsg = "\33[s\33[x;yH\33[K  Device 0x%X %s: 0x%x\33[u\a";  switch (pM->wMsgType) {    case KM_SetStatus:      if (pD)	pD->uStatus = pM->wParam;      break;    case KM_DevError:      if (pD) {	if ((INT16)pM->wParam < 0)	  pD->uStatus = STAT_Inhibit;	if (pD->uID != ID_TTY0) {	  char *pstr = (char*)malloc(strlen(szEmsg)+16);	  if (pstr) {	    sprintf(pstr, szEmsg, pD->uID,	     (((INT16)pM->wParam < 0) ? "FAILED":"ERROR"), pM->wParam&0x7fff);	    MSG Msg(ID_Kernel, KM_WriteBlk, strlen(pstr), (void*)pstr);	    *(pstr + 5) = *(pstr + 7) = '\0';	    SendMsg(ID_TTY0, &Msg);	  }	}      }      break;    case KM_Register:      if (pD == NULL) {	pD = new DEVLST;	if (pD) {	  pD->uAssign = NO_PROC;	  pD->uID = pM->wSender;	  pD->uClass = pM->wParam;	  pD->uStatus = STAT_Ready;	  pD->pP = (port*)(pM->pBody);	  Dev.DblAppend((void*)pD, sizeof(DEVLST));	  delete pD;	}      }      break;    case KM_CheckOut:      if (pD)	Dev.DblDelete();      break;    case KM_Open: {	PDEVLST pDC = (PDEVLST)Dev.DblGetHead();	while (pDC) {	  if ((pDC->uClass == pM->wParam) && (pDC->uAssign == NO_PROC)) {	    SendMsg(pDC->uID, pM);	    pDC->uAssign = pM->wSender;	    pM->wParam = pDC->uID;	    return;	  }	  pDC = (PDEVLST)Dev.DblGetNext();	}	pM->wParam = ID_NULL;      }      break;    case KM_Close: {	PDEVLST pDC = (PDEVLST)Dev.DblGetHead();	while (pDC) {	  if (pDC->uID == pM->wParam) {	    SendMsg(pDC->uID, pM);	    pDC->uAssign = NO_PROC;	    pDC->uStatus = STAT_Ready;	    pM->wParam = ID_NULL;	    return;	  }	  pDC = (PDEVLST)Dev.DblGetNext();	}	pM->wParam = 0;      }      break;    case ANI_GET_QUS:      pTask->GetQcom(pM->wParam, (PMSG_ANIQ)pM->pBody);      break;    case ANI_GET_PCB:      pTask->GetPcom((PMSG_ANIP)pM->pBody);      break;  }}////////////////////////////////// EOF /////////////////////////////////////

⌨️ 快捷键说明

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