2727#include " netsocket/nsapi_types.h"
2828#include " platform/mbed_power_mgmt.h"
2929#include " platform/mbed_error.h"
30+ #include " CacheAlignedBuffer.h"
3031
3132#include " stm32xx_emac_config.h"
3233#include " stm32xx_emac.h"
3334
35+
3436#include " mbed-trace/mbed_trace.h"
3537
3638#if defined(ETH_IP_VERSION_V2)
5961#include " lan8742/lan8742.h"
6062#include " lwip/memp.h"
6163#include " lwip/api.h"
64+ #include " linker_scripts/stm32_eth_region_size_calcs.h"
6265#endif
6366
6467using namespace std ::chrono;
@@ -75,46 +78,19 @@ using namespace std::chrono;
7578#define STM_ETH_MTU_SIZE 1500
7679#define STM_ETH_IF_NAME " st"
7780
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
10383
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 */
11086
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 */
11289
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" )));
11692
117- #endif
93+ #if defined(ETH_IP_VERSION_V2)
11894
11995static lan8742_Object_t LAN8742;
12096
@@ -206,6 +182,12 @@ bool _phy_is_up(int32_t phy_state)
206182 return phy_state > LAN8742_STATUS_LINK_DOWN;
207183}
208184
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+
209191static void MPU_Config (void )
210192{
211193 MPU_Region_InitTypeDef MPU_InitStruct;
@@ -214,34 +196,23 @@ static void MPU_Config(void)
214196 HAL_MPU_Disable ();
215197
216198 /* 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. */
218201 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
219- MPU_InitStruct.BaseAddress = 0x30040000 ;
220- MPU_InitStruct.Size = MPU_REGION_SIZE_1KB;
221202 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
222203 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
223204 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
224205 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
226207 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
227208 MPU_InitStruct.SubRegionDisable = 0x00 ;
228- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE ;
209+ MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE ;
229210
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);
231213
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 ;
245216
246217 HAL_MPU_ConfigRegion (&MPU_InitStruct);
247218
@@ -341,7 +312,7 @@ bool STM32_EMAC::low_level_init_successful()
341312 }
342313
343314 /* 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) {
345316 tr_error (" HAL_ETH_DMARxDescListInit issue" );
346317 return false ;
347318 }
@@ -399,7 +370,7 @@ bool STM32_EMAC::low_level_init_successful()
399370 TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
400371
401372 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 );
403374 }
404375
405376 tr_info (" low_level_init_successful" );
@@ -534,6 +505,12 @@ bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
534505 Txbuffer[i].next = NULL ;
535506 }
536507
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+
537514 i++;
538515 }
539516
@@ -661,7 +638,7 @@ int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)
661638 /* Build Rx descriptor to be ready for next data reception */
662639 HAL_ETH_BuildRxDescriptors (&EthHandle);
663640
664- #if !( defined(DUAL_CORE) && defined(CORE_CM4) )
641+ #if defined(__DCACHE_PRESENT )
665642 /* Invalidate data cache for ETH Rx Buffers */
666643 SCB_InvalidateDCache_by_Addr ((uint32_t *)RxBuff.buffer , frameLength);
667644#endif
0 commit comments