ucos学习笔记02--内存复制的操作

来源:互联网 发布:开心网域名被抢注案例 编辑:程序博客网 时间:2024/05/22 13:31

 //ucos笔记--关于数据复制

//任务之间的通信的两个结构体之间数据复制问题

  1. //两个结构体的原型如下:
  2. typedef struct {
  3.     INT16U  OSCnt;                          /* Semaphore count                                         */
  4.     INT8U   OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */
  5.     INT8U   OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
  6. } OS_SEM_DATA;
  7. typedef struct {
  8.     INT8U   OSEventType;                   /* Type of event control block (see OS_EVENT_TYPE_???)      */
  9.     INT8U   OSEventGrp;                    /* Group corresponding to tasks waiting for event to occur  */
  10.     INT16U  OSEventCnt;                    /* Semaphore Count (not used if other EVENT type)           */
  11.     void   *OSEventPtr;                    /* Pointer to message or queue structure                    */
  12.     INT8U   OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur                 */
  13. } OS_EVENT;
  14. /*
  15. OS_EVENT是事件控制块原型,OS_SEM_DATA是信号量在OSSemQuery里面用到的,用来获取事件控制块中有用的信息。在OSSemQuery函数里面,用了一个循环(新版本的ucos把这个循环改为了一条条赋值语句,因为循环次数最大是8次,为了减少循环的额外开销......)。但是这里其实是可以用强制类型转换简单一个赋值语句就可以搞定的。
  16. */
  17. typedef struct {
  18.     OS_SEM_DATA OSEVENTSemdata;
  19.     INT8U   OSEventType;                   /* Type of event control block (see OS_EVENT_TYPE_???)      */
  20.     void   *OSEventPtr;                    /* Pointer to message or queue structure                    */
  21. } OS_EVENT;
  22. //结构体无法直接做赋值操作,可以使用一个内存copy函数,返回目的地址
  23. //=========================================
  24. //考虑到了内存重叠的问题,不过在正常使用的时候这样的问题应该不会存在
  25. void *memcopy(void * pvfrom, void *pvto, size_t size)//源码见下面
  26. //如果那个变量不是放在结构体头的话,就需要知道这个成员的偏移地址
  27. //用宏算出结构体成员的偏移地址
  28. #define  member_offset(struct_t, member)        (int)(&((struct_t *)(0)->member))
  29. /*
  30. 做内存复制,实现对OS_SEM_DATA的获取,故ucos里的函数INT8U  OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)可以这样实现:
  31. */
  32. INT8U  OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *pdata)
  33. {
  34.     memcopy(pdata, pevent, sizeof(OS_EVENT));
  35. }
  36. /*
  37. 也许效率没直接读取、赋值来的快,但是程序会比较简洁。
  38. 并且内存复制这一部分可以用内嵌汇编实现,效率问题可根据MCU特性做取舍:单纯的读写内存,某些mcu比较高效。
  39. */
  40. //==========================================
  41. //附内存复制函数的测试程序代码
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #define  member_offset(struct_t, member) (int)(&(((struct_t *)(0))->member))
  45. typedef unsigned char byte;
  46. typedef struct st1
  47. {
  48.     byte a;
  49.     int b;
  50.     float c;
  51. }st_1;
  52. typedef struct st2
  53. {
  54.     struct st1 st1_v;
  55.     int x;
  56. }st_2;
  57. //================================== 
  58. void *memcopy(void *pvfrom, void *pvto, int size);
  59. int main(void)
  60. {
  61.     struct st1 *p_st1 = (struct st1 *)malloc(sizeof(st_1));
  62.     struct st2 st2_v1={{11,12,1.2345},13};
  63.     struct st1 *pt = p_st1;
  64.     memcopy((void *)(&st2_v1), (void *)pt, sizeof(st_1));
  65.     printf("%d/n", p_st1->a);
  66.     printf("%d/n", p_st1->b);
  67.     printf("%f/n", p_st1->c);
  68. }
  69. void *memcopy(void * pvfrom, void *pvto, int size)
  70. {
  71.     byte *ptfrom = (byte *)pvfrom;
  72.     byte *ptto = (byte *)pvto;
  73.     
  74.     printf("size is %d/n",size);
  75.     #if 1
  76.     while(size-->0)
  77.     {
  78.         *(ptto++) = *(ptfrom++);        
  79.     }
  80.     #else//#if 1 
  81.     //====在网上看到的,说这里需要考虑内存重叠问题,不过看不出什么时候会这样,除非故意的,比如插入排序? 
  82.     if((ptfrom<ptto) && ((ptfrom+size-1)>ptto))
  83.     {
  84.         for(int i=size-1; i>=0;i--)
  85.         {
  86.             *(ptto+i) = *(ptfrom+i);
  87.         }
  88.     }
  89.     else
  90.     {
  91.         for(int i=0; i<size;i++)
  92.         {
  93.             *(ptto+i) = *(ptfrom+i);
  94.         }
  95.     }
  96.     #endif//#if 1
  97.     return ptto;
  98. }