Forum: Mikrocontroller und Digitale Elektronik STM32 lwip UDP Empfang fehlerhaft


von Tim B. (tim95)


Lesenswert?

Hallo zusammen,

vielleicht hatte ja einer von euch schon mal das selbe Problem:

Ich versuche auf einem STM32H743 mithilfe des lwip Stacks (ohne RTOS) 
eine Kommunikation über UDP zu etablieren.

Das Versenden von Paketen funktioniert einwandfrei, das Empfangen 
funktioniert allerdings nicht.
Die Funktion "low_level_input" reagiert wenn ich eine Paket an den STM 
schicke, allerdings wird in der Funktion "ethernet_input" das Paket 
nicht an "ip4_input" übergeben dabei wird die Debug-Message:"Can't move 
over header in packet" ausgeben.
Diese Fehlermeldung wird ausgelöst durch den Fehler "not enough space 
for new header size" durch "pbuf_header_impl"  in "pbuf.c".

Da ich ein absoluter Neuling im Bereich lwip bin, verstehe ich nicht 
wirklich wo das Problem liegen könnte.
Bei der Konfiguration habe ich mich an diese Anleitung gehalten:
https://community.st.com/docs/DOC-1811-faq-ethernet-not-working-on-stm32h7


Wenn einer von euch einen Rat hat würde ich mich sehr freuen!

mfg

von jzjjf (Gast)


Lesenswert?

zum test den cache( beide ... )  der MCU mal deaktivieren

aber grundsätzlich ... wo ist dein code hier?
hänge den bitte ran ...

von Tim B. (tim95)


Lesenswert?

Hi,
erstmal vielen dank für die schnelle Antwort!

Code, siehe unten, habe ich erstmal nicht gepostet, weil ich dachte das 
Problem liegt im lwip Stack.

Den DCache muss ich erst Enablen, sonst funktioniert lwip_init() nicht.
Danach deaktiviere ich ihn wieder, weil ich sonst maximal drei Pakete 
hintereinander senden kann.
Die MPU Konfiguration habe ich dem FAQ entnommen.



main.c (abgespeckt)
1
/* Includes ------------------------------------------------------------------*/
2
#include "main.h"
3
#include "stm32h7xx_hal.h"
4
#include "lwip.h"
5
6
/* USER CODE BEGIN Includes */
7
#include "lwip/udp.h"
8
#include <string.h>
9
#include <stdio.h>
10
/* USER CODE END Includes */
11
12
/* Private variables ---------------------------------------------------------*/
13
14
/* USER CODE BEGIN PV */
15
/* Private variables ---------------------------------------------------------*/
16
static struct udp_pcb *udpPcb1_p;
17
extern struct netif gnetif;
18
__IO uint32_t message_count = 0;
19
/* Private function prototypes -----------------------------------------------*/
20
void SystemClock_Config(void);
21
static void MPU_Config(void);
22
static void MX_GPIO_Init(void);
23
24
/* USER CODE BEGIN PFP */
25
/* Private function prototypes -----------------------------------------------*/
26
void udpApp1_sendTESTPacket(void);
27
void udp_echo_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
28
void udpApp1_init(void);
29
/* USER CODE END PFP */
30
31
/* USER CODE BEGIN 0 */
32
33
/* USER CODE END 0 */
34
35
/**
36
  * @brief  The application entry point.
37
  *
38
  * @retval None
39
  */
40
int main(void)
41
{
42
  /* USER CODE BEGIN 1 */
43
44
  /* USER CODE END 1 */
45
46
  /* MPU Configuration----------------------------------------------------------*/
47
  MPU_Config();
48
49
  /* Enable I-Cache-------------------------------------------------------------*/
50
  //SCB_EnableICache();
51
52
  /* Enable D-Cache-------------------------------------------------------------*/
53
  SCB_EnableDCache();
54
55
  /* MCU Configuration----------------------------------------------------------*/
56
57
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
58
  HAL_Init();
59
60
  /* USER CODE BEGIN Init */
61
62
  /* USER CODE END Init */
63
64
  /* Configure the system clock */
65
  SystemClock_Config();
66
67
  /* USER CODE BEGIN SysInit */
68
69
  /* USER CODE END SysInit */
70
71
  /* Initialize all configured peripherals */
72
  MX_GPIO_Init();
73
  MX_LWIP_Init();
74
  //MX_DMA2D_Init();
75
  /* USER CODE BEGIN 2 */
76
  udpApp1_init();
77
  SCB_DisableDCache();
78
  /* USER CODE END 2 */
79
80
  /* Infinite loop */
81
  /* USER CODE BEGIN WHILE */
82
  udpApp1_sendTESTPacket();
83
        HAL_Delay(1000);
84
  while (1)
85
  {
86
87
  /* USER CODE END WHILE */
88
89
  /* USER CODE BEGIN 3 */
90
   
91
92
     //MX_LWIP_Process();
93
     ethernetif_input(&gnetif);
94
95
     /* USER CODE BEGIN 4_2 */
96
     /* USER CODE END 4_2 */
97
     /* Handle timeouts */
98
     sys_check_timeouts();
99
  }
100
  /* USER CODE END 3 */
101
102
}
103
104
105
106
/* USER CODE BEGIN 4 */
107
void udpApp1_sendTESTPacket(void){
108
  ip_addr_t       client1IpAddr;
109
  struct pbuf     *ethTxBuffer_p;
110
  u8_t   data[100];
111
112
  IP4_ADDR(&client1IpAddr, 192, 168, 1, 255); //-> Brodcast
113
114
  sprintf((char*)data, "sending udp client message %d", 10);
115
  ethTxBuffer_p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_RAM);
116
117
118
  //ethTxBuffer_p = pbuf_alloc(PBUF_TRANSPORT, sizeof(clientMagicPacket_c), PBUF_RAM);
119
  if (ethTxBuffer_p == NULL){}
120
121
  memcpy(ethTxBuffer_p->payload, data, sizeof(data));
122
  //memcpy(ethTxBuffer_p->payload, clientMagicPacket_c, sizeof(clientMagicPacket_c));
123
124
  udp_sendto(udpPcb1_p, ethTxBuffer_p, &client1IpAddr,65010);
125
126
  pbuf_free(ethTxBuffer_p);
127
}
128
void udp_echo_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
129
{
130
  /*increment message count */
131
  struct pbuf *p_tx;
132
133
    /* allocate pbuf from RAM*/
134
    p_tx = pbuf_alloc(PBUF_TRANSPORT,p->len, PBUF_RAM);
135
136
    message_count++;
137
138
    /* Free receive pbuf */
139
    pbuf_free(p);
140
}
141
void udpApp1_init(void){
142
  err_t         udpErr;
143
  ip_addr_t     ownIPaddr;
144
145
  udpPcb1_p = udp_new();
146
147
  if(udpPcb1_p != NULL)
148
  {
149
    IP4_ADDR(&ownIPaddr, 192, 168, 1, 20); //STM32-IP
150
151
    //udpErr = udp_bind(udpPcb1_p, &ownIPaddr, 61005);
152
    udpErr = udp_bind(udpPcb1_p, IP_ADDR_ANY, 61005);
153
154
155
    udp_recv(udpPcb1_p, udp_echo_recv, NULL);
156
157
    if (udpErr ==ERR_OK){}
158
  }
159
}
160
161
/* USER CODE END 4 */
162
163
/* MPU Configuration */
164
165
void MPU_Config(void)
166
{
167
  MPU_Region_InitTypeDef MPU_InitStruct;
168
169
  /* Disables the MPU */
170
  HAL_MPU_Disable();
171
    /**Initializes and configures the Region and the memory to be protected 
172
    */
173
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
174
  MPU_InitStruct.Number = MPU_REGION_NUMBER2;
175
  MPU_InitStruct.BaseAddress = 0x30040000;
176
  MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
177
  MPU_InitStruct.SubRegionDisable = 0x0;
178
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
179
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;;
180
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
181
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;;
182
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
183
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
184
185
  HAL_MPU_ConfigRegion(&MPU_InitStruct);
186
187
    /**Initializes and configures the Region and the memory to be protected 
188
    */
189
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
190
  MPU_InitStruct.Number = MPU_REGION_NUMBER1;
191
  MPU_InitStruct.BaseAddress = 0x30044000;
192
  MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
193
  MPU_InitStruct.SubRegionDisable = 0x0;
194
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
195
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;;
196
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
197
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
198
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
199
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
200
201
  HAL_MPU_ConfigRegion(&MPU_InitStruct);
202
203
  /**Initializes and configures the Region and the memory to be protected
204
   */
205
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
206
 MPU_InitStruct.Number = MPU_REGION_NUMBER0;
207
 MPU_InitStruct.BaseAddress = 0x30040000;
208
 MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
209
 MPU_InitStruct.SubRegionDisable = 0x0;
210
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
211
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;;
212
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
213
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
214
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
215
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
216
217
 HAL_MPU_ConfigRegion(&MPU_InitStruct);
218
  /* Enables the MPU */
219
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
220
221
}

von jzjjf (Gast)


Lesenswert?

schau mal nach was dein linkerscript mit dem speicher macht.

im STM gibt es DTCM, SRAM( mehrere regionen )
Je nach dem wo dein ethernetbuffer liegt und die descriptoren kann es da 
schon probleme geben .


Die andere Frage:
warum kein RTOS und interrupt betrieb?

die CPU nur mit dem bisschen ethernet zu verheizen ist ... doof

von Tim B. (tim95)


Lesenswert?

In dem linkerscript habe ich bereits alle Zuweisungen von "DTCMRAM" nach 
"RAM D1" geändert, sonst Funktioniert auch das Senden nicht....
Das habe ich allerdings auch manuell gemacht.

Das ganze soll, wenn es denn mal läuft, noch in ein größeres Projekt 
eingebettet werden, deswegen erst einmal so, ohne RTOS, um es überhaupt 
zum laufen zu bringen.

von jzjjf (Gast)


Lesenswert?

Tim B. schrieb:
> habe ich bereits alle Zuweisungen von "DTCMRAM" nach
> "RAM D1" geändert, sonst Funktioniert auch das Senden nicht....
> Das habe ich allerdings auch manuell gemacht.

dann bitte das file anhängen ...
eth buffer
descriptoren
init von diesen

und ggf die größe der TX/RX buffer

von Tim B. (tim95)


Angehängte Dateien:

Lesenswert?

Angehängt das linkerfile

Die Initizialisrung der Descriptoren lautet wie folgt:
1
__attribute__((at(0x30040000))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
2
__attribute__((at(0x30040060))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
3
__attribute__((at(0x30040200))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffer */
Größe ist:
1
#define ETH_TX_DESC_CNT ((uint32_t)4)       /* Tx Descriptor Length  */
2
#define ETH_RX_DESC_CNT ((uint32_t)4)       /* Rx Descriptor Length  */

ansonsten habe ich auch alles auf Default gelassen ( Projekt mit MXCube 
erstellt)

von Jim M. (turboj)


Lesenswert?

Tim B. schrieb:
> __attribute__((at(0x30040000)))

Schau mal im Map File nach ob das funktioniert hat. Gnu LD kann 
normalerweise keine festen Addresszuweisungen außerhalb des LD Skripts - 
man muss mit __attribute__((section("foo"))) arbeiten AFAIK.

von jzjjf (Gast)


Lesenswert?

ich habe sections im LD angelegt.
1
  /* Ethernet memory*/          
2
  .eth (NOLOAD):
3
  {
4
    . = ALIGN(8);
5
    *(.eth)
6
    *(.eth*)
7
    . = ALIGN(8);
8
  } >RAM2

__attribute__((__section__(".eth"),used))

ich nutze überall 8 byte alignment ...
hat mir schon öfters kopfschmerzen bereitet warum der M7 dann meinte 
hier und da langsamer zu sein

von Tim B. (tim95)


Lesenswert?

Vielen Dank schon mal an alle!

Habe es jetzt hinbekommen, in dem ich in pbuf.c die Abfrage rausgenommen 
habe die den Fehler geliefert hat... meiner Meinung nach war die if 
Bedingung fehlerhaft.

von Maxx (Gast)


Lesenswert?

Und die Entwickler haben einen solchen Fehler, der alle RX Frames 
wegwirft "übersehen"?

von Tim B. (tim95)


Lesenswert?

Ja wahrscheinlich!....ne keine Ahnung warum das so ist

Hier der problematische C Code
1
 if ((u8_t *)p->payload > (u8_t *)p + SIZEOF_STRUCT_PBUF) { 
2
      LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE,
3
        ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
4
        (void *)p->payload, (void *)((u8_t *)p + SIZEOF_STRUCT_PBUF)));
5
      /* restore old payload pointer */
6
      p->payload = payload;
7
      /* bail out unsuccessfully */
8
      return 1;
9
    }

Das Problem ist, wenn ein Paket versendet werden soll ist ">" die 
richtig Beziehung.
Wenn man aber empfängt, müsste die Abfrage andersherum, sprich "<", 
sein.
Da ich beides will, habe ich das jetzt einfach rausgeschmissen, 
funktioniert offensichtlich auch so.

Die Pakete sind ja sowieso über Checksums abgesichert, wenn da was 
schief geht sollte man es spätestens da noch merken.

Falls jemand noch eine bessere Idee, oder Erklärung hat gerne her damit!

von jzjjf (Gast)


Lesenswert?

der lwip code funktioniert eigentlich ganz gut.
habe selbst einen F7 mit RTOS + lwIP laufen.

Ob das eine gute idee war das so umzufriemeln ..
wird sich zeigen wenn du eine applikation laufen hast.

Wenn es hier zu kuriositäten kommt ..
schreib dir JETZT schonmal auf das du  hier was geändert hattest ...

von jzjjf (Gast)


Lesenswert?

ich vermute hier eher ein falsches speichermanagement

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.