реклама на сайте
подробности

 
 
> STM32F107RB + LAN8742A
alexmiron31
сообщение Mar 6 2018, 14:39
Сообщение #1





Группа: Участник
Сообщений: 7
Регистрация: 17-10-17
Пользователь №: 99 790



Приветствую всех форумчан. Столкнулся с необходимостью интеграции в проект возможности подключения по Ethernet. Микросхема PHY - LAN8742A. Сложность заключается в том, что раньше я работал только с WiFi-модулем, вся суть общения с которым в самом худшем случае - это соединение по UART, поскольку TCP/IP-стек в нем уже интегрирован. А в сложившейся ситуации нужно писать драйвер для соединение микросхемы с контроллером, а потом, насколько я понимаю, еще и драйвер подключения к TCP/IP-стеку. Использовать SPL или HAL я не хочу, поскольку до этого прекрасно обходился регистрами, но пока что все найденные мною в общем доступе примеры по работе STM-ки с этой микросхемой сделаны именно на одной из этих двух библиотек, а обсуждения на форуме по похожим темам касаются уже следующих этапов, то есть непосредственно передачи данных, до чего я пока не дошел.
Суть вопроса: как написать драйвер для этой микросхемы, с чего начинать и куда смотреть? Буду благодарен за любой пинок в нужном направлении.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
scifi
сообщение Mar 6 2018, 14:45
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



У меня STM32F107RC + KSZ8081RNA, но это практически то же самое. В основной прошивке lwip, в загрузчике uIP (из-за того, что он меньше). Всё портировал сам, драйвер делал сам. Кстати, драйвер для PHY - это сильно сказано, в отдельных случаях там вообще ничего не надо делать, но обычно лучше всё-таки отслеживать подключение и отключение кабеля.
Go to the top of the page
 
+Quote Post
alexmiron31
сообщение Mar 6 2018, 15:02
Сообщение #3





Группа: Участник
Сообщений: 7
Регистрация: 17-10-17
Пользователь №: 99 790



Цитата(scifi @ Mar 6 2018, 16:45) *
У меня STM32F107RC + KSZ8081RNA, но это практически то же самое. В основной прошивке lwip, в загрузчике uIP (из-за того, что он меньше). Всё портировал сам, драйвер делал сам. Кстати, драйвер для PHY - это сильно сказано, в отдельных случаях там вообще ничего не надо делать, но обычно лучше всё-таки отслеживать подключение и отключение кабеля.


У Вас есть возможность продемонстрировать части кода, отвечающие за инициализацию Ethernet и описание дескрипторов DMA в самом камне? Насколько я смог понять из найденных источников, это - самая проблемная часть. Или, если нет, то, может быть, сможете сказать, где найти какую-нибудь документацию под это дело? На сайте ST есть демонстрация работы lwIP с разными линейками, но она тоже обходит момент инициализации периферии, а больше аппноутов по этой теме я у них не нашел.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 6 2018, 15:45
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (alexmiron31 @ Mar 6 2018, 17:02) *
У Вас есть возможность продемонстрировать части кода, отвечающие за инициализацию Ethernet и описание дескрипторов DMA в самом камне?

Дескрипторы:
CODE

namespace ethernet
{

struct dma_rx_descriptor
{
union status
{
struct
{
uint32_t Payload_checksum_error : 1;
uint32_t CRC_error : 1;
uint32_t Dribble_bit_error : 1;
uint32_t Receive_error : 1;
uint32_t Watchdog_timeout : 1;
uint32_t Is_ethernet_frame : 1;
uint32_t Late_collision : 1;
uint32_t IP_header_checksum_error : 1;
uint32_t Last_descriptor : 1;
uint32_t First_descriptor : 1;
uint32_t VLAN_tag : 1;
uint32_t Overflow_error : 1;
uint32_t Length_error : 1;
uint32_t Src_addr_filter_fail : 1;
uint32_t Descriptor_error : 1;
uint32_t Error_summary : 1;
uint32_t Frame_length : 14;
uint32_t Dst_addr_filter_fail : 1;
uint32_t Owned_by_DMA : 1;
};
uint32_t Raw;
} Status;

union control
{
struct
{
uint32_t Buffer_size : 13;
uint32_t : 1;
uint32_t Is_chained : 1;
uint32_t Is_last : 1;
uint32_t : 13;
uint32_t : 2;
uint32_t : 1;
};
uint32_t Raw;
} Control;
uint32_t volatile * pBuffer;
dma_rx_descriptor volatile * pNext;
};

struct dma_tx_descriptor
{
union status
{
struct
{
uint32_t Deferred_bit : 1;
uint32_t Underflow_error : 1;
uint32_t Excessive_deferral : 1;
uint32_t Collision_count : 4;
uint32_t VLAN_frame : 1;
uint32_t Excessive_collision : 1;
uint32_t Late_collision : 1;
uint32_t No_carrier : 1;
uint32_t Loss_of_carrier : 1;
uint32_t IP_payload_error : 1;
uint32_t Frame_flushed : 1;
uint32_t Jabber_timeout : 1;
uint32_t Error_summary : 1;
uint32_t IP_header_error : 1;
uint32_t Tx_timestamp_status : 1;
uint32_t : 2;
uint32_t Is_chained : 1;
uint32_t Is_end_of_ring : 1;
uint32_t Checksum_insertion : 2;
uint32_t : 1;
uint32_t Tx_timestamp_enable : 1;
uint32_t Disable_pad : 1;
uint32_t Disable_CRC : 1;
uint32_t First_segment : 1;
uint32_t Last_segment : 1;
uint32_t Interrupt_on_completion: 1;
uint32_t Owned_by_DMA : 1;
};
uint32_t Raw;
} Status;
uint32_t Byte_count : 13;

uint32_t volatile * pBuffer;
dma_tx_descriptor volatile * pNext;
};

template<typename descriptor, size_t max_packet_size>
struct dma_chain
{
descriptor volatile Descriptor;
uint32_t volatile Data[(max_packet_size + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
};

template<size_t packet_size>
uintptr_t init_descriptors_chain(dma_chain<dma_tx_descriptor, packet_size> * pChain, size_t elements)
{
auto pElement = pChain;
do
{
pElement->Descriptor.pBuffer = pElement->Data;
pElement->Descriptor.pNext = &pElement[1].Descriptor;
dma_tx_descriptor::status Status = {};
Status.Is_chained = true;
/* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
Status.First_segment = true;
Status.Last_segment = true;
Status.Checksum_insertion = 3; // IP header, payload, pseudo-header
pElement++->Descriptor.Status.Raw = Status.Raw;
}
while(--elements);
pElement[-1].Descriptor.pNext = &pChain->Descriptor;
return (uintptr_t)&pChain->Descriptor;
}

template<size_t packet_size>
uintptr_t init_descriptors_chain(dma_chain<dma_rx_descriptor, packet_size> * pChain, size_t elements)
{
auto pElement = pChain;
do
{
dma_rx_descriptor::status Status = {};
Status.Owned_by_DMA = true;
pElement->Descriptor.Status.Raw = Status.Raw;

dma_rx_descriptor::control Control = {};
Control.Buffer_size = packet_size;
Control.Is_chained = true;
pElement->Descriptor.Control.Raw = Control.Raw;
pElement->Descriptor.pBuffer = pElement->Data;
pElement->Descriptor.pNext = &pElement[1].Descriptor;
++pElement;
}
while(--elements);
pElement[-1].Descriptor.pNext = &pChain->Descriptor;
return (uintptr_t)&pChain->Descriptor;
}

template<typename T>
inline uintptr_t init_descriptors_chain(T & buffer)
{
return init_descriptors_chain(buffer, sizeof(buffer) / sizeof(buffer[0]));
}

} // namespace ethernet
Объявление:
CODE
#define ETH_MAX_PACKET_SIZE    1520    /*!< ETH_HEADER + ETH_EXTRA + MAX_ETH_PAYLOAD + ETH_CRC */

namespace ethernet
{
static dma_chain<dma_rx_descriptor, ETH_MAX_PACKET_SIZE> Rx_buffer[ETH_RXBUFNB];
static dma_chain<dma_tx_descriptor, ETH_MAX_PACKET_SIZE> Tx_buffer[ETH_TXBUFNB];

static dma_tx_descriptor volatile * Tx_next = &Tx_buffer[0].Descriptor;
static dma_rx_descriptor volatile * Rx_last = &Rx_buffer[0].Descriptor;

Инициализация:
CODE
err_t stm32_if_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
/*
* 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.
*/
// NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);

/* 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...) */
netif->output = etharp_output;
netif->linkoutput = stm32_if_output;

/* initialize the hardware */
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* maximum transfer unit */
netif->mtu = 1500;
/* device capabilities */
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;

lan8720a::init();

while(ETH->DMABMR & ETH_DMABMR_SR)
;
/* set MAC hardware address */
ETH->MACA0HR = 0
| (netif->hwaddr[5] << 8)
| (netif->hwaddr[4] << 0)
;
ETH->MACA0LR = 0
| (netif->hwaddr[3] << 24)
| (netif->hwaddr[2] << 16)
| (netif->hwaddr[1] << 8)
| (netif->hwaddr[0] << 0)
;

ETH->MACFFR = 0
| 0 * ETH_MACFFR_RA // Receive all
| 0 * ETH_MACFFR_HPF // Hash or perfect filter
| 0 * ETH_MACFFR_SAF // Source address filter
| 0 * ETH_MACFFR_SAIF // SA inverse filtering
| 1 * ETH_MACFFR_PCF // Pass control frames:
// 1: MAC filters all control frames from reaching the application
// 2: MAC forwards all control frames to application even if they fail the Address Filter
// 3: MAC forwards control frames that pass the Address Filter
| 0 * ETH_MACFFR_BFD // Broadcast frame disable
| 0 * ETH_MACFFR_PAM // Pass all multicast
| 0 * ETH_MACFFR_DAIF // DA Inverse filtering
| 0 * ETH_MACFFR_HM // Hash multicast
| 0 * ETH_MACFFR_HU // Hash unicast
| 0 * ETH_MACFFR_PM // Promiscuous mode
;
// Hash table
ETH->MACHTHR = 0;
ETH->MACHTLR = 0;

ETH->MACFCR = 0
| 0 * (ETH_MACFCR_PT & -ETH_MACFCR_PT) // Pause time
| 1 * ETH_MACFCR_ZQPD // Zero-quanta pause disable
| 0 * (ETH_MACFCR_PLT & -ETH_MACFCR_PLT)// Pause low threshold:
// 0: Pause time minus 4 slot times
// 1: Pause time minus 28 slot times
// 2: Pause time minus 144 slot times
// 3: Pause time minus 256 slot times
| 0 * ETH_MACFCR_UPFD // Unicast pause frame detect
| 1 * ETH_MACFCR_RFCE // Receive flow control enable
| 1 * ETH_MACFCR_TFCE // Transmit flow control enable
| 0 * ETH_MACFCR_FCBBPA // Flow control busy/backpressure activate
;

ETH->MACVLANTR = 0
| 0 * ETH_MACVLANTR_VLANTC // 12-bit VLAN tag comparison
| 0 * (ETH_MACVLANTR_VLANTI & -ETH_MACVLANTR_VLANTI) // VLAN tag identifier
;

/* Initialize Tx Descriptors list: Chain Mode */
ETH->DMATDLAR = init_descriptors_chain(Tx_buffer);
/* Initialize Rx Descriptors list: Chain Mode, owned by DMA, ints enabled */
ETH->DMARDLAR = init_descriptors_chain(Rx_buffer);

ETH->DMABMR = 0
| 1 * ETH_DMABMR_AAB // Address-aligned beats
| 0 * ETH_DMABMR_FPM // 4xPBL mode
| 0 * ETH_DMABMR_USP // Use separate PBL
| 1 * (ETH_DMABMR_RDP & -ETH_DMABMR_RDP) // RxDMA programmable burst length, must be 2^n
| 0 * ETH_DMABMR_FB // Fixed burst
| 0 * (ETH_DMABMR_RTPR & -ETH_DMABMR_RTPR) // Rx/Tx priority ratio
| 1 * (ETH_DMABMR_PBL & -ETH_DMABMR_PBL) // TxDMA (or both) programmable burst length
| 0 * ETH_DMABMR_DSL // Descriptor Skip Length
| 0 * ETH_DMABMR_DA // DMA arbitration scheme: 0 - roubd-robbin, 1 - rx priority
| 0 * ETH_DMABMR_SR // Software reset
;

/* Enable MAC transmission and reception*/
ETH->MACCR = 0
| 0 * ETH_MACCR_WD // Watchdog disabling
| 0 * ETH_MACCR_JD // Jabber disabling
| 0 * (ETH_MACCR_IFG & -ETH_MACCR_IFG) // Inter-frame gap
| 0 * ETH_MACCR_CSD // Carrier sense disabling
| 1 * ETH_MACCR_FES // Fast ethernet speed
| 0 * ETH_MACCR_ROD // Receive own disabling
| 0 * ETH_MACCR_LM // loopback mode
| 1 * ETH_MACCR_DM // Duplex mode
| 0 * ETH_MACCR_IPCO // IP Checksum offload
| 0 * ETH_MACCR_RD // Retry disable
| 0 * ETH_MACCR_APCS // Automatic Pad/CRC stripping
| 0 * (ETH_MACCR_BL &-ETH_MACCR_BL) // Back-off limit: random integer number ® of slot time delays before rescheduling
// a transmission attempt during retries after a collision: 0 =< r <2^k
| 0 * ETH_MACCR_DC // Defferal check
| 1 * ETH_MACCR_TE // Transmitter enable
| 1 * ETH_MACCR_RE // Receiver enable
;
/* Flush Transmit FIFO, enable DMA transmission and DMA reception */
ETH->DMAOMR = 0
| 1 * ETH_DMAOMR_DTCEFD // Disabling dropping of TCP/IP checksum error frames
| 1 * ETH_DMAOMR_RSF // Receive store and forward
| 1 * ETH_DMAOMR_DFRF // Disabling flushing of received frames
| 1 * ETH_DMAOMR_TSF // Transmit store and forward Mandatory for hardware CRC calc.
| 0 * ETH_DMAOMR_FTF // Flush transmit FIFO
| 0 * (ETH_DMAOMR_TTC & -ETH_DMAOMR_TTC)// Transmit threshold control:
// 0: 64 Bytes
// 1: 128 Bytes
// 2: 192 Bytes
// 3: 256 Bytes
// 4: 40 Bytes
// 5: 32 Bytes
// 6: 24 Bytes
// 7: 16 Bytes
| 1 * ETH_DMAOMR_ST // Start/stop transmission command
| 0 * ETH_DMAOMR_FEF // Forward error frames
| 0 * ETH_DMAOMR_FUGF // Forward undersized good frames
| 0 * (ETH_DMAOMR_RTC & -ETH_DMAOMR_RTC)// receive threshold control
// 0: 64 Bytes
// 1: 32 Bytes
// 2: 96 Bytes
// 3: 128 Bytes
| 0 * ETH_DMAOMR_OSF // operate on second frame
| 1 * ETH_DMAOMR_SR // Start/stop receive
;
etharp_init();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);

ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE; // enable receive interrupt

return ERR_OK;
}



--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 16:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01821 секунд с 7
ELECTRONIX ©2004-2016