czwartek, 23 marca 2023

STM32H7 - STM32H725VGTx - Freertos, LWIP

W tym poście chciałbym opisać konfigurację Ethernetu oraz stosu LWIP wraz z systemem operacyjnym FreeRtos.


Konfiguracja bloków pamięci oraz miejsc na deskryptory ethernetu udostępniona w poprzednim poście, zdaje się działać poprawnie dla wersji bez FreeRtos oraz bibliotek mbedTLS. Natomiast w przypadku ich zastosowania rozmieszczenie tych bloków musi być dużo bardziej przemyślane. Tak aby stos LWIP oraz potrzebne deskryptory miały wystarczającą ilość miejsca w pamięci.

Bardzo dobry opis konfiguracji dla różnych układów STM32H7 stosowanych w płytkach Nucleo i Discovery można znaleźć na githubie pod tym linkiem

STM32H725 Konfiguracja pamięci:


Pamięć dla buforów RX oraz TX jest umieszcza najczęściej w całości w pamięci D2 RAM. Z takimi rozwiązaniami można się najczęściej spotkać przy przykładowych aplikacjach. 

Wygenerowana mapa pamięci przez program CubeMx:

  1. MEMORY
  2. {
  3.   ITCMRAM (xrw)    : ORIGIN = 0x00000000,   LENGTH = 64K
  4.   DTCMRAM (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  5.   FLASH    (rx)    : ORIGIN = 0x08000000,   LENGTH = 1024K
  6.   RAM_D1  (xrw)    : ORIGIN = 0x24000000,   LENGTH = 320K
  7.   RAM_D2  (xrw)    : ORIGIN = 0x30000000,   LENGTH = 32K
  8.   RAM_D3  (xrw)    : ORIGIN = 0x38000000,   LENGTH = 16K
  9. }

W przypadku tego układu pamięć RAM_D2 jest za mała i należy jeden z buforów przenieść do RAM D1.

Konfiguracja CubeMx:

Konfiguracja CortexM7:


Konfiguracja ETH:


Biblioteka LWIP:

  1. /* Define to prevent recursive inclusion --------------------------------------*/
  2. #ifndef __LWIPOPTS__H__
  3. #define __LWIPOPTS__H__
  4.  
  5. #include "main.h"
  6.  
  7. /*-----------------------------------------------------------------------------*/
  8. /* Current version of LwIP supported by CubeMx: 2.1.2 -*/
  9. /*-----------------------------------------------------------------------------*/
  10.  
  11. /* Within 'USER CODE' section, code will be kept by default at each generation */
  12. /* USER CODE BEGIN 0 */
  13.  
  14. /* USER CODE END 0 */
  15.  
  16. #ifdef __cplusplus
  17.  extern "C" {
  18. #endif
  19.  
  20. /* STM32CubeMX Specific Parameters (not defined in opt.h) ---------------------*/
  21. /* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
  22. /*----- WITH_RTOS enabled (Since FREERTOS is set) -----*/
  23. #define WITH_RTOS 1
  24. /* Temporary workaround to avoid conflict on errno defined in STM32CubeIDE and lwip sys_arch.c errno */
  25. #undef LWIP_PROVIDE_ERRNO
  26. /*----- CHECKSUM_BY_HARDWARE enabled -----*/
  27. #define CHECKSUM_BY_HARDWARE 1
  28. /*-----------------------------------------------------------------------------*/
  29.  
  30. /* LwIP Stack Parameters (modified compared to initialization value in opt.h) -*/
  31. /* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
  32. /*----- Default value in ETH configuration GUI in CubeMx: 1524 -----*/
  33. #define ETH_RX_BUFFER_SIZE 1536
  34. /*----- Value in opt.h for MEM_ALIGNMENT: 1 -----*/
  35. #define MEM_ALIGNMENT 4
  36. /*----- Default Value for MEM_SIZE: 1600 ---*/
  37. #define MEM_SIZE 32232
  38. /*----- Default Value for H7 devices: 0x30044000 -----*/
  39. #define LWIP_RAM_HEAP_POINTER 0x30000200
  40. /*----- Default Value for MEMP_NUM_TCP_SEG: 16 ---*/
  41. #define MEMP_NUM_TCP_SEG 17
  42. /*----- Value supported for H7 devices: 1 -----*/
  43. #define LWIP_SUPPORT_CUSTOM_PBUF 1
  44. /*----- Value in opt.h for LWIP_ETHERNET: LWIP_ARP || PPPOE_SUPPORT -*/
  45. #define LWIP_ETHERNET 1
  46. /*----- Value in opt.h for LWIP_DNS_SECURE: (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -*/
  47. #define LWIP_DNS_SECURE 7
  48. /*----- Default Value for TCP_MSS: 536 ---*/
  49. #define TCP_MSS 1460
  50. /*----- Default Value for TCP_SND_BUF: 2920 ---*/
  51. #define TCP_SND_BUF 5840
  52. /*----- Default Value for TCP_SNDQUEUELOWAT: 9 ---*/
  53. #define TCP_SNDQUEUELOWAT 8
  54. /*----- Value in opt.h for LWIP_NETIF_LINK_CALLBACK: 0 -----*/
  55. #define LWIP_NETIF_LINK_CALLBACK 1
  56. /*----- Value in opt.h for TCPIP_THREAD_STACKSIZE: 0 -----*/
  57. #define TCPIP_THREAD_STACKSIZE 1024
  58. /*----- Value in opt.h for TCPIP_THREAD_PRIO: 1 -----*/
  59. #define TCPIP_THREAD_PRIO osPriorityNormal
  60. /*----- Value in opt.h for TCPIP_MBOX_SIZE: 0 -----*/
  61. #define TCPIP_MBOX_SIZE 6
  62. /*----- Value in opt.h for SLIPIF_THREAD_STACKSIZE: 0 -----*/
  63. #define SLIPIF_THREAD_STACKSIZE 1024
  64. /*----- Value in opt.h for SLIPIF_THREAD_PRIO: 1 -----*/
  65. #define SLIPIF_THREAD_PRIO 3
  66. /*----- Value in opt.h for DEFAULT_THREAD_STACKSIZE: 0 -----*/
  67. #define DEFAULT_THREAD_STACKSIZE 1024
  68. /*----- Value in opt.h for DEFAULT_THREAD_PRIO: 1 -----*/
  69. #define DEFAULT_THREAD_PRIO 3
  70. /*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
  71. #define DEFAULT_UDP_RECVMBOX_SIZE 6
  72. /*----- Value in opt.h for DEFAULT_TCP_RECVMBOX_SIZE: 0 -----*/
  73. #define DEFAULT_TCP_RECVMBOX_SIZE 6
  74. /*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
  75. #define DEFAULT_ACCEPTMBOX_SIZE 6
  76. /*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
  77. #define RECV_BUFSIZE_DEFAULT 2000000000
  78. /*----- Default Value for LWIP_HTTPD: 0 ---*/
  79. #define LWIP_HTTPD 1
  80. /*----- Value in opt.h for HTTPD_USE_CUSTOM_FSDATA: 0 -----*/
  81. #define HTTPD_USE_CUSTOM_FSDATA 1
  82. /*----- Default Value for LWIP_SNMP: 0 ---*/
  83. #define LWIP_SNMP 1
  84. /*----- Value in opt.h for MIB2_STATS: 0 or SNMP_LWIP_MIB2 -----*/
  85. #define MIB2_STATS 1
  86. /*----- Value in opt.h for CHECKSUM_GEN_IP: 1 -----*/
  87. #define CHECKSUM_GEN_IP 0
  88. /*----- Value in opt.h for CHECKSUM_GEN_UDP: 1 -----*/
  89. #define CHECKSUM_GEN_UDP 0
  90. /*----- Value in opt.h for CHECKSUM_GEN_TCP: 1 -----*/
  91. #define CHECKSUM_GEN_TCP 0
  92. /*----- Value in opt.h for CHECKSUM_GEN_ICMP6: 1 -----*/
  93. #define CHECKSUM_GEN_ICMP6 0
  94. /*----- Value in opt.h for CHECKSUM_CHECK_IP: 1 -----*/
  95. #define CHECKSUM_CHECK_IP 0
  96. /*----- Value in opt.h for CHECKSUM_CHECK_UDP: 1 -----*/
  97. #define CHECKSUM_CHECK_UDP 0
  98. /*----- Value in opt.h for CHECKSUM_CHECK_TCP: 1 -----*/
  99. #define CHECKSUM_CHECK_TCP 0
  100. /*----- Value in opt.h for CHECKSUM_CHECK_ICMP6: 1 -----*/
  101. #define CHECKSUM_CHECK_ICMP6 0
  102. /*-----------------------------------------------------------------------------*/
  103. /* USER CODE BEGIN 1 */
  104.  
  105. /* USER CODE END 1 */
  106.  
  107. #ifdef __cplusplus
  108. }
  109. #endif
  110. #endif /*__LWIPOPTS__H__ */

Po wygenerowaniu projektu należy się upewnić, że plik *.FLASH zawiera poprawne dane:

  1.   . = ALIGN(4);
  2.   .bss (NOLOAD) :
  3.   {
  4.     /* This is used by the startup in order to initialize the .bss section */
  5.     _sbss = .;         /* define a global symbol at bss start */
  6.     __bss_start__ = _sbss;
  7.     *(.bss)
  8.     *(.bss*)
  9.     *(COMMON)
  10.  
  11.     . = ALIGN(32);
  12.     *(.Rx_PoolSection)
  13.     . = ALIGN(4);
  14.     _ebss = .;         /* define a global symbol at bss end */
  15.     __bss_end__ = _ebss;
  16.   } >RAM_D1
  17.  
  18.     .lwip_sec (NOLOAD) :
  19.   {
  20.     . = ABSOLUTE(0x30000000);
  21.     *(.RxDecripSection)
  22.    
  23.     . = ABSOLUTE(0x30000100);
  24.     *(.TxDecripSection)
  25.    
  26.   } >RAM_D2

Do pliku ethernetif, należy dołożyć deklarację bufora RX:

  1. __attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];

Sprawdzam komunikację przez wysłanie komendy ping. 


Standardowy przykład czyli serwer TCP. Był on już wielokrotnie umieszczany na tym blogu. Więc poniżej będzie screen z przebiegu komunikacji:


Przykładowy projekt można pobrać z dysku Google lub z serwisu Github.