/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#define IPADDR0 192
#define IPADDR1 168
#define IPADDR2 1
#define IPADDR3 20
#define SEND_RETRY_MAX 10
#define SEND_RETRY_INTERVAL 2
static const struct uip_eth_addr macaddr = {
{0xC2, 0xAF, 0x51, 0x03, 0xCF, 0x46}
};
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
/*
* uIP send function wrapping the EMAC functions.
*/
static void network_device_send(void) {
int i;
BufDescriptorEntry *bdep;
for (i = 0; i < SEND_RETRY_MAX; i++) {
if ((bdep = EMACGetTransmitBuffer()) != NULL) {
uint8_t *bp = (uint8_t *)bdep->w1;
if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN)
memcpy(bp, &uip_buf[0], uip_len);
else {
memcpy(bp, &uip_buf[0], UIP_LLH_LEN + UIP_TCPIP_HLEN);
memcpy(bp + UIP_LLH_LEN + UIP_TCPIP_HLEN,
uip_appdata,
uip_len - (UIP_LLH_LEN + UIP_TCPIP_HLEN));
}
EMACTransmit(bdep, uip_len);
return;
}
chThdSleep(SEND_RETRY_INTERVAL);
}
/* Dropped... */
}
/*
* uIP receive function wrapping the EMAC function.
*/
static size_t network_device_read(void) {
size_t size = UIP_CONF_BUFFER_SIZE;
if (EMACReceive(uip_buf, &size))
return size;
return 0;
}
void clock_init(void) {}
clock_time_t clock_time( void )
{
return chSysGetTime();
}
/*
* TCP/IP periodic timer.
*/
static void PeriodicTimerHandler(eventid_t id) {
int i;
for (i = 0; i < UIP_CONNS; i++) {
uip_periodic(i);
if (uip_len > 0) {
uip_arp_out();
network_device_send();
}
}
}
/*
* ARP periodic timer.
*/
static void ARPTimerHandler(eventid_t id) {
uip_arp_timer();
(void)EMACGetLinkStatus();
}
/*
* Ethernet frame received.
*/
static void FrameReceivedHandler(eventid_t id) {
while ((uip_len = network_device_read()) > 0) {
if (BUF->type == HTONS(UIP_ETHTYPE_IP)) {
uip_arp_ipin();
uip_input();
if (uip_len > 0) {
uip_arp_out();
network_device_send();
}
}
else if (BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();
if (uip_len > 0)
network_device_send();
}
}
}
#define FRAME_RECEIVED_ID 0
#define PERIODIC_TIMER_ID 1
#define ARP_TIMER_ID 2
static const evhandler_t evhndl[] = {
FrameReceivedHandler,
PeriodicTimerHandler,
ARPTimerHandler
};
msg_t WebThread(void *p) {
EvTimer evt1, evt2;
EventListener el0, el1, el2;
uip_ipaddr_t ipaddr;
/*
* Event sources setup.
*/
chEvtRegister(&EMACFrameReceived, &el0, FRAME_RECEIVED_ID);
chEvtSend(&EMACFrameReceived); /* In case some frames are already buffered */
evtInit(&evt1, CH_FREQUENCY / 2);
evtStart(&evt1);
chEvtRegister(&evt1.et_es, &el1, PERIODIC_TIMER_ID);
evtInit(&evt2, CH_FREQUENCY * 10);
evtStart(&evt2);
chEvtRegister(&evt2.et_es, &el2, ARP_TIMER_ID);
/*
* EMAC settings.
*/
EMACSetAddress(&macaddr.addr[0]);
(void)EMACGetLinkStatus();
/*
* uIP initialization.
*/
uip_init();
uip_setethaddr(macaddr);
uip_ipaddr(ipaddr, IPADDR0, IPADDR1, IPADDR2, IPADDR3);
uip_sethostaddr(ipaddr);
httpd_init();
while (TRUE)
chEvtWait(ALL_EVENTS, evhndl);
return 0;
}