200906

来源:互联网 发布:数空车床编程视频教程 编辑:程序博客网 时间:2024/06/13 06:25

一、填空题(共30空,每空1.5分)共45分

注:已知定义如下:

typedef unsigned char   UINT8;

typedef unsigned short  UINT16;

typedef unsigned int    UINT32;

1、在全局变量、任务变量、局部变量、静态全局变量中,任何情况下都可以用于可重入函数的变量有  __                 _____  __                          

2试题说明:阅读下面C语言代码,请在空格内填上相应的内容;

#include <malloc.h>

auto char           gvChar;

volatile short     gvShort;

unsigned int        gvInt = 0x12345678;

const long          gvLong = 0x87654321;

unsigned char       * pChar = “Hello C”;

void main(void)

{

unsigned char array[10], *p;

p = malloc(10*sizeof(char));

       ... ... ...

}

试题要求:参考上述代码,如下变量分别存放在什么空间(如堆,栈,bss段,data段、代码段):

gvChar   __     _______     gvShort   _      __ _____

gvInt   _      ______  _    gvLong   _      ________

array   ___   __       _    p            _   ________

pChar    _      _______     pChar所指向的字符串存放在  _        _______

3、某存储器芯片的位宽为16比特,共有16根地址线(不考虑地址复用的情况),该存储器的容量为                      字节。

在内存中给某模块分配的临终遗言空间为0x90000~0x97FFF(内存按字节编址),则该模块的临终遗言空间大小为   _              _  字节。

4、某16位的硬件寄存器A的地址可以用REG_A_ADDR表示,该寄存器可读可写,请用一个C语句在不影响其他比特的情况下将A寄存器的bit2和bit1(已知bit0为LSB)置1:

_________                                           ____________

再用一个C语句完成将A寄存器的bit2和bit1清零的操作(同样要求不影响其他比特):_________                                             ____________

另有一个16位的硬件寄存器B的地址用REG_B_ADR表示,该寄存器是一个告警状态寄存器,每个比特都表示一个特定的硬件异常状态,1表示有相应告警,0表示没有告警,因此读该寄存器的值就可以得到硬件异常的告警状态。此寄存器的每比特写1可以清除相应位的告警状态(写1清0),写0无效。请用一个C语句在不影响其他比特的情况下将B寄存器的bit1告警位清零:

__________                                             ____________

5试题说明:有如下结构定义:

struct tagAbc

{                                                                                     

    char  cStr1;

    short sStr2;

    char  cStr3;

    long  lStr4;

}*pstrAbc;            

 

pAbc = 0x300000; 

试题要求:请计算并填空(注:typedef unsigned long  ULONG)

pstrAbc + 0x100            =               _____

(ULONG) pstrAbc + 0x100     =               _____

(ULONG *) pstrAbc + 0x100   =                ____

(char *) pstrAbc + 0x100    =               _____

6、有如下程序段:

#define MAX(a,b)   ((a)>(b)?(a):(b))

...

   X = 5;

   Y = 8;

   Z = MAX(x++,y++);

请填写该程序运行后X、Y、Z的值:

X =    __   ___

Y =    __   ___

Z =    __    __

7、以太网通信中,如果通信双方中一端的工作模式(全双工/半双工)固定,另一端设置为自适应模式,那么不管固定一端是全双工还是半双工,自适应那端自适应出来的工作模式为     

                               

8、在32位嵌入式操作系统中,定义UINT32* g_pulStatus = 0x5a6b7c8d,请问:

在大模式(big-endian)时:     *(UINT8*)g_pulStatus         =           

*(UINT16 *)g_pulStatus   =            

在小模式(little-endian)时:  *(UINT8 *)g_pulStatus    =           

*(UINT16 *)g_pulStatus   =            

9、为了保证cache一致性,在必要的时候可以采用人工cache操作来保证数据的及时刷新。如在CPU“读”方向上,可以先使用                    (请填写API函数名,简要描述也可以)然后再读来保证cache和内存的数据一致性,在CPU“写”方向上,可以先写数据然后使用                     (请填写API函数名,简要描述也可以)保证cache和内存的数据一致性。

10、有如下定义:

union  unFlag

{

struct

{

unsigned char  ucMode ;

};

unsigned short usVal;

}unMyFlag;

那么unMyFlag占用了  __     ___位(bit)的内存大小

 

二、改错题(共5题,每错1~2分)共34分

1试题说明:硬件驱动编程中,通常要等待硬件寄存器的状态翻转表明某项硬件功能已完成,才能进行后续的操作,请找出该段程序的错误之处。

#define  BSP_READ_REG(addr)  (*((UINT16 *)((UINT32)(addr))))

 

。。。。

    while ((0 != ((BSP_ READ _REG(BSP_STATE_REG_ADRS)) & 0x01)))

    {

         /*延迟1 Us*/

。。。 。。。

}

。。。。

试题要求:请找出该段程序的1~2处错误或隐患(不考虑代码风格问题),不要求修正。

 

2、试题说明:如下程序段,函数NETDRV_PacketRecv主要完成数据包的接收处理,每次可以接收处理一个标准的MAC包。

试题要求:请找出该段程序的2~4处错误或隐患(不考虑代码风格问题),不要求修正。

01  UINT32 NETDRV_PacketRecv(UINT8 *pucBuf,UINT32 ulLen)

02  {

03     UINT32 ulReturn = NETDRV_ERROR; /*注:NETDRV_ERROR是已定义的正确宏 */

04    

05     if (pucBuf = NULL)

06     {

07         return NETDRV_ERROR;

08     }

09    

10     /* 对接收的数据包进行校验,此函数已经在前面进行了声明 */

11     ulReturn = NETDRV_VerifyPacket(UINT8 *pucBuf,UINT32 ulLen);

12    

13     /* 接收包校验错误时丢弃包 */

14     if (NETDRV_ERROR == ulReturn)

15     {

16         printf("Verify packet error\n");      

17        

18         /* 丢包处理 */

19         ... ...

20        

21         free(pucBuf);

22     }

23    

24     /* 如果使能了接收包环回转发功能,则进行环回转发处理

25        注:此处宏和全局变量gulLoopFwdEnableFlag已经正确定义和初始化 */

26     if (NETDRV_LOOPFWD_ENABLE == gulLoopFwdEnableFlag)

27     { 

28        ulReturn = NETDRV_LoopFwdPacket(UINT8 *pucBuf,UINT32 ulLen);

29        return (ulReturn);

30     }

31     else

32     {

33        /* 进行接收包处理,此函数已经在前面进行了声明 */

34        ulReturn = NETDRV_ProcessPacket(UINT8 *pucBuf,UINT32 ulLen);

35        return (ulReturn);

36     }

37  }

38 

39  /* 此函数完成环回转发功能,即把收到的包调换源/目的地址后发送回去,

40     或者按照设置的目的地址进行转发 */

41  UINT32 NETDRV_LoopFwdPacket(UINT8 *pucBuf,UINT32 ulLen)

42  {

43     /* 如果是环回处理,则调换MAC地址并发送回去 */

44     if (... ...)

45     {

46        ... ...

47     }

48     else /*转发处理,填写目的MAC为已设置的转发MAC地址并发送*/

49     {

50        ... ...

51     }

52    

53     /* 处理完后释放内存 */

54     if (... ...)

55     {

56         free(pucBuf);          

57     }     

58       

59     return NETDRV_OK;

60  }

61

62  UINT32 NETDRV_VerifyPacket(UINT8 *pucBuf,UINT32 ulLen)

63  {

64     /* 如下代码完成接收包的校验判断功能 */

65     ... ...

66       

67     return NETDRV_OK;

68  }

69

70  UINT32 NETDRV_ProcessPacket(UINT8 *pucBuf,UINT32 ulLen)

71  {

72     /* 如下代码完成接收包的解析,并根据不同的解析类型把

73        数据包拷贝一份送给上层应用软件 */

74     ... ...

75       

76     return NETDRV_OK;

77  }

 

3、试题说明:如下程序段,挂接一个定时器中断,驱动sample任务运行,代码中用到的函数原型参考如下:

taskSpawn ( name, priority, options, stacksize, main, arg1, ... arg10 );

STATUS intConnect

(

    VOIDFUNCPTR *vector, /* to attach */

    VOIDFUNCPTR routine, /* to be called */

    int parameter   /* for the routine */

)

   

SEM_ID semMCreate

(

    int options          /* mutex semaphore options */

)

试题要求:请找出该段程序的2~3处错误或隐患(不考虑代码风格问题),不要求修正。

01  /*This example shows the use of semaphores for task synchronization*/

02  #include <vxWorks.h>

03  #include <semLib.h>

04  #include <arch/arch/ivarch.h>

05 

06  SEM_ID syncSem; /* ID of sync semaphore */

07  init (int someIntNum)

08  {

09      /* connect interrupt service routine */

10      intConnect(INUM_TO_IVEC(someIntNum), eventInterruptSvcRout, 0);

11 

12      /* create semaphore */

13      syncSem = semMCreate (SEM_Q_FIFO, SEM_EMPTY);

14 

15      /* spawn task used for synchronization. */

16      taskSpawn ("sample", 100, VX_USER_MODE, 200, task1,

17                                                0,0,0,0,0,0,0,0,0,0);

18  }

19 

20  task1 (void)

21  {

22      unsigned long testStat[400];

23      do

24      {

25          semTake (syncSem, WAIT_FOREVER); /*wait for event to occur*/

26          printf ("task 1 got the semaphore\n");

27

28          /* process event */

29          ... ...

30      }while(1)

31  }

32 

33  eventInterruptSvcRout (void)

34  {

35      printf ("Give the semaphore\n");

36      semGive (syncSem); /* let task 1 process event */

37  }

 

4、试题说明:请分析如下代码,找出其中的错误之处。

01  unsigned char size = 100;

02  while (size-- >= 0)

03  {

04      int * p ;

05      unsigned char * q = NULL;

06  

07      q = malloc(sizeof(char));

08      *p = 100 ;

09      *q = size;

10      if(*p != *q)

11      {

12          continue;

13      }

14      else

15      {

16           printf("\nwhen size is :%d,*p ==*q\n",size);

17      }

18  }

试题要求:请找出该段程序的3~5处错误或隐患(不考虑代码风格问题),不要求修正。

 

5、试题说明:在某单板上起一个任务不断地检测寄存器REG_ADDR中REG_BUSY_BITMASK位是否处于忙状态,根据忙闲状态进行做不同的处理,同时更新全局变量g_ulRegBusy,其它任务也会读写该全局变量,进行相应处理。函数原型参考:taskSpawn ( name, priority, options, stacksize, main, arg1, ... arg10 );

试题要求:请找出该段程序的6~9处错误或隐患(不考虑代码风格问题),不要求修正。

01  typedef unsigned char       UINT8;

02  typedef unsigned short      UINT16;

03  typedef unsigned int         UINT32;

04  #define REG_ADDR                  0xff001000

05  #define REG_BUSY_BITMASK          0x00001000

06  #define FALSE                  0

07  #define TRUE                   1

08  UINT32  g_ulRegBusy = TRUE;

09 

10  void test()

11  {

12      UINT32 *ptr ;

13      UINT8  aucTemp[1000];

14      UINT8  ucCounter;

15      UINT16 usCounter = 0;

16 

17      ptr = (UINT32 *)REG_ADDR;

18      while ( 1 )

19      { 

20          /*硬件首先做一段延时处理*/

21          ucCounter = 200;

22          while ((ucCounter--) >= 0 )

23          {

24              /*空处理*/;

25          }

26 

27          while (0 !=((*ptr)&REG_BUSY_BITMASK) )

28          {

29              g_ulRegBusy = TRUE;

30          }

31 

32          /* 取出寄存器空间的值并存入数组中 */

33          aucTemp[++usCounter] = (*ptr)& 0xff;

34 

35          if (usCounter > 1000 )

36          {

37              /*把aucTemp数组中的数据发送出去*/

38              ... ... ...

39

40              usCounter = 0;

41          }

42 

43          g_ulRegBusy = FALSE;

44      }

45  }   

46 

47  void testInit()

48  {

49      taskSpawn("tTest", 20, 0, 1000, (FUNCPTR)test,0,0,0,0,0,0,0,0,0,0);

50  }

 

三、优化题(共1 题,每题6分)共6分

1试题要求:如下代码的运行效率较低(不考虑编译器的自动优化),需要进行优化。请分析一下代码效率低的可能原因,并给出优化后的代码或者修改思路。

funx()

{

    ...

 

    /* 注:ALM_LCBITEM_STRU是已经定义好的告警结构 */

    for (ulLoop = 0; ulLoop < (sizeof(pstrAlarms->pLCBItem)/ sizeof(ALM_LCBITEM_STRU)); ulLoop ++)

{

        /*注:pstrAlarms为全局结构指针*/

        pstrAlarms -> pLCBItem[ulLoop].ulPreviousIndex  = ulLoop - 1;

        pstrAlarms -> pLCBItem[ulLoop].ulNextIndex      = ulLoop + 1;

        pstrAlarms -> pLCBItem[ulLoop].bIdleFlag        = VOS_TRUE;

    }

    ...

}

 

四、编程题(共1 题,每题15分)共15分

1试题说明:栈(Stack)结构是计算机语言实现中的一种重要数据结构。对于任意栈,进行插入和删除操作的一端称为栈顶(Stack Top),而另一端称为栈底(Stack Bottom)。栈的基本操作包括:创建栈(NewStack)、 判断栈是否为空(IsStackEmpty)、判断栈是否已满(IsStackFull)、获取栈顶数据(GetStackTop)、压栈/入栈(PushStack)、弹栈/出栈(PopStack)。

当设计栈的存储结构时,可以采取多种方式。此处采用链式存储结构实现一个整数栈操作,栈结构定义如下:

typedef struct List

{

int data;              // 栈数据

struct List* next;   // 上次入栈的数据地址

}List;

 

typedef struct Stack

{

List* pTop;      // 当前栈顶指针

}Stack;

 

现给出一个函数示例供参考:

(1)创建栈: 函数定义为 Stack* NewStack(void)

Stack* NewStack()

{

return (Stack*)calloc(1,sizeof(Stack));

}

 

试题要求:请编写栈的基本操作函数,具体函数定义如下:

判断栈是否为空:函数定义为 int IsStackEmpty(Stack* pstrStack)

                函数功能描述:判断pstrStack指向的堆栈是否为空

已知如下宏定义:

#define FALSE       0

#define TRUE        1

压栈/入栈:     函数定义为 void PushStack(Stack* pstrStack, int iTheData)

                函数功能描述:将数据iTheData压入pstrStack指向的堆

原创粉丝点击