天天看點

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

通過網絡連接配接,極大地提高了PC與DSP之間的資料傳輸速率(相對于USB連接配接而言)。

在記錄06(點此跳轉)中給出了一個簡單的測試示例,但是那隻能傳輸很少的資料。

如果将資料(buffer)尺寸設定為一個較大的值(如2048等)就會出現timeout的錯誤。

在這種情形下更不用說傳輸一個大檔案了,是以我們需要尋找一種解決方案。

本文正是為此而展開。

核心思想是:

1.在PC端,打開檔案,分塊讀取資料到buffer(比如每一塊大小為2KB等)

2.在PC端,每次讀取資料到bufer後将buffer資料發送到socket

3.資料經過網絡連接配接傳送到DSP端

4.DSP端不斷處理(暫存)ETH0接口收到的資料并發送響應

5.在PC端,每次發送一個資料塊之後等待來自DSP的響應,之後才發送下一塊

6.在PC端,不斷發送資料塊,直到整個檔案資料發送完畢,最後關閉連接配接

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

經過測試發現,将檔案分成2048B(=2KB)大小的塊進行發送是一個比較好的選擇。

每次發送2KB被DSP收到後立即被處理,然後DSP發回響應,表示已經收到這個資料。

PC端收到應答後就知道剛才發給DSP的資料已經被接收了,可以發送下一塊資料。

為了讓測試更加嚴謹,我們找來幾個大小不同的檔案,具體測試過程截圖如下

一幅普通尺寸(1000*1000以下)的圖檔,30KB左右,處理時間不到1秒

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

一幅稍大尺寸(1920*1080)的圖檔,不到1MB,處理時間1秒左右

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

測試一個較大的檔案,44.13MB大小,處理用時25秒左右

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

測試一個更大的檔案,191.82MB大小,處理用時103秒左右

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

最後測試傳輸一張大尺寸照片,4k*3k分辨率,5.28MB大小,用時約3秒

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

在CCS調試輸出視窗的截圖如下

CCS+C6678LE開發記錄09:以太網接口測試續(大塊資料傳輸)

對比一下發現,5次測試中都能正确收到全部資料。

這個測試表明,我們的流程設計是合理的。

最後将PC端發送資料以及DSP端接收資料的代碼貼上來以供參考。

  1. // PC端:發送資料

  2. // fengyhack @ 20150203

  3. #include <stdio.h>

  4. #include <time.h>

  5. #include <stdlib.h>

  6. #include "sockets.h"

  7. #pragma comment(lib,"ws2_32.lib")

  8. #pragma warning(disable:4996)

  9. const char *TARGET = "169.254.11.123";

  10. #define PORT 7

  11. #define TIMEOUT 1

  12. int main(void)

  13. {

  14. system("title Ethernet0 Transfer Test");

  15. system("color 2e");

  16. printf("Remote ( %s : %d )\n", TARGET, PORT);

  17. char fileName[256] = { 0 };

  18. printf("Input filename:");

  19. scanf("%s", fileName);

  20. FILE* fp = fopen(fileName, "rb");

  21. if (fp == NULL)

  22. {

  23. printf("Failed to open file.\n");

  24. goto leave;

  25. }

  26. long fsize = 0;

  27. fseek(fp, 0L, SEEK_END);

  28. fsize = ftell(fp);

  29. double kilo = 1.0*fsize / 1024.0;

  30. if (kilo >= 1024.0)

  31. {

  32. printf("File size: %.2fMB\n", kilo/1024.0);

  33. }

  34. else

  35. {

  36. printf("File size: %.2fKB\n", kilo);

  37. }

  38. const int unit = 2048;

  39. int loop = fsize / unit;

  40. int residue = fsize - loop*unit;

  41. char* data = (char*)malloc(unit + 1);

  42. struct in_addr dst;

  43. inet_pton(AF_INET, TARGET, &dst);

  44. unsigned short port = PORT;

  45. socketsStartup();

  46. SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);

  47. if (s < 0)

  48. {

  49. printf("failed socket (%d)\n", getError());

  50. goto leave;

  51. }

  52. struct sockaddr_in sin;

  53. sin.sin_family = AF_INET;

  54. sin.sin_addr.s_addr = 0;

  55. int status = 0;

  56. status = bind(s, (const struct sockaddr *) &sin, sizeof(sin));

  57. if (status< 0)

  58. {

  59. printf(" failed bind (%d)\n", getError());

  60. goto leave;

  61. }

  62. sin.sin_addr = dst;

  63. sin.sin_port = htons(port);

  64. struct timeval timeout;

  65. timeout.tv_sec = TIMEOUT;

  66. timeout.tv_usec = 0;

  67. fd_set fds;

  68. int nr;

  69. char tmp[8] = { 0 };

  70. printf("<Start sending data>\n");

  71. time_t time_start = time(0);

  72. for (int i = 1; i <= loop; ++i)

  73. {

  74. fread(data, unit, 1, fp);

  75. data[unit] = 0;

  76. status = sendto(s, data, strlen(data), 0, (const struct sockaddr *)&sin, sizeof(sin));

  77. if (status< 0)

  78. {

  79. printf("send failed (%d)\n", getError());

  80. goto leave;

  81. }

  82. FD_ZERO(&fds);

  83. FD_SET(s, &fds);

  84. select(s + 1, &fds, NULL, NULL, &timeout);

  85. nr = recv(s, tmp, 8, 0);

  86. if (i % 64 == 0)

  87. {

  88. printf(".");

  89. if (i % 4096 == 0) printf(" (%4.1f%%)\n", 100.0*i / loop);

  90. }

  91. }

  92. if (residue > 0)

  93. {

  94. fread(data, residue, 1, fp);

  95. data[residue] = 0;

  96. status = sendto(s, data, strlen(data), 0, (const struct sockaddr *)&sin, sizeof(sin));

  97. if ( status< 0)

  98. {

  99. printf("send failed (%d)\n", getError());

  100. goto leave;

  101. }

  102. FD_ZERO(&fds);

  103. FD_SET(s, &fds);

  104. select(s + 1, &fds, NULL, NULL, &timeout);

  105. nr = recv(s, tmp, 8, 0);

  106. printf(" (100%%)\n");

  107. }

  108. fclose(fp);

  109. printf("Finished transfer. Time = %d seconds\n", (int)(time(0) - time_start));

  110. leave:

  111. if(s>=0) closesocket(s);

  112. if(data) free(data);

  113. socketsShutdown();

  114. system("pause");

  115. return 0;

  116. }

DSP端接收資料的代碼與本系列的06X篇(點此跳轉)基本一緻,

唯一改動的地方是在一個函數中,具體代碼如下

  1. int udpTransferTask( SOCKET s, UINT32 unused )

  2. {

  3. printf("TASK execution %d\n",++task_counter);

  4. struct timeval tv;

  5. tv.tv_sec = 1;

  6. tv.tv_usec = 0;

  7. setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv));

  8. setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));

  9. struct sockaddr_in sin1;

  10. int sz=sizeof(sin1);

  11. int hlen=strlen(reply);

  12. int nr,total=0;

  13. HANDLE hBuffer;

  14. unsigned char* pBuf;

  15. while(1)

  16. {

  17. nr=recvncfrom( s, (void**)&pBuf, 0, (PSA)&sin1, &sz, &hBuffer );

  18. if(nr<=0) break;

  19. total+=nr;

  20. sendto( s, reply, hlen, 0, (PSA)&sin1, sz );

  21. recvncfree( hBuffer );

  22. }

  23. double kilo_bytes=1.0*total/1024.0;

  24. if(kilo_bytes>=1024.0)

  25. {

  26. printf("Total size of data received: %.2fMB\n",kilo_bytes/1024.0);

  27. }

  28. else

  29. {

  30. printf("Total size of data received: %.2fKB\n",kilo_bytes);

  31. }

  32. return 1;

  33. }

本文原創,博文位址

http://blog.csdn.net/fengyhack/article/details/43446989

繼續閱讀