Перейти к содержанию
    

А кто заставляет посылать широковещательные? Можно MAC адрес приёмника забить прямо в пакет. Для сдачи задания вполне достаточно.

Вы предлагали UDP. А там кроме MAC вообще-то есть и IP-адреса если что. Какие туда адреса забивать прикажете если ARP не реализован?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы предлагали UDP. А там кроме MAC вообще-то есть и IP-адреса если что. Какие туда адреса забивать прикажете если ARP не реализован?

Мне кажется можно статично вбить ip-адреса железки (задать самому любой свободный), и адрес приёмника. Нужно будет считать контрольные суммы. Но я не уверен за результат, т.к. никогда так не делал, и не стал бы советовать кому-либо делать. Хотя для диплома - пойдёт. Но ещё раз повторюсь: диплом довольно сложен. Преподаватель обязан консультировать студента. Но я думаю, что преподаватель не очень компетентен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Преподаватель обязан консультировать студента. Но я думаю, что преподаватель не очень компетентен.

Да судя по формулировке задачи я бы сказал, что преподаватель вообще не копенгаген :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется можно статично вбить ip-адреса железки (задать самому любой свободный), и адрес приёмника.

Работать будет, если в одной подсети. Проверено.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Работать будет, если в одной подсети. Проверено.

Ну в общем для диплома действительно пойдёт. Но для реального проекта - только с большим количеством ограничений)))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы предлагали UDP. А там кроме MAC вообще-то есть и IP-адреса если что. Какие туда адреса забивать прикажете если ARP не реализован?

Так же, как и MAC - руками (статически). И даже работать будет. :rolleyes:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В указанном примере как раз таки MAC и ip адреса вбиваются вручную, все хидеры lwip проставляет автоматически, все что остается это засунуть данные в payload.

По советам jcxz решил, что надо добавлять в проект и RTOS.

Из той информации, которую изучил на данный момент, имею следующее представление:

1. Создаю 2 задачи. В первой провожу инициализацию АЦП и в бесконечном цикле отправляю запрос на единичное преобразование, записывая результат в соответствующий элемент структуры и ставя её в очередь.

Примерный код:

// Добавляю глобальную переменную для очереди //
osMailQId strout_Queue

// Указываю размер очереди //
#define MAIL_SIZE (uint32_t) 1 // Насколько я понимаю, чтобы гарантированно передать по ethernet значение преобразования, в очереди должен быть всего 1 элемент, соответственно если она заполнена, то первая задача находится в блокированном состоянии

// Задаю структуру с данными //
typedef data_t {
   int32_t temperature;
   uint8_t time;
   uint8_t date;
} data;

// Создаю задачу RTOS //
osThreadDef(ADC, StartTaskADC, osPriorityNormal, 0, 128);
ADCHandle = osThreadCreate(osThread(ADC), NULL);

// Создаю очередь //
osMailQDef(stroutqueue, MAIL_SIZE, data;
strout_Queue = osMailCreate(osMailQ(stroutqueue), NULL);

// Создаю функцию первой задачи //
void StartTaskADC(void const * argument)
{
  /* USER CODE BEGIN StartTaskADC */
  struct_out *qstruct; // добавляю переменную типа передаваемой в очереди структуры
  ADC_Init; // выполняю инициализацию АЦП (отправляю набор команд по SPI, использую функцию HAL_SPI_Transmit, можно ли взять её или для таких применений нужно с DMA каким-нибудь?)
  /* Infinite loop */
  for(;;)
  {
    qstruct = osMailAlloc(strout_Queue, osWaitForever); // выделяю память под очередь
    qstruct->temperature = ADC_ReadValue; // записываю в элемент структуры temperature полученное значение из АЦП (посылаю команду единичного преобразования через HAL_SPI_Transmit, аналогичный вопрос)
    qstruct->time = 1 // записываю в элемент структуры time рандомное значение (пока не важно)
    qstruct->date = 2 // записываю в элемент структуры date рандомное значение (пока не важно)
    osMailPut(strout_Queue, qstruct); // отправляю структуру в очередь
    osDelay(1);
  }
  /* USER CODE END StartTaskADC */
}

 

2. Создаю вторую задачу, которая будет инициализировать UDP, получать измеренное значение температуры из очереди и отправлять его.

// Создаю глобальные переменные структур, требующихся для передачи по ethernet //
extern struct netif gnetif;
static struct udp_pcb *udp_Pcb1_p;

// Создаю задачу RTOS //
osThreadDef(ETH, StartTaskETH, osPriorityNormal, 0, 128);
ETHHandle = osThreadCreate(osThread(ETH), NULL);

// Создаю функцию второй задачи //
void StartTaskETH(void const * argument)
{
  /* USER CODE BEGIN StartTaskETH */
  osEvent event; // добавляю переменную типа структуры состояния очереди
  struct_out *qstruct; // добавляю переменную типа передаваемой в очереди структуры
  UDP_Init; // выполняю инициализацию UDP (в ней создается новое подключение UDP (udp_new), вручную записывается mac и ip адрес компа, биндится соединение (udp_bind) и проверяется на наличие ошибок)
  /* Infinite loop */
  for(;;)
  {
    static const char packet[]; // создаю переменную для данных, которые буду класть в payload
    event = osMailGet(strout_Queue, osWaitForever); // забираю данные из очереди
    if (event.status == osEventMail) // проверяю состояние очереди
    qstruct = event.value.p; // присваиваю переменной типа структуры очереди указатель на элемент очереди
    packet[] = qstruct->temperature, qstruct->time, qstruct->date; // записываю полученные данные в переменную для payload
    SendPacket; // вызываю функцию отправки udp (здесь указывается ip адрес клиента, создается буффер для передачи по eth, в который заносим вышеуказанный packet[], заносим все это в payload и отправляем (udp_sendto)
    ethernetif_input(&gnetif); // вписываю стандартный код для обеспечения постоянной работы стека
    sys_check_timeouts; // продолжение... (говорят, что эти 2 строки можно заменить MX_LWIP_Process() тогда и extern struct netif gnetif не нужно, но пока попробую запуститься так)
    osDelay(1);
  }
  /* USER CODE END StartTaskETH */
}

 

Где-то что-то упустил или вообще все кардинально неправильно?))

Изменено пользователем remixx

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы рекомендовал не использовать ось. Я не знаю ваши строки, но вы можете закопаться и не успеть. ОС - это не просто многозадачность, это ещё и особый подход к проектированию ПО. Например, передача данных между процессами, обработка прерываний и т.п. Если у вас, конечно, есть опыт работы с операционными системами, тогда другой вопрос)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы рекомендовал не использовать ось. Я не знаю ваши строки, но вы можете закопаться и не успеть. ОС - это не просто многозадачность, это ещё и особый подход к проектированию ПО. Например, передача данных между процессами, обработка прерываний и т.п. Если у вас, конечно, есть опыт работы с операционными системами, тогда другой вопрос)

на крайняк сделаю с "тупыми" задержками :biggrin:

посмотрю еще сегодня ISR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По советам jcxz решил, что надо добавлять в проект и RTOS.

...

osDelay(1);

...

osDelay(1);

...

Где-то что-то упустил или вообще все кардинально неправильно?))

А что кардинально изменилось? Точно так же всё на задержках сделали. :laughing:

"Использовать ОС" - это не просто рассовать функции по задачам. Это в первую очередь означает, что работа должна производиться event-driven.

Т.е. - Ваши задачи должны не всё время долбить что-то (и зачем тогда вообще многозадачность?), а должны обрабатывать события.

Т.е. - в задаче АЦП дали старт преобразования и после этого задача должна ждать завершения преобразования, после чего считать данные, обработать их, и запустить следующее преобразование. Ждать она должна, ожидая готовности какого-либо элемента синхронизации ОС (мэйлбокса, семафора и т.п.). Этот мэйлбокс переводиться в сигнальное состояние может например из ISR завершения преобразования АЦП (а лучше конечно из ISR завершения DMA-пересылки блока данных АЦП->ОЗУ).

То же самое и с задачей отправки данных в ETHERNET.

 

Если у Вас задачи всё время что-то долбят, то тут никакой многозадачности нет, одна фикция, пыль в глаза.

Наберите в гугле "event-driven programming".

В упрощённом виде работа с АЦП должна выглядеть так:

void AdcReadyIsr()
{
 AdcConfirm();
 OSMboxPost(mboxAdcReady);
}
void AdcTask()
{
 AdcInit();
 ClearAndEnableIrqAdcReady();
 while (1) {
AdcStart();
OSMboxPend(mboxAdcReady);
DataQueueWrite(AdcRead());
PingEthernetSendTask();
 }
}

Это если время преобразования АЦП == необходимому периоду измерений (или можно так сконфигурить АЦП).

Если нет, то чуть сложнее (с использованием таймера):

void AdcReadyIsr()
{
 AdcConfirm();
 OSMboxPost(mboxAdcReady);
}
void TimerPeriodicIsr()
{
 TimerConfirm();
 OSMboxPost(mboxTimerPeriodic);
}
void AdcTask()
{
 AdcInit();
 TimerInit(DESIRED_FREQUENCY);
 ClearAndEnableIrqAdcReady();
 ClearAndEnableIrqTimerPeriodic();
 while (1) {
OSMboxPend(mboxTimerPeriodic);
AdcStart();
OSMboxPend(mboxAdcReady);
DataQueueWrite(AdcRead());
PingEthernetSendTask();
 }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В рбщем поговорил с преподавателем, решили т.к. времени мало организовать всю работу на таймерах/счетчиках. Дальше уже буду сам разбираться :laughing:

Но вот на деле уже 2 дня так и не могу пропинговать плату)

В настройках LWIP пробую забивать как статический ip так и выставлять DHCP. Реакции 0.

Варианта 2: либо я что-то неправильно подключил (схему приложил)

post-93818-1527007345_thumb.jpg

либо подозрение упало на PHYADR, в дш написано что по дефолту он 1, собственно 1 в настройках LWIP я и выставляю, но у меня вывод PHYAD0 вообще не подключен, а 1-4 включены т.к. это RXD. Получается у меня PHY адрес 30 или все таки дефолтный 1?

post-93818-1527007349_thumb.jpg

Изменено пользователем remixx

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но вот на деле уже 2 дня так и не могу пропинговать плату)

ИМХО, не тем путём вы идёте :rolleyes: У вас может не работать канальный уровень, а вы ждёте пинга. Для начала - увас фиттер (ksz8721) ответила? Т.е. вы можете прочитать из её регистров её ID-номер? Если нет, или он не совпадает с даташитовским, то дальше вообще нет смысла ничего со стеком делать, кроме как решать проблему драйвера фиттера. Если id читатете. То следующий вопрос. У вас wireshark видит исходящие пакеты с платы? Любые. А плата принимает пакеты на канальном уровне? Когда заработает канальный уровень. вам нужно подключить стек. Как это делается, читатйте в документации. В том же lwip, я уже плохо помню, но надо поправить шаблон файла ethernetif.c под свои драйвера. После этого оно у меня сразу заработало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...