Использую плату STM32F446RE, ENC28J60, LWIP, FreeRTOS. Когда отправляю запрос к удаленному серверу с помощью httpc_get_file_dns, то не получаю ответа. Но стоит исковеркать запрос, то получаю ответ от cloudflare о неправильном запросе. IP по DHCP получается корректно, IP сервера по DNS также получается.
Пока тестирую на первом попавшемся APi времени.
Задача:
void Poll_Task() {
lwip_init();
ip4_addr_t ipaddr, netmask, gw;
IP4_ADDR(&ipaddr, 0, 0, 0, 0);
IP4_ADDR(&netmask, 0, 0, 0, 0);
IP4_ADDR(&gw, 0, 0, 0, 0);
netif_add(&netif_data, &ipaddr, &netmask, &gw, NULL, enc28j60_netif_init, ethernet_input);
netif_set_default(&netif_data);
netif_set_up(&netif_data);
dhcp_start(&netif_data);
//Настройка DNS серверов
ip_addr_t dnsserver;
IP4_ADDR(&dnsserver, 8, 8, 8, 8); // Google DNS
dns_setserver(0, &dnsserver);
IP4_ADDR(&dnsserver, 8, 8, 4, 4); // Google DNS
dns_setserver(1, &dnsserver);
for (;;) {
for(uint8_t i = 0; i < 60; i++) {
sys_check_timeouts(); // Обработка таймеров LwIP
enc28j60_handle_received_packets(&netif_data); // Обработка входящих пакетов
enc28j60_check_link_status(&netif_data); // Проверка статуса соединения
vTaskDelay(pdMS_TO_TICKS(250)); // Добавим задержку, чтобы избежать излишней загрузки процессора
}
http_get_request();
}
}
Запрос и обработка ответа
#include <net.h>
extern struct netif netif_data;
extern UART_HandleTypeDef huart2;
httpc_state_t *connection = NULL;
// Функция для обработки результатов HTTP запроса
err_t httpc_result_callback(void *arg, httpc_result_t result, u32_t response_len, void *userdata) {
char result_msg[50];
snprintf(result_msg, sizeof(result_msg), "HTTP result: %d, len: %lu\r\n", result, response_len);
HAL_UART_Transmit(&huart2, (uint8_t*)result_msg, strlen(result_msg), 0x1000);
return ERR_OK;
}
// Функция для обработки полученных заголовков HTTP
err_t httpc_headers_callback(httpc_state_t *connection, void *arg, struct pbuf *hdr, u16_t hdr_len, u8_t flags) {
char headers_msg[100];
snprintf(headers_msg, sizeof(headers_msg), "HTTP headers received: %.*s\r\n", hdr_len, (char*)hdr->payload);
HAL_UART_Transmit(&huart2, (uint8_t*)headers_msg, strlen(headers_msg), 0x1000);
pbuf_free(hdr);
return ERR_OK;
}
// Функция для обработки полученных данных HTTP
err_t httpc_body_callback(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err) {
if (p != NULL) {
char body_msg[500];
snprintf(body_msg, sizeof(body_msg), "HTTP body received: %.*s\r\n", p->tot_len, (char*)p->payload);
HAL_UART_Transmit(&huart2, (uint8_t*)body_msg, strlen(body_msg), 0x1000);
pbuf_free(p);
} else {
HAL_UART_Transmit(&huart2, "HTTP body received: null\r\n", 26, 0x1000);
}
return ERR_OK;
}
void http_get_request() {
const char* server_name = "worldtimeapi.org";
const char* request_url = "/api/timezone/America/Argentina/Salta";
u16_t port = 80;
httpc_connection_t settings;
memset(&settings, 0, sizeof(settings));
//settings.result_fn = httpc_result_callback;
//settings.headers_done_fn = httpc_headers_callback;
err_t result = httpc_get_file_dns(server_name, port, request_url, &settings, httpc_body_callback, NULL, &connection);
if (result != ERR_OK) {
char error_msg[50];
snprintf(error_msg, sizeof(error_msg), "HTTP request error: %d\r\n", result);
HAL_UART_Transmit(&huart2, (uint8_t*)error_msg, strlen(error_msg), 0x1000);
} else {
HAL_UART_Transmit(&huart2, "HTTP request sent\r\n", 19, 0x1000);
}
}
Реализация функций для lwip
#include "enc28j60_netif.h"
#include "enc28j60.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include <stm32f4xx_hal.h>
extern UART_HandleTypeDef huart2;
err_t enc28j60_netif_init(struct netif *netif) {
uint8_t mac_address[6] = {0x00, 0x26, 0x62, 0x01, 0x02, 0x03};
netif->hwaddr_len = ETHARP_HWADDR_LEN;
memcpy(netif->hwaddr, mac_address, ETHARP_HWADDR_LEN);
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
netif->linkoutput = enc28j60_link_output;
netif->output = etharp_output;
enc28j60_init(mac_address);
return ERR_OK;
}
err_t enc28j60_link_output(struct netif *netif, struct pbuf *p) {
struct pbuf *q;
uint8_t buffer[1514]; // максимальный размер Ethernet-фрейма
int len = 0;
for (q = p; q != NULL; q = q->next) {
memcpy(buffer + len, q->payload, q->len);
len += q->len;
if (len > sizeof(buffer)) break; // предотвращаем переполнение буфера
}
enc28j60_send_packet(buffer, len);
return ERR_OK;
}
void enc28j60_handle_received_packets(struct netif *netif) {
uint8_t buf[1514];
uint16_t len;
len = enc28j60_recv_packet(buf, sizeof(buf));
if (len > 0) {
struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
pbuf_take(p, buf, len);
if (netif->input(p, netif) != ERR_OK) {
pbuf_free(p);
}
}
}
}
void enc28j60_check_link_status(struct netif *netif) {
uint16_t phstat1 = enc28j60_read_phy(PHSTAT1);
if (phstat1 & PHSTAT1_LLSTAT) {
if (!netif_is_link_up(netif)) {
netif_set_link_up(netif);
dhcp_start(netif); // Запустить DHCP, если ссылка только что поднялась
}
} else {
if (netif_is_link_up(netif)) {
netif_set_link_down(netif);
dhcp_release(netif); // Освободить DHCP
dhcp_stop(netif); // Остановить DHCP, если ссылка опущена
}
}
}