27
27
#include " netsocket/nsapi_types.h"
28
28
#include " platform/mbed_power_mgmt.h"
29
29
#include " platform/mbed_error.h"
30
+ #include " CacheAlignedBuffer.h"
30
31
31
32
#include " stm32xx_emac_config.h"
32
33
#include " stm32xx_emac.h"
33
34
35
+
34
36
#include " mbed-trace/mbed_trace.h"
35
37
36
38
#if defined(ETH_IP_VERSION_V2)
59
61
#include " lan8742/lan8742.h"
60
62
#include " lwip/memp.h"
61
63
#include " lwip/api.h"
64
+ #include " linker_scripts/stm32_eth_region_size_calcs.h"
62
65
#endif
63
66
64
67
using namespace std ::chrono;
@@ -75,46 +78,19 @@ using namespace std::chrono;
75
78
#define STM_ETH_MTU_SIZE 1500
76
79
#define STM_ETH_IF_NAME " st"
77
80
78
- #ifndef ETH_IP_VERSION_V2
79
-
80
- #if defined (__ICCARM__) /* !< IAR Compiler */
81
- #pragma data_alignment=4
82
- #endif
83
- __ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END; /* Ethernet Rx DMA Descriptor */
84
-
85
- #if defined (__ICCARM__) /* !< IAR Compiler */
86
- #pragma data_alignment=4
87
- #endif
88
- __ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END; /* Ethernet Tx DMA Descriptor */
89
-
90
- #if defined (__ICCARM__) /* !< IAR Compiler */
91
- #pragma data_alignment=4
92
- #endif
93
- __ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */
94
-
95
- #if defined (__ICCARM__) /* !< IAR Compiler */
96
- #pragma data_alignment=4
97
- #endif
98
- __ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */
99
-
100
- #else // ETH_IP_VERSION_V2
101
-
102
- #if defined ( __ICCARM__ ) /* !< IAR Compiler */
81
+ #define ETH_RX_DESC_CNT MBED_CONF_STM32_EMAC_ETH_RXBUFNB
82
+ #define ETH_TX_DESC_CNT MBED_CONF_STM32_EMAC_ETH_TXBUFNB
103
83
104
- #pragma location=0x30040000
105
- ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
106
- #pragma location=0x30040100
107
- ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
108
- #pragma location=0x30040400
109
- uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffers */
84
+ ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(" .EthDescriptors" ))); /* Ethernet Rx DMA Descriptors */
85
+ ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(" .EthDescriptors" ))); /* Ethernet Tx DMA Descriptors */
110
86
111
- #elif defined ( __GNUC__ ) /* GCC & ARMC6*/
87
+ // Rx buffer addresses need to be aligned 4 bytes and to cache lines because we cache invalidate the buffers after receiving them.
88
+ mbed::StaticCacheAlignedBuffer<uint32_t , ETH_MAX_PACKET_SIZE / sizeof (uint32_t )> Rx_Buff[ETH_RX_DESC_CNT] __attribute__((section(" .EthBuffers" ))); /* Ethernet Receive Buffers */
112
89
113
- ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(" .RxDecripSection" ))); /* Ethernet Rx DMA Descriptors */
114
- ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(" .TxDecripSection" ))); /* Ethernet Tx DMA Descriptors */
115
- uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE] __attribute__((section(" .RxArraySection" ))); /* Ethernet Receive Buffers */
90
+ // Tx buffers just need to be aligned to the nearest 4 bytes.
91
+ uint32_t Tx_Buff[ETH_TX_DESC_CNT][ETH_MAX_PACKET_SIZE / sizeof (uint32_t )] __attribute__((section(" .EthBuffers" )));
116
92
117
- #endif
93
+ #if defined(ETH_IP_VERSION_V2)
118
94
119
95
static lan8742_Object_t LAN8742;
120
96
@@ -206,6 +182,12 @@ bool _phy_is_up(int32_t phy_state)
206
182
return phy_state > LAN8742_STATUS_LINK_DOWN;
207
183
}
208
184
185
+ // Integer log2 of an integer.
186
+ // from https://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
187
+ static inline uint32_t log2i (uint32_t x) {
188
+ return sizeof (uint32_t ) * 8 - __builtin_clz (x) - 1 ;
189
+ }
190
+
209
191
static void MPU_Config (void )
210
192
{
211
193
MPU_Region_InitTypeDef MPU_InitStruct;
@@ -214,34 +196,23 @@ static void MPU_Config(void)
214
196
HAL_MPU_Disable ();
215
197
216
198
/* Configure the MPU attributes as Device not cacheable
217
- for ETH DMA descriptors */
199
+ for ETH DMA descriptors. The linker script puts these into their own
200
+ cordoned off, power-of-2 sized region. */
218
201
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
219
- MPU_InitStruct.BaseAddress = 0x30040000 ;
220
- MPU_InitStruct.Size = MPU_REGION_SIZE_1KB;
221
202
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
222
203
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
223
204
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
224
205
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
225
- MPU_InitStruct.Number = MPU_REGION_NUMBER0;
206
+ MPU_InitStruct.Number = 4 ; // Mbed OS MPU config can use regions 0 through 3
226
207
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
227
208
MPU_InitStruct.SubRegionDisable = 0x00 ;
228
- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE ;
209
+ MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE ;
229
210
230
- HAL_MPU_ConfigRegion (&MPU_InitStruct);
211
+ extern uint8_t __eth_descriptors_start[0 ]; // <-- defined in linker script
212
+ MPU_InitStruct.BaseAddress = reinterpret_cast <uint32_t >(__eth_descriptors_start);
231
213
232
- /* Configure the MPU attributes as Cacheable write through
233
- for LwIP RAM heap which contains the Tx buffers */
234
- MPU_InitStruct.Enable = MPU_REGION_ENABLE;
235
- MPU_InitStruct.BaseAddress = 0x30044000 ;
236
- MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
237
- MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
238
- MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
239
- MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
240
- MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
241
- MPU_InitStruct.Number = MPU_REGION_NUMBER1;
242
- MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
243
- MPU_InitStruct.SubRegionDisable = 0x00 ;
244
- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
214
+ // Use a logarithm to calculate the region size
215
+ MPU_InitStruct.Size = log2i (STM32_DMA_DESCRIP_REGION_SIZE) - 1 ;
245
216
246
217
HAL_MPU_ConfigRegion (&MPU_InitStruct);
247
218
@@ -341,7 +312,7 @@ bool STM32_EMAC::low_level_init_successful()
341
312
}
342
313
343
314
/* Initialize Rx Descriptors list: Chain Mode */
344
- if (HAL_ETH_DMARxDescListInit (&EthHandle, DMARxDscrTab, & Rx_Buff[0 ][ 0 ] , ETH_RXBUFNB) != HAL_OK) {
315
+ if (HAL_ETH_DMARxDescListInit (&EthHandle, DMARxDscrTab, Rx_Buff[0 ]. data () , ETH_RXBUFNB) != HAL_OK) {
345
316
tr_error (" HAL_ETH_DMARxDescListInit issue" );
346
317
return false ;
347
318
}
@@ -399,7 +370,7 @@ bool STM32_EMAC::low_level_init_successful()
399
370
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
400
371
401
372
for (idx = 0 ; idx < ETH_RX_DESC_CNT; idx++) {
402
- HAL_ETH_DescAssignMemory (&EthHandle, idx, Rx_Buff[idx], NULL );
373
+ HAL_ETH_DescAssignMemory (&EthHandle, idx, reinterpret_cast < uint8_t *>( Rx_Buff[idx]. data ()) , NULL );
403
374
}
404
375
405
376
tr_info (" low_level_init_successful" );
@@ -534,6 +505,12 @@ bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
534
505
Txbuffer[i].next = NULL ;
535
506
}
536
507
508
+ #if defined(__DCACHE_PRESENT)
509
+ // For chips with a cache, we need to evict the Tx data from cache to main memory.
510
+ // This ensures that the DMA controller can see the most up-to-date copy of the data.
511
+ SCB_CleanDCache_by_Addr (Txbuffer[i].buffer , Txbuffer[i].len );
512
+ #endif
513
+
537
514
i++;
538
515
}
539
516
@@ -661,7 +638,7 @@ int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)
661
638
/* Build Rx descriptor to be ready for next data reception */
662
639
HAL_ETH_BuildRxDescriptors (&EthHandle);
663
640
664
- #if !( defined(DUAL_CORE) && defined(CORE_CM4) )
641
+ #if defined(__DCACHE_PRESENT )
665
642
/* Invalidate data cache for ETH Rx Buffers */
666
643
SCB_InvalidateDCache_by_Addr ((uint32_t *)RxBuff.buffer , frameLength);
667
644
#endif
0 commit comments