STM32 har allt - Utom trådlöshet
Re: STM32 har allt - Utom trådlöshet
Ja, men tydligen så får jag ett felmeddelande angående om ETH på DMA.
Alltså jag har skrivit 0% kod för ETH. Jag har BARA bockat i att jag vill ha ETH och sedan har jag inte gjort något mera.
Om STM32CubeIDE har konfigurerat allt, och det blev fel. Då måste detta vara en bug?
Jag har ju bara valt "Interrupt mode" istället för "polling mode" för jag vill ha händelser, som kan anropa en funktion.
För LwIP så måste man ha polling mode dock om man använder STM32CubeMX's egna LwIP kod. Men oavsett om det är polling eller interrupt som är valet, så blir felkoden exakt det samma.
Alltså jag har skrivit 0% kod för ETH. Jag har BARA bockat i att jag vill ha ETH och sedan har jag inte gjort något mera.
Om STM32CubeIDE har konfigurerat allt, och det blev fel. Då måste detta vara en bug?
Jag har ju bara valt "Interrupt mode" istället för "polling mode" för jag vill ha händelser, som kan anropa en funktion.
För LwIP så måste man ha polling mode dock om man använder STM32CubeMX's egna LwIP kod. Men oavsett om det är polling eller interrupt som är valet, så blir felkoden exakt det samma.
Re: STM32 har allt - Utom trådlöshet
Det är ju DMA det är därför du anger minnet den skall buffra i.
Flash är minnet programmet du skriver hamnar i (därav att man "flashar" in koden), ram är arbetsminnet.
Flash är långsammare och har begränsat antal skrivningar (därför använder man det inte som ram), men det behåller informationen efter avstängning till skillnad mot ram.
Och för tredjegången (och sista).
Du måste reservera den minnesarean i ram som du buffrar till.
Flash är minnet programmet du skriver hamnar i (därav att man "flashar" in koden), ram är arbetsminnet.
Flash är långsammare och har begränsat antal skrivningar (därför använder man det inte som ram), men det behåller informationen efter avstängning till skillnad mot ram.
Och för tredjegången (och sista).
Du måste reservera den minnesarean i ram som du buffrar till.
Re: STM32 har allt - Utom trådlöshet
Tackar.
Men i detta fall så handlar detta om Eth i STM32. Inte LwIP. När jag bockar i att jag vill köra Eth, så frågar den inte om någon minnesadress.
När jag bockar i LwIP så frågar den om heap-adress. Men den allokerar bara heap en gång vid start.
Men i detta fall så handlar detta om Eth i STM32. Inte LwIP. När jag bockar i att jag vill köra Eth, så frågar den inte om någon minnesadress.
När jag bockar i LwIP så frågar den om heap-adress. Men den allokerar bara heap en gång vid start.
Re: STM32 har allt - Utom trådlöshet
Utdraget från
Tittar vi på denna
Så betyder AIS följande att det finns problem i DMAIER.
Då tittar vi på denna
Då tittar vi på denna
Här vet vi att DMAErrorCode är innehåller 13, dvs DMA Fatal bus error.
Fråga:
En på Reddit har samma problem:
Och hans egna svar var:
Kod: Markera allt
/* ETH DMA Error */
if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_AIS))
{
if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_AISE))
{
heth->ErrorCode |= HAL_ETH_ERROR_DMA;
/* if fatal bus error occurred */
if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_FBES))
{
/* Get DMA error code */
heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS));
/* Disable all interrupts */
__HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMAIER_NISE | ETH_DMAIER_AISE);
/* Set HAL state to ERROR */
heth->gState = HAL_ETH_STATE_ERROR;
}
else
{
/* Get DMA error status */
heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_ETS | ETH_DMASR_RWTS |
ETH_DMASR_RBUS | ETH_DMASR_AIS));
/* Clear the interrupt summary flag */
__HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMASR_ETS | ETH_DMASR_RWTS |
ETH_DMASR_RBUS | ETH_DMASR_AIS));
}
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
/* Call registered Error callback*/
heth->ErrorCallback(heth);
#else
/* Ethernet DMA Error callback */
HAL_ETH_ErrorCallback(heth);
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
}
}
Kod: Markera allt
/* ETH DMA Error */
if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_AIS))
{
Kod: Markera allt
if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_AISE))
{
heth->ErrorCode |= HAL_ETH_ERROR_DMA;
Kod: Markera allt
/* if fatal bus error occurred */
if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_FBES))
{
/* Get DMA error code */
heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS));
En på Reddit har samma problem:
Och hans egna svar var:
Vad menar han?Alright, thank you everyone for your suggestions. They were all great, but the cause of the issue was much simpler: I misunderstood the format of the register holding the descriptor's list base address. The 2 LSBs are reserved, which I interpreted as needing to left shift the address by 2. This was wrong, these bits are reserved because this address must be 4-byte (bus width) aligned. So I was essentially supplying 4 * list_address to the ETH DMA, which probably sent it to some inaccessible memory location.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: STM32 har allt - Utom trådlöshet
Han menar att han inte förstått att DMA måste vara aligned på 32-bitar, dvs du kan skriva till 0x0000, 0x0004 och 0x0008 osv men inte 0x0001 eller 0x0002.
Re: STM32 har allt - Utom trådlöshet
Betyder detta att koden är fel på med tanke på att "The LSB bits [1/2/3:0] for 32/64/128-bit bus width) are internally ignored"?
Kod: Markera allt
static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth)
{
ETH_DMADescTypeDef *dmatxdesc;
uint32_t i;
/* Fill each DMATxDesc descriptor with the right values */
for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++)
{
dmatxdesc = heth->Init.TxDesc + i;
WRITE_REG(dmatxdesc->DESC0, 0x0);
WRITE_REG(dmatxdesc->DESC1, 0x0);
WRITE_REG(dmatxdesc->DESC2, 0x0);
WRITE_REG(dmatxdesc->DESC3, 0x0);
WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc);
/* Set Second Address Chained bit */
SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TCH);
if (i < ((uint32_t)ETH_TX_DESC_CNT - 1U))
{
WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc + i + 1U));
}
else
{
WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc));
}
/* Set the DMA Tx descriptors checksum insertion */
SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL);
}
heth->TxDescList.CurTxDesc = 0;
/* Set Transmit Descriptor List Address */
WRITE_REG(heth->Instance->DMATDLAR, (uint32_t) heth->Init.TxDesc); <<<--- HÄR
}
Kod: Markera allt
static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth)
{
ETH_DMADescTypeDef *dmarxdesc;
uint32_t i;
for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++)
{
dmarxdesc = heth->Init.RxDesc + i;
WRITE_REG(dmarxdesc->DESC0, 0x0);
WRITE_REG(dmarxdesc->DESC1, 0x0);
WRITE_REG(dmarxdesc->DESC2, 0x0);
WRITE_REG(dmarxdesc->DESC3, 0x0);
WRITE_REG(dmarxdesc->BackupAddr0, 0x0);
WRITE_REG(dmarxdesc->BackupAddr1, 0x0);
/* Set Own bit of the Rx descriptor Status */
dmarxdesc->DESC0 = ETH_DMARXDESC_OWN;
/* Set Buffer1 size and Second Address Chained bit */
dmarxdesc->DESC1 = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE;
/* Enable Ethernet DMA Rx Descriptor interrupt */
dmarxdesc->DESC1 &= ~ETH_DMARXDESC_DIC;
/* Set Rx descritors addresses */
WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc);
if (i < ((uint32_t)ETH_RX_DESC_CNT - 1U))
{
WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc + i + 1U));
}
else
{
WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc));
}
}
WRITE_REG(heth->RxDescList.RxDescIdx, 0);
WRITE_REG(heth->RxDescList.RxDescCnt, 0);
WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0);
WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0);
WRITE_REG(heth->RxDescList.ItMode, 0);
/* Set Receive Descriptor List Address */
WRITE_REG(heth->Instance->DMARDLAR, (uint32_t) heth->Init.RxDesc); <<<--- HÄR
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: STM32 har allt - Utom trådlöshet
Pekar värdet heth->Init.TxDesc och heth->Init.RxDesc på adresser som är alignade på rätt sätt?
Re: STM32 har allt - Utom trådlöshet
Ja. Det gör det.
Men många verkar ha problem med just detta. Är det så mycket buggar i ST's processorer eller utvecklingsverktyg?
Men många verkar ha problem med just detta. Är det så mycket buggar i ST's processorer eller utvecklingsverktyg?
Kod: Markera allt
ETH_TxPacketConfig TxConfig;
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
...
..
.
heth.Init.MACAddr = &MACAddr[0];
heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
heth.Init.TxDesc = DMATxDscrTab;
heth.Init.RxDesc = DMARxDscrTab;
heth.Init.RxBuffLen = 1524;
/* USER CODE BEGIN MACADDRESS */
/* USER CODE END MACADDRESS */
if (HAL_ETH_Init(&heth) != HAL_OK)
{
Error_Handler();
}
Kod: Markera allt
HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth)
{
/*------------------ DMA Tx Descriptors Configuration ----------------------*/
ETH_DMATxDescListInit(heth);
/*------------------ DMA Rx Descriptors Configuration ----------------------*/
ETH_DMARxDescListInit(heth);
Kod: Markera allt
static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth)
{
ETH_DMADescTypeDef *dmatxdesc;
uint32_t i;
/* Fill each DMATxDesc descriptor with the right values */
for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++)
{
dmatxdesc = heth->Init.TxDesc + i;
WRITE_REG(dmatxdesc->DESC0, 0x0);
WRITE_REG(dmatxdesc->DESC1, 0x0);
WRITE_REG(dmatxdesc->DESC2, 0x0);
WRITE_REG(dmatxdesc->DESC3, 0x0);
WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc);
/* Set Second Address Chained bit */
SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TCH);
if (i < ((uint32_t)ETH_TX_DESC_CNT - 1U))
{
WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc + i + 1U));
}
else
{
WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc));
}
/* Set the DMA Tx descriptors checksum insertion */
SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL);
}
heth->TxDescList.CurTxDesc = 0;
/* Set Transmit Descriptor List Address */
WRITE_REG(heth->Instance->DMATDLAR, (uint32_t) heth->Init.TxDesc);
}
Kod: Markera allt
static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth)
{
ETH_DMADescTypeDef *dmarxdesc;
uint32_t i;
for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++)
{
dmarxdesc = heth->Init.RxDesc + i;
WRITE_REG(dmarxdesc->DESC0, 0x0);
WRITE_REG(dmarxdesc->DESC1, 0x0);
WRITE_REG(dmarxdesc->DESC2, 0x0);
WRITE_REG(dmarxdesc->DESC3, 0x0);
WRITE_REG(dmarxdesc->BackupAddr0, 0x0);
WRITE_REG(dmarxdesc->BackupAddr1, 0x0);
/* Set Own bit of the Rx descriptor Status */
dmarxdesc->DESC0 = ETH_DMARXDESC_OWN;
/* Set Buffer1 size and Second Address Chained bit */
dmarxdesc->DESC1 = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE;
/* Enable Ethernet DMA Rx Descriptor interrupt */
dmarxdesc->DESC1 &= ~ETH_DMARXDESC_DIC;
/* Set Rx descritors addresses */
WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc);
if (i < ((uint32_t)ETH_RX_DESC_CNT - 1U))
{
WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc + i + 1U));
}
else
{
WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc));
}
}
WRITE_REG(heth->RxDescList.RxDescIdx, 0);
WRITE_REG(heth->RxDescList.RxDescCnt, 0);
WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0);
WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0);
WRITE_REG(heth->RxDescList.ItMode, 0);
/* Set Receive Descriptor List Address */
WRITE_REG(heth->Instance->DMARDLAR, (uint32_t) heth->Init.RxDesc);
}
Re: STM32 har allt - Utom trådlöshet
Jag tänker använda ett färdigt projekt som är skapat av ST själva.
Då finns det tre projektmappar:
- EWARN
- MDK-ARM
- SW4STM32
Hur kan jag importera dessa och få ett STM32CubeIDE projekt med STM32CubeIDE?
Då finns det tre projektmappar:
- EWARN
- MDK-ARM
- SW4STM32
Hur kan jag importera dessa och få ett STM32CubeIDE projekt med STM32CubeIDE?
Re: STM32 har allt - Utom trådlöshet
Okej! Nu börjar det hända lite saker.
Förr fick jag endast
Men efter att ha sett RESET-pinnen på min Ethernet PHY till HÖG (logisk 1) INNAN jag aktiverar min PHY i STM32 samt aktiverade dessa:
Ja, då fick jag detta.
Fråga:
Om man får time out med Ping...alltså betyder det att den prickar rätt adress, men den får inget tillbaka?
Förr fick jag endast
Kod: Markera allt
C:\Users\danie>ping 192.168.1.15
Pinging 192.168.1.15 with 32 bytes of data:
Reply from 192.168.1.34: Destination host unreachable.
Reply from 192.168.1.34: Destination host unreachable.
Reply from 192.168.1.34: Destination host unreachable.
Ping statistics for 192.168.1.15:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Control-C
^C
C:\Users\danie>
Kod: Markera allt
C:\Users\danie>ping 192.168.1.15
Pinging 192.168.1.15 with 32 bytes of data:
Request timed out.
Request timed out.
Request timed out.
Request timed out.
Ping statistics for 192.168.1.15:
Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),
C:\Users\danie>
Om man får time out med Ping...alltså betyder det att den prickar rätt adress, men den får inget tillbaka?
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: STM32 har allt - Utom trådlöshet
Ja! Ett svar kommer inte, men adressen finns!
Känns som jag är på väg att få detta fungera kanske
Men enligt denna så måste man hålla på med flash-script.
Problemet är att han använder en annan processor? Någon som vet hur man ska göra?
Mitt ethernetif.c ser ut så här. Jag tror att jag har fortfarande problem med minnet. Chache minne?
Känns som jag är på väg att få detta fungera kanske
Men enligt denna så måste man hålla på med flash-script.
Problemet är att han använder en annan processor? Någon som vet hur man ska göra?
Mitt ethernetif.c ser ut så här. Jag tror att jag har fortfarande problem med minnet. Chache minne?
Kod: Markera allt
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : ethernetif.c
* Description : This file provides code for the configuration
* of the ethernetif.c MiddleWare.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/timeouts.h"
#include "netif/ethernet.h"
#include "netif/etharp.h"
#include "lwip/ethip6.h"
#include "ethernetif.h"
#include "dp83848.h"
#include <string.h>
/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* Private define ------------------------------------------------------------*/
/* Network interface name */
#define IFNAME0 's'
#define IFNAME1 't'
/* ETH Setting */
#define ETH_DMA_TRANSMIT_TIMEOUT ( 20U )
#define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT) * 2U)
/* ETH_RX_BUFFER_SIZE parameter is defined in lwipopts.h */
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* Private variables ---------------------------------------------------------*/
/*
@Note: This interface is implemented to operate in zero-copy mode only:
- Rx buffers are allocated statically and passed directly to the LwIP stack
they will return back to ETH DMA after been processed by the stack.
- Tx Buffers will be allocated from LwIP stack memory heap,
then passed to ETH HAL driver.
@Notes:
1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4,
to customize it please redefine ETH_RX_DESC_CNT in ETH GUI (Rx Descriptor Length)
so that updated value will be generated in stm32xxxx_hal_conf.h
1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4,
to customize it please redefine ETH_TX_DESC_CNT in ETH GUI (Tx Descriptor Length)
so that updated value will be generated in stm32xxxx_hal_conf.h
2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT
2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must
passed to ETH DMA in the init field (heth.Init.RxBuffLen)
2.c The RX Ruffers addresses and sizes must be properly defined to be aligned
to L1-CACHE line size (32 bytes).
*/
/* Data Type Definitions */
typedef enum
{
RX_ALLOC_OK = 0x00,
RX_ALLOC_ERROR = 0x01
} RxAllocStatusTypeDef;
typedef struct
{
struct pbuf_custom pbuf_custom;
uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32);
} RxBuff_t;
/* Memory Pool Declaration */
#define ETH_RX_BUFFER_CNT 12U
LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");
/* Variable Definitions */
static uint8_t RxAllocStatus;
__IO uint32_t TxPkt = 0;
__IO uint32_t RxPkt = 0;
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Global Ethernet handle */
ETH_HandleTypeDef heth;
ETH_TxPacketConfig TxConfig;
/* Private function prototypes -----------------------------------------------*/
int32_t ETH_PHY_IO_Init(void);
int32_t ETH_PHY_IO_DeInit (void);
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t ETH_PHY_IO_GetTick(void);
dp83848_Object_t DP83848;
dp83848_IOCtx_t DP83848_IOCtx = {ETH_PHY_IO_Init,
ETH_PHY_IO_DeInit,
ETH_PHY_IO_WriteReg,
ETH_PHY_IO_ReadReg,
ETH_PHY_IO_GetTick};
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */
/* Private functions ---------------------------------------------------------*/
void pbuf_free_custom(struct pbuf *p);
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/*******************************************************************************
LL Driver Interface ( LwIP stack --> ETH)
*******************************************************************************/
/**
* @brief In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
HAL_StatusTypeDef hal_eth_init_status = HAL_OK;
/* Start ETH HAL Init */
uint8_t MACAddr[6] ;
heth.Instance = ETH;
MACAddr[0] = 0x80;
MACAddr[1] = 0x80;
MACAddr[2] = 0xA2;
MACAddr[3] = 0xAE;
MACAddr[4] = 0x13;
MACAddr[5] = 0x41;
heth.Init.MACAddr = &MACAddr[0];
heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
heth.Init.TxDesc = DMATxDscrTab;
heth.Init.RxDesc = DMARxDscrTab;
heth.Init.RxBuffLen = 1536;
/* USER CODE BEGIN MACADDRESS */
/* USER CODE END MACADDRESS */
hal_eth_init_status = HAL_ETH_Init(&heth);
memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));
TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
/* End ETH HAL Init */
/* Initialize the RX POOL */
LWIP_MEMPOOL_INIT(RX_POOL);
#if LWIP_ARP || LWIP_ETHERNET
/* set MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;
/* set MAC hardware address */
netif->hwaddr[0] = heth.Init.MACAddr[0];
netif->hwaddr[1] = heth.Init.MACAddr[1];
netif->hwaddr[2] = heth.Init.MACAddr[2];
netif->hwaddr[3] = heth.Init.MACAddr[3];
netif->hwaddr[4] = heth.Init.MACAddr[4];
netif->hwaddr[5] = heth.Init.MACAddr[5];
/* maximum transfer unit */
netif->mtu = ETH_MAX_PAYLOAD;
/* Accept broadcast address and ARP traffic */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
#if LWIP_ARP
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
#else
netif->flags |= NETIF_FLAG_BROADCAST;
#endif /* LWIP_ARP */
/* USER CODE BEGIN PHY_PRE_CONFIG */
/* USER CODE END PHY_PRE_CONFIG */
/* Set PHY IO functions */
DP83848_RegisterBusIO(&DP83848, &DP83848_IOCtx);
/* Initialize the DP83848 ETH PHY */
DP83848_Init(&DP83848);
if (hal_eth_init_status == HAL_OK)
{
/* Get link state */
ethernet_link_check_state(netif);
}
else
{
Error_Handler();
}
#endif /* LWIP_ARP || LWIP_ETHERNET */
/* USER CODE BEGIN LOW_LEVEL_INIT */
/* USER CODE END LOW_LEVEL_INIT */
}
/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become available since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
uint32_t i = 0U;
struct pbuf *q = NULL;
err_t errval = ERR_OK;
ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
for(q = p; q != NULL; q = q->next)
{
if(i >= ETH_TX_DESC_CNT)
return ERR_IF;
Txbuffer[i].buffer = q->payload;
Txbuffer[i].len = q->len;
if(i>0)
{
Txbuffer[i-1].next = &Txbuffer[i];
}
if(q->next == NULL)
{
Txbuffer[i].next = NULL;
}
i++;
}
TxConfig.Length = p->tot_len;
TxConfig.TxBuffer = Txbuffer;
TxConfig.pData = p;
HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
return errval;
}
/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf * low_level_input(struct netif *netif)
{
struct pbuf *p = NULL;
if(RxAllocStatus == RX_ALLOC_OK)
{
HAL_ETH_ReadData(&heth, (void **)&p);
}
return p;
}
/**
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
void ethernetif_input(struct netif *netif)
{
struct pbuf *p = NULL;
do
{
p = low_level_input( netif );
if (p != NULL)
{
if (netif->input( p, netif) != ERR_OK )
{
pbuf_free(p);
}
}
} while(p!=NULL);
}
#if !LWIP_ARP
/**
* This function has to be completed by user in case of ARP OFF.
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if ...
*/
static err_t low_level_output_arp_off(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
{
err_t errval;
errval = ERR_OK;
/* USER CODE BEGIN 5 */
/* USER CODE END 5 */
return errval;
}
#endif /* LWIP_ARP */
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
/*
* Initialize the snmp variables and counters inside the struct netif.
* The last argument should be replaced with your link speed, in units
* of bits per second.
*/
// MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
/* We directly use etharp_output() here to save a function call.
* You can instead declare your own function an call etharp_output()
* from it if you have to do some checks before sending (e.g. if link
* is available...) */
#if LWIP_IPV4
#if LWIP_ARP || LWIP_ETHERNET
#if LWIP_ARP
netif->output = etharp_output;
#else
/* The user should write its own code in low_level_output_arp_off function */
netif->output = low_level_output_arp_off;
#endif /* LWIP_ARP */
#endif /* LWIP_ARP || LWIP_ETHERNET */
#endif /* LWIP_IPV4 */
#if LWIP_IPV6
netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
return ERR_OK;
}
/**
* @brief Custom Rx pbuf free callback
* @param pbuf: pbuf to be freed
* @retval None
*/
void pbuf_free_custom(struct pbuf *p)
{
struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p;
LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
/* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to
* call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */
if (RxAllocStatus == RX_ALLOC_ERROR)
{
RxAllocStatus = RX_ALLOC_OK;
RxPkt = 1 ;
}
}
/* USER CODE BEGIN 6 */
/**
* @brief Returns the current time in milliseconds
* when LWIP_TIMERS == 1 and NO_SYS == 1
* @param None
* @retval Current Time value
*/
u32_t sys_now(void)
{
return HAL_GetTick();
}
/* USER CODE END 6 */
void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(ethHandle->Instance==ETH)
{
/* USER CODE BEGIN ETH_MspInit 0 */
/* USER CODE END ETH_MspInit 0 */
/* Enable Peripheral clock */
__HAL_RCC_ETH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**ETH GPIO Configuration
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PB11 ------> ETH_TX_EN
PB12 ------> ETH_TXD0
PB13 ------> ETH_TXD1
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
/* USER CODE BEGIN ETH_MspInit 1 */
/* USER CODE END ETH_MspInit 1 */
}
}
void HAL_ETH_MspDeInit(ETH_HandleTypeDef* ethHandle)
{
if(ethHandle->Instance==ETH)
{
/* USER CODE BEGIN ETH_MspDeInit 0 */
/* USER CODE END ETH_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ETH_CLK_DISABLE();
/**ETH GPIO Configuration
PC1 ------> ETH_MDC
PA1 ------> ETH_REF_CLK
PA2 ------> ETH_MDIO
PA7 ------> ETH_CRS_DV
PC4 ------> ETH_RXD0
PC5 ------> ETH_RXD1
PB11 ------> ETH_TX_EN
PB12 ------> ETH_TXD0
PB13 ------> ETH_TXD1
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13);
/* Peripheral interrupt Deinit*/
HAL_NVIC_DisableIRQ(ETH_IRQn);
/* USER CODE BEGIN ETH_MspDeInit 1 */
/* USER CODE END ETH_MspDeInit 1 */
}
}
/*******************************************************************************
PHI IO Functions
*******************************************************************************/
/**
* @brief Initializes the MDIO interface GPIO and clocks.
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_Init(void)
{
/* We assume that MDIO GPIO configuration is already done
in the ETH_MspInit() else it should be done here
*/
/* Configure the MDIO Clock */
HAL_ETH_SetMDIOClockRange(&heth);
return 0;
}
/**
* @brief De-Initializes the MDIO interface .
* @param None
* @retval 0 if OK, -1 if ERROR
*/
int32_t ETH_PHY_IO_DeInit (void)
{
return 0;
}
/**
* @brief Read a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param pRegVal: pointer to hold the register value
* @retval 0 if OK -1 if Error
*/
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
{
if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK)
{
return -1;
}
return 0;
}
/**
* @brief Write a value to a PHY register through the MDIO interface.
* @param DevAddr: PHY port address
* @param RegAddr: PHY register address
* @param RegVal: Value to be written
* @retval 0 if OK -1 if Error
*/
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
{
if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK)
{
return -1;
}
return 0;
}
/**
* @brief Get the time in millisecons used for internal PHY driver process.
* @retval Time value
*/
int32_t ETH_PHY_IO_GetTick(void)
{
return HAL_GetTick();
}
/**
* @brief Check the ETH link state then update ETH driver and netif link accordingly.
* @param argument: netif
* @retval None
*/
void ethernet_link_check_state(struct netif *netif)
{
ETH_MACConfigTypeDef MACConf = {0};
int32_t PHYLinkState = 0;
uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;
PHYLinkState = DP83848_GetLinkState(&DP83848);
if(netif_is_link_up(netif) && (PHYLinkState <= DP83848_STATUS_LINK_DOWN))
{
HAL_ETH_Stop(&heth);
netif_set_down(netif);
netif_set_link_down(netif);
}
else if(!netif_is_link_up(netif) && (PHYLinkState > DP83848_STATUS_LINK_DOWN))
{
switch (PHYLinkState)
{
case DP83848_STATUS_100MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case DP83848_STATUS_100MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_100M;
linkchanged = 1;
break;
case DP83848_STATUS_10MBITS_FULLDUPLEX:
duplex = ETH_FULLDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
case DP83848_STATUS_10MBITS_HALFDUPLEX:
duplex = ETH_HALFDUPLEX_MODE;
speed = ETH_SPEED_10M;
linkchanged = 1;
break;
default:
break;
}
if(linkchanged)
{
/* Get MAC Config MAC */
HAL_ETH_GetMACConfig(&heth, &MACConf);
MACConf.DuplexMode = duplex;
MACConf.Speed = speed;
HAL_ETH_SetMACConfig(&heth, &MACConf);
HAL_ETH_Start(&heth);
netif_set_up(netif);
netif_set_link_up(netif);
}
}
}
void HAL_ETH_RxAllocateCallback(uint8_t **buff)
{
/* USER CODE BEGIN HAL ETH RxAllocateCallback */
struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL);
if (p)
{
/* Get the buff from the struct pbuf address. */
*buff = (uint8_t *)p + offsetof(RxBuff_t, buff);
p->custom_free_function = pbuf_free_custom;
/* Initialize the struct pbuf.
* This must be performed whenever a buffer's allocated because it may be
* changed by lwIP or the app, e.g., pbuf_free decrements ref. */
pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE);
}
else
{
RxAllocStatus = RX_ALLOC_ERROR;
*buff = NULL;
}
/* USER CODE END HAL ETH RxAllocateCallback */
}
void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
{
/* USER CODE BEGIN HAL ETH RxLinkCallback */
struct pbuf **ppStart = (struct pbuf **)pStart;
struct pbuf **ppEnd = (struct pbuf **)pEnd;
struct pbuf *p = NULL;
/* Get the struct pbuf from the buff address. */
p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff));
p->next = NULL;
p->tot_len = 0;
p->len = Length;
/* Chain the buffer. */
if (!*ppStart)
{
/* The first buffer of the packet. */
*ppStart = p;
}
else
{
/* Chain the buffer to the end of the packet. */
(*ppEnd)->next = p;
}
*ppEnd = p;
/* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its tot_len
* set to its own length, plus the length of all the following pbufs in the chain. */
for (p = *ppStart; p != NULL; p = p->next)
{
p->tot_len += Length;
}
/* USER CODE END HAL ETH RxLinkCallback */
}
void HAL_ETH_TxFreeCallback(uint32_t * buff)
{
/* USER CODE BEGIN HAL ETH TxFreeCallback */
pbuf_free((struct pbuf *)buff);
/* USER CODE END HAL ETH TxFreeCallback */
}
/* USER CODE BEGIN 8 */
/* USER CODE END 8 */
Re: STM32 har allt - Utom trådlöshet
Jag har en fråga som jag tror ni kan svara på.
Vad har jag för duplex på min Ethernet PHY?
Enligt min ST processor så körs denna kod vid början av starten. Den säger att jag har 100 MBIT Full Duplex. Enligt databladet Min uppkoppling så verkar jag ha AN_EN = 1, AN_0 = 1, AN_1 = 1. Kan det vara något här man ska välja?
Noter att jag har ju valt en extern PHY. Jag får fortfarande time out när jag pingar.
Vad har jag för duplex på min Ethernet PHY?
Enligt min ST processor så körs denna kod vid början av starten. Den säger att jag har 100 MBIT Full Duplex. Enligt databladet Min uppkoppling så verkar jag ha AN_EN = 1, AN_0 = 1, AN_1 = 1. Kan det vara något här man ska välja?
Noter att jag har ju valt en extern PHY. Jag får fortfarande time out när jag pingar.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: STM32 har allt - Utom trådlöshet
Det bör betyda att den gett sig tillkänna på nätverket och att din dator kan mappa dess ip-nummer till mac-adress. Ser du den med "arp -a <ip-nummer>"?
För att få svar på ping krävs det att den skickar ett sådant. Gör ip-stacken i STM32 det rakt av utan extra insats?