#ifndef __RPP_ETH_H
#define __RPP_ETH_H
+#include <stdio.h>
+
#include "os/os.h"
#include "lwip/netif.h"
-/* this MAC address is used when user doesn't put the address to postInit function */
+/* this MAC address is used when user put NULL on the right place when calling postInit function */
#define RPP_MAC_ADDR {0x12,0x34,0x56,0x78,0x9a,0xbc}
#if STATIC_IP_ADDRESS
#define RPP_IP_ADDR 0xC0A8F701 /* 192.168.247.1 IP4_ADDR(rppip, 192,168,0,10); */
#define MACADDR_NOT_SET -3
#define PHY_LINK_DOWN -4
-#define NETIF_ADD_ERR -10 /* could be one of previous */
+#define NETIF_ADD_ERR -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
#define DHCP_MEM_ERR -11
#define DHCP_BIND_TIMEOUT -12
+#define rpp_debug_printf rpp_sci_printf
+
/**
* ETH module system startup initialization.
*
*/
int8_t rpp_eth_init();
-
/**
* ETH module application initialization.
*
* Call this method before using eth module.
- * This method blocks on autonegotiation till it's complete and creates tasks
- * for lwIP (including lwIP init) and for receiving. Sets IP address using
+ * This method waits for a while on autonegotiation till it's complete, if not completed
+ * in predefined time it continues with creating tasks for lwIP (including lwIP init),
+ * for receiving and for handling transmission buffer descriptors. Sets IP address using
* predefined static IP or DHCP. Before calling this method you must call rpp_eth_init() first.
*
* @param instNum number of EMAC instance
*/
int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray);
-//Generic API
+// Helper routines/functions for command processor and other applications
+
+/**
+ * Uses MDIO module to read link status of PHY attached to #instNum network interface
+ *
+ * @param instNum Number of network interface
+ */
+uint32_t rpp_eth_phylinkstat(uint32_t instNum);
+
+/**
+ * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
+ */
+#define MAC_BIG_LETTERS 1
+/**
+ * Fills macStr field with MAC address of given network interface instance as 'string'
+ *
+ * @note 18 bytes will be filled {2 chars per 6 mac bytes + 5 semicolons + 1 null termination}
+ *
+ * @param instNum Number of network interface
+ * @param *macStr field where null terminated string will be inserted
+ */
+void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr);
+
+/**
+ * Fills ipStr field with IP address in ip_addr_t as 'string'
+ *
+ * @note up to 16 bytes will be filled {1-3 * 4 IP fields + 3 dots + 1 null termination}
+ *
+ * @param ip ip address to be converted
+ * @param ipStr pointer to string where ip will be filled as text
+ */
+inline void rpp_eth_getIPDecimalStr(ip_addr_t ip, uint8_t *ipStr);
/**
- * Handles too short packets, preserves the integrity of the transmission,
- * calls rpp_et_send_raw()
+ * Fills ip.addr with converted ipstr. Checks for correct format of IP string
+ * x.x.x.x where x = [0..9]. When FAILURE is returned struct ip was not modified.
+ *
+ * @param ip struct to be filled
+ * @param ipstr string to be converted
+ *
+ * @return SUCCESS when succesfully converted
+ * FAILURE when wrong format of IP string
+ */
+err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr);
+
+/**
+ * Returns struct describing network interface
+ *
+ * @param instNum instance number of network interface
+ *
+ * @return pointer to struct netif
+ */
+struct netif *rpp_eth_get_netif(uint32_t instNum);
+
+/**
+ * Adjusts packet (pbuf) length and send it within critical section
+ * using rpp_eth_send_raw()
*
* @param netif lwIP network interface describing struct
* @param p buffer for data to be sent
* Receives raw data and sends them upward to lwIP stack.
* Handles rx emac descriptors.
*
+ * @note when using OS tasks (!NO_SYS) this function is used as
+ * task, otherwise (NO_SYS) this is called from RX ISR.
+ *
* @param arg netif
*/
void rpp_eth_recv_raw(void *arg);
#define MAX_TRANSFER_UNIT 1500 /* take in account oversized frames */
#define PBUF_LEN_MAX MAX_TRANSFER_UNIT
-#define MAX_RX_PBUF_ALLOC 15 /* no need to limit it here -> better to do it in lwipopts.h */
+#define MAX_RX_PBUF_ALLOC 15 /* no need to limit it here -> it's better to do it in lwipopts.h */
#define MIN_PKT_LEN 60
/* Define those to better describe the network interface. */
static boolean_t initialized = FALSE, postInitialized = FALSE;
-/******************************************************************************************************/
+/**********************************************testing functions**********************************************/
-uint32_t rpp_eth_linkstat(uint32_t instNum)
+uint32_t rpp_eth_phylinkstat(uint32_t instNum)
{
struct hdkif *hdkif = &hdkif_data[instNum];
return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
}
-/* prints MAC address assigned to EMAC instance reffered by instNum */
-void rpp_eth_print_macAddr(uint32_t instNum)
+#define BYTE_BUFF_SIZE 2
+#define OFFSET_MAC_LETTERS (MAC_BIG_LETTERS ? 'A' : 'a')
+/* puts string of MAC address assigned to EMAC instance reffered by instNum into *mac */
+void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr)
{
- u32_t temp;
+ uint8_t index, outindex = 0;
+ char buff[BYTE_BUFF_SIZE];
struct hdkif *hdkif = &hdkif_data[instNum];
- rpp_sci_printf((const char *) "MAC address: ");
- for(temp = 0; temp < (MAC_ADDR_LEN-1); temp++) {
- rpp_sci_printf((const char *) "%x:", hdkif->mac_addr[(MAC_ADDR_LEN - 1) - temp]);
+ for(index = 0; index < MAC_ADDR_LEN; index++) {
+ if(index)macStr[outindex++] = ':';
+ buff[0] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] >> 4);
+ buff[1] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] & 0xf);
+ macStr[outindex++] = (buff[0]<10) ? (buff[0] + '0') : (buff[0] - '\012' + OFFSET_MAC_LETTERS);
+ macStr[outindex++] = (buff[1]<10) ? (buff[1] + '0') : (buff[1] - '\012' + OFFSET_MAC_LETTERS);
}
- rpp_sci_printf((const char *) "%x\r\n", hdkif->mac_addr[0]);
+ macStr[outindex] = '\0';
}
-/* prints an IP address, where each byte is one of 4 fields in IPv4 IP address format */
-void rpp_eth_printIPDecimal(ip_addr_t ip)
+/* prepares an IP address to ipStr in form of null terminated string; each byte of ip is converted to one of 4 field in IPv4 IP address format 0xAABBCCDD -> "aaa.bbb.ccc.ddd" */
+inline void rpp_eth_getIPDecimalStr(ip_addr_t ip, uint8_t *ipStr)
{
- rpp_sci_printf((const char *) "%d.%d.%d.%d",(ip.addr >> 24),((ip.addr >> 16) & 0xff),((ip.addr >> 8) & 0xff),(ip.addr%256));
+ snprintf((char *)ipStr, 16, "%d.%d.%d.%d",(ip.addr >> 24),((ip.addr >> 16) & 0xff),((ip.addr >> 8) & 0xff),(ip.addr & 0xff));
}
/* @param ip will be filled accroding to content of ipstr */
err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr)
{
- uint8_t index, tmp = 0, dots = 0;
+ uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
uint32_t ipaddr = 0;
-/* TODO: checking chars for weird combinations,... */
- for(index = 0; ipstr[index] != 0; index++)
+ for(charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.' ; charProccessed = ipstr[++index])
{
- if(ipstr[index] != '.' && ipstr[index] != 0)
- {
- tmp = tmp*10 + ipstr[index] - '0';
- }
- else
+ if(charProccessed == '.')
{
+ if(++dotindex == index)
+ {
+ dots = 0;
+ break;
+ }
+ dotindex = index;
+
ipaddr = (ipaddr << 8) + tmp;
- if(dots == 3)break;
+
dots++;
+ if(dots > 3)break;
+
tmp = 0;
+ fldEdit = FALSE;
+ }
+ else
+ {
+ fldEdit = TRUE;
+ tmp = tmp*10 + charProccessed - '0';
}
}
- if(dots != 3)
+ if(dots != 3 || !fldEdit)
{
- ip->addr = 0;
- return -1;
+ /* if unsuccesful, don't modify previous content */
+ return FAILURE;
}
ipaddr = (ipaddr << 8) + tmp;
ip->addr = ipaddr;
- return ERR_OK;
-}
-
-/* prints address, netmask and gateway in hex*/
-void rpp_eth_print_IPAddr(uint32_t instNum)
-{
- struct netif *netif = &hdkNetIF[instNum];
- rpp_sci_printf((const char *) "address: %x\r\nnetmask: %x\r\ngateway: %x\r\n",netif->ip_addr,netif->netmask,netif->gw);
+ return SUCCESS;
}
struct netif *rpp_eth_get_netif(uint32_t instNum)
return &hdkNetIF[instNum];
}
-/******************************************************************************************************/
+/********************************************** forward declares **********************************************/
-/* forward declare */
+/*
+ * interface initializes
+ */
err_t rpp_eth_lwip_init(struct netif *netif);
-/**
+/*
* Initializes hw such as PHY, MDIO, EMAC, EMAC control module
*
* @return SUCCESS if initialization successful.\n
*/
err_t rpp_eth_hw_init(struct hdkif *hdkif);
-/**
+/*
* Initializes hw, after lwIP was initialized and
* OS was initialized in case OS is used.
*/
err_t rpp_eth_hw_init_postInit(struct netif *netif);
-/**
+/********************************************** utility functions **********************************************/
+
+/*
* Function to set the MAC address to the interface
* @param inst_num the instance number
*
hdkif->mac_addr[temp] = mac_addr[(MAC_ADDR_LEN - 1) - temp];
}
#ifdef DEBUG
- //rpp_eth_print_macAddr(inst_num);
+ uint8_t macStr[18];
+ rpp_eth_get_macAddrStr(inst_num, uint8_t *macStr);
+ rpp_debug_printf((const char *) "Setting MAC... %s\r\n", macStr);
#endif
}
}
}
-/******************************************************************************************************/
+/********************************************** initializing functions **********************************************/
int8_t rpp_eth_init()
{
int8_t retVal = SUCCESS;
struct netif *netif = &hdkNetIF[instNum];
u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
+#ifdef DEBUG
+ uint8_t ipString[16];
+#endif
/* ----- lwIP stuff ----- */
struct ip_addr ip_addr;
/* ----- end - freeRTOS ----- */
#endif /* !NO_SYS */
- if(rpp_eth_linkstat(hdkif->inst_num))
+ if(rpp_eth_phylinkstat(hdkif->inst_num))
{
- rpp_sci_printf((const char *)"cable connected\r\n");
+ rpp_debug_printf((const char *)"cable connected\r\n");
#if STATIC_IP_ADDRESS
netif_set_up(netif);
#elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
if(dhcp_start(netif) != ERR_OK)
{
#ifdef DEBUG
- rpp_sci_printf((const char *) "dhcp mem err\r\n");
+ rpp_debug_printf((const char *) "dhcp mem err\r\n");
#endif
return DHCP_MEM_ERR;
}
#ifdef DEBUG
- rpp_sci_printf((const char *) "binding DHCP\r");
+ rpp_debug_printf((const char *) "binding DHCP\r");
#endif
while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--));
#ifdef DEBUG
if(!dhcpBindWait)
- rpp_sci_printf((const char *) "dhcp binding timeout...\r\n");
+ rpp_debug_printf((const char *) "dhcp binding timeout...\r\n");
#endif
#else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
autoip_start(netif);
#endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
#ifdef DEBUG
- rpp_sci_printf((const char *) "Address: ");
- rpp_eth_printIPDecimal(netif->ip_addr);
- rpp_sci_printf((const char *) "\r\nNetmask: ");
- rpp_eth_printIPDecimal(netif->netmask);
- rpp_sci_printf((const char *) "\r\nGateway: ");
- rpp_eth_printIPDecimal(netif->gw);
- rpp_sci_printf((const char *) "\r\n");
- /* rpp_eth_print_IPAddr(instNum); */
+ rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
+ rpp_debug_printf((const char *) "Address: %s\r\n", ipString);
+ rpp_eth_getIPDecimalStr(netif->netmask, ipString);
+ rpp_debug_printf((const char *) "Netmask: %s\r\n", ipString);
+ rpp_eth_getIPDecimalStr(netif->gw, ipString);
+ rpp_debug_printf((const char *) "Gateway: %s\r\n", ipString);
#endif
}
else
{
- rpp_sci_printf((const char *)"cable not connected\r\n");
+ rpp_debug_printf((const char *)"cable not connected\r\n");
retVal = PHY_LINK_DOWN;
}
/* ----- end - lwIP stuff ----- */
err_t rpp_eth_hw_init(struct hdkif *hdkif)
{
/* FIXME: express initial index using defines */
- uint8_t index = 80; /* initially used to hw reset of PHY connected to GIO pin 'rpp project only' */
+ uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin 'rpp project only'; 1us - according to PHY specification. */
uint16_t regContent;
uint32_t physAlive;
if(!physAlive)
{
#ifdef DEBUG
- rpp_sci_printf((const char *) "no phy found, phys: %d\r\n", physAlive);
+ rpp_debug_printf((const char *) "no phy found, phys: %d\r\n", physAlive);
#endif
return NO_PHY_ALIVE;
}
#else
#ifdef DEBUG
- rpp_sci_printf((const char *) "default phy not alive\r\n");
+ rpp_debug_printf((const char *) "default phy not alive\r\n");
#endif
return DFLT_PHY_NOT_ALIVE;
#endif
txch = &(hdkif->txch);
#ifdef DEBUG
- rpp_sci_printf((const char *) "autoneg started - check on cable if it's connected!\r\n");
+ rpp_debug_printf((const char *) "autoneg started - check on cable if it's connected!\r\n");
#endif
last_rxbd->next = NULL;
#ifdef DEBUG
- rpp_sci_printf((const char *) "last_rxbd: 0x%x\r\n",last_rxbd);
+ rpp_debug_printf((const char *) "last_rxbd: 0x%x\r\n",last_rxbd);
#endif
rxch->active_tail = last_rxbd;
num_bd = (((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1);
#ifdef DEBUG
- rpp_sci_printf((const char *) "num of filled bds: %d\r\nnum of pbufs: %d\r\n", num_bd, pbuf_cnt);
+ rpp_debug_printf((const char *) "num of filled bds: %d\r\nnum of pbufs: %d\r\n", num_bd, pbuf_cnt);
#endif
#ifdef DEBUG
if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
- rpp_sci_printf((const char *) "aneg finished \r\n");
+ rpp_debug_printf((const char *) "aneg finished \r\n");
else
- rpp_sci_printf((const char *) "aneg timeout \r\n");
+ rpp_debug_printf((const char *) "aneg timeout \r\n");
#endif
/* check if phy link is up - it is when autoneg was completed succesfully */
/* if(!PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 3))
{
#ifdef DEBUG
- rpp_sci_printf((const char *) "Link is down\r\n");
+ rpp_debug_printf((const char *) "Link is down\r\n");
#endif
return PHY_LINK_DOWN;
}*/
EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
} else {
#ifdef DEBUG
- rpp_sci_printf((const char *) "Unknown duplex mode\r\n");
+ rpp_debug_printf((const char *) "Unknown duplex mode\r\n");
#endif
return UNKN_DUPLEX_MODE;
}
return SUCCESS;
}
+/********************************************** send and receive functions / ISRs **********************************************/
+
err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
{
err_t retVal = SUCCESS;