piątek, 24 lutego 2023

STM32H7 - STM32H725VGTx - Konfiguracja ETH, Serwer TCP.

W tym poście chciałbym opisać podstawową konfigurację Ethernet'u na płycie z układem STM32H725VGTx.


Podłączenie:


W projekcie wykorzystuje układ LAN8720. Jego sterowniki są możliwe do pobrania bezpośrednio z programu CubeMx. 


W sterowniku dostępnym z poziomu CubeMx brakuje zdefiniowana dwóch pinów PHY_RXER oraz PHY_RESET. Oba piny są domyślnie podciągnięte pod VCC. 

Pin PHY_RXER może być podciągnięty do VCC lub gdy niewykorzystywany należy go podciągnąć przez rezystor do GND. 

Aby zresetować układ należy ustawić pin w stan niski. Powrót do normalnej pracy następuje po ponownym ustawieniu stanu wysokiego. Drugi pin wystawia informację, że nastąpił błąd w ramce danych. Pierwszy ze wspomnianych wyprowadzeń musi być skonfigurowany jako wyjście, ponieważ reset jest sterowany z mikrokontrolera. PHY_RXER należy skonfigurować jako wejście, i ustawić odpowiednie dane w rejestrach tak aby przesyłał informację o błędzie. 

Konfiguracja:


W projekcie wykorzystałem układ LAN8720, to jego sterownik jest możliwy do dołożenia bezpośrednio z bibliotek CubeMx, podczas deklaracji projektu. Wobec tego samo uruchomienie działającego ETH na poprawnie zaprojektowanej płycie zajmuje kilka minut. 


Konfiguracja biblioteki LWIP:


Po wygenerowaniu projektu wprowadzam kilka zmian.

Gdy wszystko zostanie poprawnie ustawione w CubeMx to w pliku FLASH znajdziemy przygotowaną konfigurację pamięci:

  1.   .lwip_sec (NOLOAD) : {
  2.     . = ABSOLUTE(0x30000000);
  3.     *(.RxDecripSection)
  4.    
  5.     . = ABSOLUTE(0x30000060);
  6.     *(.TxDecripSection)
  7.    
  8.     . = ABSOLUTE(0x30000200);
  9.     *(.RxArraySection)
  10.   } >RAM_D2 AT> ROM

Deskryptory zostały zdefiniowane w pliku ethernetif.c:

  1. #if defined ( __ICCARM__ ) /*!< IAR Compiler */
  2.  
  3. #pragma location=0x30004000
  4. ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  5. #pragma location=0x30004060
  6. ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  7. #pragma location=0x30004200
  8. uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
  9.  
  10. #elif defined ( __CC_ARM )  /* MDK ARM Compiler */
  11.  
  12. __attribute__((at(0x30004000))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
  13. __attribute__((at(0x30004060))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
  14. __attribute__((at(0x30004200))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffer */
  15.  
  16. #elif defined ( __GNUC__ ) /* GNU Compiler */
  17.  
  18. ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
  19. ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection")));   /* Ethernet Tx DMA Descriptors */
  20. uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */
  21.  
  22. #endif

Po konfiguracji i uruchomieniu projektu sprawdzam przesyłanie informacji z pingiem:


Do projektu dołożyłem konfigurację jako TCP Server Echo. Inicjalizacja:

  1. void tcp_echoserver_init(void)
  2. {
  3.   tcp_echoserver_pcb = tcp_new();
  4.  
  5.   if (tcp_echoserver_pcb != NULL)
  6.   {
  7.     err_t err;
  8.  
  9.     err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 1025);
  10.  
  11.     if (err == ERR_OK)
  12.     {
  13.       tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);
  14.       tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
  15.     }
  16.     else
  17.     {
  18.       memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
  19.     }
  20.   }
  21. }

Do testu połączenia wykorzystałem program Hercules:


Cały projekt można pobrać z dysku Google pod tym linkiem.