Поскольку у меня на столе имеется платка с stm32f217 + phy ks8721bl (режим RMII) пришлось демку LwIP переделать под нее (не поленился переделал все демки в том числе и под FREE RTOS). Все приложения работают без проблем. Вот ссылка на архив (большой ~47м ). (переделаны проекты для Keil, проекты под IAR переделываюся только сменой камня. Все работает также без проблем) Но остался вопрос.
Нормального понимания как работать с LwIP + stm32 пока нет. Дока на стек и демку не проясняет.
У кого есть опыт работы с LwIP + stm32 подсобите please для старта простым примером LwIP как принять одни данные по UDP и отправить другие.
В демке имеется UDP эхо сервер. Поможет даже подсказка как сделать так, чтобы сервер отправлял не эхо, а конкретные данные из конкретного буфера типа *my_buf.
Спасибо.
В main все начинается так:
Код
/* check if any packet received */
if (ETH_CheckFrameReceived())
{
/* process received ethernet packet */
LwIP_Pkt_Handle();
}
if (ETH_CheckFrameReceived())
{
/* process received ethernet packet */
LwIP_Pkt_Handle();
}
Функция ETH_CheckFrameReceived делает это:
CODE
/**
* @brief This function polls for a frame reception
* @param None
* @retval Returns 1 when a frame is received, 0 if none.
*/
uint32_t ETH_CheckFrameReceived(void)
{
/* check if last segment */
if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) &&
((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (uint32_t)RESET))
{
DMA_RX_FRAME_infos->LS_Rx_Desc = DMARxDescToGet;
DMA_RX_FRAME_infos->Seg_Count++;
return 1;
}
/* check if first segment */
else if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) &&
((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (uint32_t)RESET)&&
((DMARxDescToGet->Status & ETH_DMARxDesc_LS) == (uint32_t)RESET))
{
DMA_RX_FRAME_infos->FS_Rx_Desc = DMARxDescToGet;
DMA_RX_FRAME_infos->LS_Rx_Desc = NULL;
DMA_RX_FRAME_infos->Seg_Count = 1;
DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr);
}
/* check if intermediate segment */
else if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) &&
((DMARxDescToGet->Status & ETH_DMARxDesc_FS) == (uint32_t)RESET)&&
((DMARxDescToGet->Status & ETH_DMARxDesc_LS) == (uint32_t)RESET))
{
(DMA_RX_FRAME_infos->Seg_Count) ++;
DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr);
}
return 0;
}
* @brief This function polls for a frame reception
* @param None
* @retval Returns 1 when a frame is received, 0 if none.
*/
uint32_t ETH_CheckFrameReceived(void)
{
/* check if last segment */
if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) &&
((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (uint32_t)RESET))
{
DMA_RX_FRAME_infos->LS_Rx_Desc = DMARxDescToGet;
DMA_RX_FRAME_infos->Seg_Count++;
return 1;
}
/* check if first segment */
else if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) &&
((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (uint32_t)RESET)&&
((DMARxDescToGet->Status & ETH_DMARxDesc_LS) == (uint32_t)RESET))
{
DMA_RX_FRAME_infos->FS_Rx_Desc = DMARxDescToGet;
DMA_RX_FRAME_infos->LS_Rx_Desc = NULL;
DMA_RX_FRAME_infos->Seg_Count = 1;
DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr);
}
/* check if intermediate segment */
else if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) &&
((DMARxDescToGet->Status & ETH_DMARxDesc_FS) == (uint32_t)RESET)&&
((DMARxDescToGet->Status & ETH_DMARxDesc_LS) == (uint32_t)RESET))
{
(DMA_RX_FRAME_infos->Seg_Count) ++;
DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr);
}
return 0;
}
Я так понимаю, что функция проверяет имеется ли что-то в DMA В частности если имеется фрейм и сегмент в фрейме последний, то возвращается 1.
Что такое последний сегмент? Понимаю, что можно послать меня на очередной мануал. Но мануалы меня уже сильно достали из за их непоследовательности и часто бесполезности.
Ответьте пожалуйста на русском коротко работу функции ETH_CheckFrameReceived(void) (функция почемуто всегда, послал я фрейм или нет, возвращает 1)
Дальше начинается кошмар по имени
Код
/* process received ethernet packet */
LwIP_Pkt_Handle();
который далее переходит в LwIP_Pkt_Handle();
Код
/* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
ethernetif_input(&netif);
ethernetif_input(&netif);
и куда дальше попадают собственно данные посланного из компа UDP пакета, так, чтобы с ними можно было -бы поработать и как послать компу ответ в виде своего пакета (а не того же самого) не допираю.
Подсобите, кто сталкивался с этим.
Нашел пока это http://lwip.wikia.com/wiki/Raw/UDP
Всеравно не понятно как на базе LwIP послать на комп UDP пакет Ну допустим так:
Код
struct udp_pcb *upcb;
/* Create a new UDP control block */
upcb = udp_new();
/* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
udp_bind(upcb, IP_ADDR_ANY, 23);
/* Connect to the remote client */
udp_connect(upcb, addr, 23);
/* Create a new UDP control block */
upcb = udp_new();
/* Bind the upcb to the UDP_PORT port */
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
udp_bind(upcb, IP_ADDR_ANY, 23);
/* Connect to the remote client */
udp_connect(upcb, addr, 23);
В каком виде нужно записать addr?
Похоже, что дальше можно
Код
udp_send(struct udp_pcb * pcb, struct pbuf * p)
тоесть
Код
udp_send(upcb, p);
Что такое struct pbuf * p