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

 
 
> LwIP стек в STM32F217
Acvarif
сообщение Jan 12 2012, 09:42
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



На st имеется демка под LwIP на stm32f207 для PHY DP83848C (режим MII) (в демке реализованы почти все возможные варианты серверов и клиентов).
Поскольку у меня на столе имеется платка с 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();
    }


Функция 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;
}

Я так понимаю, что функция проверяет имеется ли что-то в DMA В частности если имеется фрейм и сегмент в фрейме последний, то возвращается 1.
Что такое последний сегмент? Понимаю, что можно послать меня на очередной мануал. Но мануалы меня уже сильно достали из за их непоследовательности и часто бесполезности.
Ответьте пожалуйста на русском коротко работу функции ETH_CheckFrameReceived(void) (функция почемуто всегда, послал я фрейм или нет, возвращает 1)
Дальше начинается кошмар по имени
Код
      /* process received ethernet packet */
      LwIP_Pkt_Handle();
который далее переходит в
Код
  /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
  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);

В каком виде нужно записать addr?
Похоже, что дальше можно
Код
udp_send(struct udp_pcb * pcb, struct pbuf * p)

тоесть
Код
udp_send(upcb, p);

Что такое struct pbuf * p

Сообщение отредактировал Acvarif - Jan 12 2012, 14:48
Go to the top of the page
 
+Quote Post
4 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 14)
kan35
сообщение Jan 12 2012, 15:49
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Дока на lwIP существует, она вполне полезная, по крайней мере описание API нужно там изучить.
Я советую пользоваться только под FreeRTOS в силу того, что в ней как мне кажется существенно проще работать.

Создать дескриптор и соединение TCP (или UDP - по аналогии):
Код
struct netconn * conn;
conn = netconn_new(NETCONN_TCP);
struct ip_addr addr;
addr.addr = inet_addr("193.193.165.165");
unsigned short server_port = 45321;
if (netconn_connect(conn, &addr, server_port) == ERR_OK)
...

Отправить данные
Код
netconn_write(conn, "Hello...", strlen("Hello..."), NETCONN_NOCOPY);// передача данных

Принять данные в netbuf
Код
struct netbuf * in_buf = netconn_recv(conn)
..../// сделал что нужно с данными и удалил буфер
netbuf_delete(in_buf);

Еще можно добавить что netbuf это структура, описывающая склейку некоторого количества маленьких буферов, в ней храняться указатели на предыдущий буфер и на последующий и проч, работать напрямую не удобно, да и не нужно, так как в stm памяти достаточно чтобы с помощью API вытащить из буфера данные в линейный массив:
Код
unsigned long buflen = netbuf_len(in_buf);
incoming_data = (char *)pvPortMalloc(buflen);
netbuf_copy(in_buf, incoming_data, buflen);

Здесь и везде по стеку используется куча, потому не забываем удалять выделенные области после изспользования. Все примеры на функциях из доки на lwIP.
Конечно можно перейти на нижний уровень или на верхний - с сокетами, но я рекомендую начать netconn API.

Сообщение отредактировал kan35 - Jan 12 2012, 16:01
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 13 2012, 06:43
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Спасибо. Начало проясняться.

Удалось послать строку по UDP на комп. Смутно понимаю (придется таки почитать мануал на LwIP), как стек это делает, в коде это достаточно просто.

CODE
struct udp_pcb *upcb;
struct pbuf *p;
struct ip_addr DestIPaddr;
char tdata[] = {"Test"};
char *data = tdata;

/* Create a new UDP control block */
upcb = udp_new();
/*assign destination IP address */
IP4_ADDR( &DestIPaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3 );
/* configure destination IP address and port */
udp_connect(upcb, &DestIPaddr, UDP_SERVER_PORT);
/* allocate pbuf from pool*/
p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
/* copy data to pbuf */
pbuf_take(p, (char*)data, strlen((char*)data));
/* send udp data */
udp_send(upcb, p);

После этого очевидно нужно еще разорвать соединение и освободить занятую память
Код
/* Reset the upcb */
   udp_disconnect(upcb);
/* Free the p buffer */
   pbuf_free(p);


Сообщение отредактировал Acvarif - Jan 13 2012, 06:43
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 13 2012, 07:33
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Вы продолжаете работать на уровне pcb, я же предлагаю использовать netbuf API и netconn интерфейс или socket интерфейс и будет работать не сложнее чем с сериальным портом.
Вот пример из доки в полной мере делающий то же что и ваш код
CODE
int
main()
{
struct netconn *conn;
struct netbuf *buf;
struct ip_addr addr;
char *data;
char text[] = "A static text";
int i;
/* create a new connection */
conn = netconn_new(NETCONN_UDP);
/* set up the IP address of the remote host */
addr.addr = htonl(0x0a000001);
/* connect the connection to the remote host */
netconn_connect(conn, &addr, 7000);
/* create a new netbuf */
buf = netbuf_new();
data = netbuf_alloc(buf, 10);
/* create some arbitrary data */
for(i = 0; i < 10; i++)
data[i] = i;
/* send the arbitrary data */
netconn_send(conn, buf);
/* reference the text into the netbuf */
netbuf_ref(buf, text, sizeof(text));
/* send the text */
netconn_send(conn, buf);
/* deallocate connection and netbuf */
netconn_delete(conn);
netconn_delete(buf);
}
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 13 2012, 11:39
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Цитата
Вы продолжаете работать на уровне pcb, я же предлагаю использовать netbuf API и netconn интерфейс или socket интерфейс и будет работать не сложнее чем с сериальным портом.

Нет. Просто меня пробило как передать пакет на уровне pcb (без глубокого копания).

Конечно же я попробую Ваше предложение, тем более, если это не сложнее Com.
Спасибо за пример. В доке действительно все расписано. Но...

Пытаюсь откомпилировать...Не хватает нужных #include для вызываемых функций. Попробую поискать в файлах стека где они спрятаны.

Сообщение отредактировал Acvarif - Jan 13 2012, 12:02
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 13 2012, 13:03
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Цитата(Acvarif @ Jan 13 2012, 15:39) *
Пытаюсь откомпилировать...Не хватает нужных #include для вызываемых функций. Попробую поискать в файлах стека где они спрятаны.


К проекту из LwIP подключена папка api где имеются файлы netbuf.c, api_lib.c

При компиляции выскакивает:

compiling main.c...
..\src\main.c(134): warning: #223-D: function "netconn_new" declared implicitly
..\src\main.c(134): error: #20: identifier "NETCONN_UDP" is undefined
..\src\main.c(134): error: #513: a value of type "int" cannot be assigned to an entity of type "struct netconn *"
..\src\main.c(138): warning: #223-D: function "netconn_connect" declared implicitly
..\src\main.c(146): warning: #223-D: function "netconn_send" declared implicitly
..\src\main.c(152): warning: #223-D: function "netconn_delete" declared implicitly
..\src\main.c - 2 Error(s), 4 Warning(s).

Например NETCONN_UDP находится в api.h который в свою очередь подключен к api_lib.c

Пока непонятно что не так.
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 13 2012, 14:51
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Все прояснилось. Мануал 2001 года подходит для LwIP 1.1.0, а в демках применен LwIP 1.3.2 (хотя заголовок демки именуется как STM32F2x7_ETH_LwIP_V1.1.0)
В новой версии стека нет netconn_new(NETCONN_UDP); и т. д.

Там есть struct netconn * netconn_new_with_proto_and_callback (enum netconn_type t, u8_t proto, netconn_callback callback)
Что это и с чем его едят придется разбираться. Примеров использования пока не нашел.

Сообщение отредактировал Acvarif - Jan 13 2012, 14:52
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 13 2012, 16:34
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Чтобы активировать те или иные Api кроме того, чтобы включить файлы надо настроить стек. Делается это в файле lwipopt.h
У вас должно быть так:
Код
/**
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
*/
#define LWIP_NETCONN                    1

и пока что мануал актуален на все 100

Сообщение отредактировал kan35 - Jan 13 2012, 16:37
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 13 2012, 18:58
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Спасибо. Почти получилось...
Портит картину netconn_delete(buf);
..\src\main.c(154): error: #167: argument of type "struct netbuf *" is incompatible with parameter of type "struct netconn *"
Очевидно в мануале ошибка
Нужно так
Код
netconn_delete(conn);
netbuf_delete(buf);

В понедельник проверю на железе.
Спасибо kan35
Удачного Старого Нового Года!

Сообщение отредактировал IgorKossak - Jan 14 2012, 16:56
Причина редактирования: Бездумное цитирование
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 14 2012, 13:40
Сообщение #10


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Таки не выдержал. Попытался откомпилировать весь проект. Для удобства поиска в файлах перешел с Keil на IAR (принципиально ничего не меняется) Напоролся на недопонимание в файлах api_lib.c, api_msg.c
api_lib.c - выскочила куча ошибок и предупреждений. Интуиция подсказала, что в файле не хватает
#include "lwip/api_msg.h" После компиляции количество непоняток уменьшилось но не совсем...
CODE
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 82
Error[Pe020]: identifier "SYS_SEM_NULL" is undefined \src\api\api_lib.c 86
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_lib.c 87
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_lib.c 88
Warning[Pe223]: function "tcpip_apimsg" declared implicitly \src\api\api_lib.c 118
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 151
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 177
Warning[Pe223]: function "tcpip_apimsg" declared implicitly \src\api\api_lib.c 201
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 220
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 247
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_lib.c 263
Warning[Pe223]: function "sys_arch_mbox_fetch" declared implicitly \src\api\api_lib.c 270
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_lib.c 306
Warning[Pe223]: function "sys_arch_mbox_fetch" declared implicitly \src\api\api_lib.c 339
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 375
Warning[Pe223]: function "sys_arch_mbox_fetch" declared implicitly \src\api\api_lib.c 384
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 438
Warning[Pe223]: function "TCPIP_APIMSG" declared implicitly \src\api\api_lib.c 469
Warning[Pe223]: function "tcpip_apimsg" declared implicitly \src\api\api_lib.c 488

Например Error[Pe020]: identifier "SYS_SEM_NULL" is undefined \src\api\api_lib.c 86
касается этого
Код
LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL);

Warning[Pe223]: function "tcpip_apimsg" declared implicitly \src\api\api_lib.c 118
касается этого
Код
tcpip_apimsg(&msg);


Для api_msg.c еще больше непоняток.
CODE
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 93
Error[Pe029]: expected an expression \src\api\api_msg.c 116
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 159
Error[Pe029]: expected an expression \src\api\api_msg.c 185
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 215
Error[Pe029]: expected an expression \src\api\api_msg.c 227
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 314
Error[Pe020]: identifier "SYS_SEM_NULL" is undefined \src\api\api_msg.c 319
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 323
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 376
Error[Pe029]: expected an expression \src\api\api_msg.c 388
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 482
Error[Pe020]: identifier "SYS_SEM_NULL" is undefined \src\api\api_msg.c 536
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 540
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 546
Warning[Pe550]: variable "size" was set but never used \src\api\api_msg.c 499
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 581
Error[Pe029]: expected an expression \src\api\api_msg.c 582
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 596
Error[Pe029]: expected an expression \src\api\api_msg.c 597
Error[Pe020]: identifier "SYS_SEM_NULL" is undefined \src\api\api_msg.c 605
Error[Pe020]: identifier "SYS_SEM_NULL" is undefined \src\api\api_msg.c 709
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 750
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 843
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 869
Error[Pe020]: identifier "SYS_MBOX_NULL" is undefined \src\api\api_msg.c 874
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 893
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 931
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 959
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 1097
Warning[Pe223]: function "TCPIP_APIMSG_ACK" declared implicitly \src\api\api_msg.c 1145


Пытался найти решение проблем в настройках lwipopts.h - не получилось.
В стеке еще имеется файл opt.h но как с ним работать непонятно. Файл вообще с атрибутами только для чтения.
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 14 2012, 17:05
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



opt.h - это настройки по умолчанию, их не стоит трогать, потому он read only
lwipopt.h - это файл для настройки пользователем, они имеют приоритет над настройками по умолчанию, его и крутите

Как я понимаю все эти ошибки из за того, что стек не видит FreeRTOS.
И еще, файлы sys_arch являются связкой между FreeRTOS и lwIP и тоже должны иметься в проекте.
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 14 2012, 18:17
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Понял. Спасибо. Файл нашел.
Можно ли подружить этот файл ( sys_arch.h) со стеком без FreeRTOS?
Вроде в нем есть то чего не хватает для нормальной компиляции api_lib.c, api_msg.c
Наверняка должен же как то стек (имеется ввиду netbuf API и netconn ) работать в stm32 и без какой-либо операционной системы (уровень pcb работает без ОС).
Очевидно для работы стека в режиме netbuf API и netconn без ОС нужны другие файлы api_lib.c, api_msg.c и может еще некоторые другие h файлы.

Сообщение отредактировал Acvarif - Jan 14 2012, 18:46
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 14 2012, 19:04
Сообщение #13


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Должен работать конечно, но нюансов не скажу, так как я так же как и вы взял пример от ST и кручу его под свою задачу.
И вы берите пример с ОС, как я и посоветовал в первом своем посте, грех на таком чипе без нее что либо вообще делать. Самому FreeRTOS можно конечно приладить, но без опыта можно долго биться, да и зачем когда есть пример.
Немного лирики. Отличие с ОС и без ОС в том, что без ОС надо по таймерам вызывать определенные процедуры из стека, ловить пакеты через callback-и и прочие неудобства, а когда ОС - просто крутится поток, а взаимодействие стека с вашим приложением идет через через API, которые используют сервисы ОС и в итоге интерфейс с lwIP становится совершенно элементарным.
Go to the top of the page
 
+Quote Post
Acvarif
сообщение Jan 14 2012, 19:35
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850



Понял. Спасибо. С ОС стек компилится без проблем. Попробую уровень netbuf API и netconn.
Go to the top of the page
 
+Quote Post
MK2
сообщение Jan 15 2012, 18:20
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 202
Регистрация: 30-10-10
Пользователь №: 60 535



А чем вы с компьютера посылали пакеты?
Go to the top of the page
 
+Quote Post

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

 


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


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