Здравствуйте!
Недавно решил попробовать сокеты BSD в составе кейловского стека (Keil uVision 4.5). Необходимо сделать SNTP клиент, который смог бы получать из сети время. Написал вот такой текст:
Код
#include "LPC23xx.h"
#include "uart.h"
#include "RTL.h"
#include "main.h"
#include <Net_Config.h>
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <h>Time server IP
// ====================
//
// <o>IP1: Address byte 1 <0-255>
// <i> Default: 192
#define IP1 192
// <o>IP2: Address byte 2 <0-255>
// <i> Default: 168
#define IP2 168
// <o>IP3: Address byte 3 <0-255>
// <i> Default: 0
#define IP3 0
// <o>IP4: Address byte 4 <0-255>
// <i> Default: 100
#define IP4 13
// </h>
//------------- <<< end of configuration section >>> -----------------------
OS_TID poolID, timerID, SNTPID;
int sock;
U64 tcp_stack[800/8];
U64 SNTP_stack[800/8];
#define MCLK 48000000 /* Master Clock 48 MHz */
#define TCLK 10 /* Timer Clock rate 10/s */
#define TCNT (MCLK/TCLK/4) /* Timer Counts */
BOOL tick;
U32 dhcp_tout;
BOOL LCDupdate;
extern LOCALM localm[]; /* Local Machine Settings */
#define MY_IP localm[NETIF_ETH].IpAdr
#define DHCP_TOUT 50 /* DHCP timeout 5 seconds */
void tcp_task (void) {
/* Main Thread of the TcpNet. This task should have */
/* the lowest priority because it is always READY. */
UART2_init(115200);
init_TcpNet();
timerID=os_tsk_create (timer_task, 0x20);
//poolID=os_tsk_create_user (tcp_task, 0, &tcp_stack, sizeof(tcp_stack));
//os_dly_wait(1000);
SNTPID=os_tsk_create_user (SNTP_task, 0x02, &SNTP_stack, sizeof(SNTP_stack));
while (1)
{
main_TcpNet();
os_tsk_pass();
}
}
/*--------------------------- timer_poll ------------------------------------*/
void timer_task (void)
{
os_itv_set (10);
while (1)
{
/* Timer tick every 100 ms */
timer_tick ();
tick = __TRUE;
os_itv_wait ();
}
}
void SNTP_task (void)
{
//static int sock;
int res;
int addrlen;
SOCKADDR_IN time_addr;
char tx_buf[50];
char rx_buf[50];
tx_buf[0]=0x23; //SNTPV4 client
send_string2("SNTP task started\r\n");
addrlen = sizeof (time_addr);
while(1)
{
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock>0)
{
time_addr.sin_port = htons(123);
time_addr.sin_family = PF_INET;
time_addr.sin_addr.s_b1 = IP1;
time_addr.sin_addr.s_b2 = IP2;
time_addr.sin_addr.s_b3 = IP3;
time_addr.sin_addr.s_b4 = IP4;
connect (sock, (SOCKADDR *)&time_addr, sizeof (time_addr));
while(1)
{
res = sendto (sock, (char *)&tx_buf, 48, 0, (SOCKADDR *)&time_addr, addrlen);
if (res <0)
{
break;
}
send_string2("Get-time request sent\r\n");
res = recv (sock, rx_buf, 48, 0);
if (res <0)
{
switch (res)
{
case SCK_EINVALID: send_string2("socket invalid\r\n"); break;
case SCK_ECLOSED: send_string2("remote host closed connection\r\n"); break;
case SCK_EWOULDBLOCK: send_string2("function would be locked\r\n"); break;
case SCK_ETIMEOUT: send_string2("Timeout\r\n"); break;
case SCK_ELOCKED: send_string2("function blocked by RTX\r\n"); break;
}
break;
}
os_dly_wait(300);
}
closesocket (sock);
os_dly_wait(300);
}
else
{
send_string2("Create socket error!\r\n");
while(1);
}
}
}
int main (void)
{
os_sys_init_user (tcp_task, 0, &tcp_stack, sizeof(tcp_stack));
}
Отправка сообщения серверу командами send() или sendto() проходит нормально - кадр передается на компьютер и там принимается без проблем.
При приеме функции recv() и recvfrom() вываливаются с ошикбой SCK_EINVALID (-2). Если закомментировать участок отправки данных, все равно получаем ту же ошибку.
Настройки Net_Config.h
Сокеты UDP 2, TCP 1. Включены сокеты BSD: BSD сокетов 1, таймаут 20с (по-умолчанию).
В чем может быть проблема?
Заранее спасибо!
P.S. Обновил до Keil 4.53 (что-то поправили в функции recv()) - не помогло.
Сообщение отредактировал stepper88 - Jun 7 2012, 08:40