ucos學習筆記02--內存複製的操作

 //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. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章