Ethernet Shield code

This commit is contained in:
Andreas Mieke 2018-04-03 22:50:13 +02:00
parent 496209fb46
commit f3d70e65a8
7 changed files with 1158 additions and 2 deletions

115
Mieke/SW/ETH/main.c Normal file
View file

@ -0,0 +1,115 @@
/*
Ethernet shield test program
Copyright (C) 2018 Andreas Mieke
This program 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.
This program 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 <https://www.gnu.org/licenses/>.
*/
#include "stm32f10x.h"
#include "stm32f10x_usart.h" // Keil::Device:StdPeriph Drivers:USART
#include "w5100.h"
#include "socket.h"
#include "string.h"
#define BUFFLEN 256
// Socket (TCP) with ID 1
SOCKET tcp = 1;
uint8_t buffer[BUFFLEN] = {0};
uint8_t len = 0;
void USART_SendString(USART_TypeDef *USARTx, uint8_t *str)
{
// Send a string character by character over UART
while(*str) {
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
USART_SendData(USARTx, *str++);
}
}
int main() {
// Enable USART 1 and GPIOA clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// Create gpio strct and set default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PA9 to alternate function push pull (TxD)
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA, &gpio);
// Set PA10 to input floating (RxD)
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &gpio);
// Set up USART1
USART_InitTypeDef usart;
USART_StructInit(&usart);
USART_Init(USART1, &usart);
// Set up USART1 clocks
USART_ClockInitTypeDef usartclock;
USART_ClockStructInit(&usartclock);
USART_ClockInit(USART1, &usartclock);
// Enable USART1
USART_Cmd(USART1, ENABLE);
// Initzialize Ethernet module
ETH_init();
// Set gateway IP
uint8_t gid[4] = {192, 168, 10, 1};
// Set subnet mask
uint8_t sma[4] = {255, 255, 255, 0};
// Set MAC address (unused testing address space)
uint8_t mac[6] = {0x1E, 0x8E, 0xA8, 0x88, 0x1C, 0xAA};
// Set source IP (IP of the Ethernet module)
uint8_t sip[4] = {192, 168, 10, 2};
// Transmit all these values to the module
ETH_set_gateway_IP(gid);
ETH_set_subnet_mask(sma);
ETH_set_mac(mac);
ETH_set_IP(sip);
// Try to create a TCP socket on port 80 as long as it does not work
do {
ETH_socket(tcp, ETH_SMR_TCP, 80, 0);
} while (ETH_socket_status(tcp) != ETH_SSR_INIT);
// Wait for the socket to finish creating
while(!ETH_listen(tcp));
// Endless loop
do {
// Wait for data to be available
while(ETH_recv_available(tcp) == 0);
// Receive data
buffer[ETH_recv(tcp, buffer, BUFFLEN)] = 0;
// Send data to USART
USART_SendString(USART1, buffer);
// Send string over tcp
ETH_send(tcp, "Hallo, Welt!", 12);
} while (1);
}

391
Mieke/SW/ETH/socket.c Normal file
View file

@ -0,0 +1,391 @@
/*
Ethernet shield test program
Copyright (C) 2018 Andreas Mieke
Copyright (C) 2010 Arduino LLC
This program 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.
This program 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 <https://www.gnu.org/licenses/>.
*/
#include "socket.h"
// Check if address is a net addres 0.0.0.0
#define is_net_addr(addr) ((addr[0] == 0x00) && \
(addr[1] == 0x00) && \
(addr[2] == 0x00) && \
(addr[3] == 0x00))
// Check if address is broadcast address 255.255.255.255
#define is_broadcast_addr(addr) ((addr[0] == 0xFF) && \
(addr[1] == 0xFF) && \
(addr[2] == 0xFF) && \
(addr[3] == 0xFF))
// Check if port is valid (not 0)
#define is_valid_port(port) (port != 0x00)
static uint16_t local_port;
uint8_t ETH_socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
{
// Check if protocol is supported
if ((protocol == ETH_SMR_TCP) || (protocol == ETH_SMR_UDP) || (protocol == ETH_SMR_IPRAW) || (protocol == ETH_SMR_MACRAW) || (protocol == ETH_SMR_PPPoE))
{
// Close socket, if open
ETH_close(s);
// Set the mode register to the protocol, plus eventual flags
ETH_writeSnMR(s, protocol | flag);
if (port != 0) {
// If port is not 0 (0 on client mode) write port to the port register
ETH_writeSnPORT(s, port);
}
else {
// Write a random port to the port register (for client mode)
local_port++;
ETH_writeSnPORT(s, local_port);
}
// Execute the open socket command
ETH_exec_socket_cmd(s, ETH_SCR_OPEN);
return 1;
}
return 0;
}
uint8_t ETH_socket_status(SOCKET s)
{
// Read the status register and return it
uint8_t tmp = ETH_readSnSR(s);
return tmp;
}
void ETH_close(SOCKET s)
{
// Execute close socket and disable interrupts
ETH_exec_socket_cmd(s, ETH_SCR_CLOSE);
ETH_writeSnIR(s, 0xFF);
}
uint8_t ETH_connect(SOCKET s, uint8_t * addr, uint16_t port)
{
// Check if port and address is valid
if (is_net_addr(addr) || is_broadcast_addr(addr) || !is_valid_port(port))
return 0;
// Write IP to destination register
ETH_writeSnDIPR(s, addr);
// Write port to destination register
ETH_writeSnDPORT(s, port);
// Execute connect
ETH_exec_socket_cmd(s, ETH_SCR_CONNECT);
return 1;
}
void ETH_disconnect(SOCKET s)
{
// Execute disconnect
ETH_exec_socket_cmd(s, ETH_SCR_DISCON);
}
uint8_t ETH_listen(SOCKET s)
{
// If state is not initzialized, return
if (ETH_readSnSR(s) != ETH_SSR_INIT) {
return 0;
}
// Execute the listen command
ETH_exec_socket_cmd(s, ETH_SCR_LISTEN);
return 1;
}
uint16_t ETH_send(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status=0;
uint16_t ret=0;
uint16_t freesize=0;
// If data is bigger then Tx memory, split it
if (len > ETH_SSIZE)
ret = ETH_SSIZE;
else
ret = len;
do
{
// Write data to Tx memory
freesize = ETH_get_TX_free_size(s);
status = ETH_readSnSR(s);
if ((status != ETH_SSR_ESTABLISHED) && (status != ETH_SSR_CLOSE_WAIT))
{
ret = 0;
break;
}
}
while (freesize < ret);
// Start data processing and execute send command
ETH_send_data_processing(s, (uint8_t *)buf, ret);
ETH_exec_socket_cmd(s, ETH_SCR_SEND);
// Check interrupt if everything is okay
while ((ETH_readSnIR(s) & ETH_SIR_SEND_OK) != ETH_SIR_SEND_OK )
{
// If socket is closed set the state locally right
if (ETH_readSnSR(s) == ETH_SSR_CLOSED )
{
ETH_close(s);
return 0;
}
}
// Mark interrupt as handled
ETH_writeSnIR(s, ETH_SIR_SEND_OK);
return ret;
}
int16_t ETH_recv(SOCKET s, uint8_t * buf, int16_t len)
{
// Check remaining size
int16_t ret = ETH_get_RX_received_size(s);
if (ret == 0)
{
// Read status
uint8_t status = ETH_readSnSR(s);
// If status is wrong, return 0 read bytes
if (status == ETH_SSR_LISTEN || status == ETH_SSR_CLOSED || status == ETH_SSR_CLOSE_WAIT)
{
ret = 0;
}
else
{
// Return -1 if there is nothing to read
ret = -1;
}
}
// If there is more to read then we have space, just read to the supplied limit
else if (ret > len)
{
ret = len;
}
// If there is data to read and we have space, beginn processing and reading
if (ret > 0)
{
ETH_recv_data_processing(s, buf, ret, 0x00);
ETH_exec_socket_cmd(s, ETH_SCR_RECV);
}
return ret;
}
int16_t ETH_recv_available(SOCKET s)
{
// Check if data is available to read
return ETH_get_RX_received_size(s);
}
uint16_t ETH_peek(SOCKET s, uint8_t *buf)
{
// Receive one byte
ETH_recv_data_processing(s, buf, 1, 1);
return 1;
}
uint16_t ETH_sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
{
uint16_t ret=0;
// If write size is bigger then memory, limit to memory
if (len > ETH_SSIZE) ret = ETH_SSIZE;
else ret = len;
// Check if address and port is right
if (is_net_addr(addr) || !is_valid_port(port) || ret == 0) {
ret = 0;
}
else
{
// Set address and port to send to
ETH_writeSnDIPR(s, addr);
ETH_writeSnDPORT(s, port);
// Process data and send it
ETH_send_data_processing(s, (uint8_t *)buf, ret);
ETH_exec_socket_cmd(s, ETH_SCR_SEND);
// Wait for the data to be sent
while ((ETH_readSnIR(s) & ETH_SIR_SEND_OK) != ETH_SIR_SEND_OK)
{
// If time out reset send and timout interrupts
if (ETH_readSnIR(s) & ETH_SIR_TIMEOUT)
{
ETH_writeSnIR(s, (ETH_SIR_SEND_OK | ETH_SIR_TIMEOUT));
return 0;
}
}
// Reset send ok interrupt
ETH_writeSnIR(s, ETH_SIR_SEND_OK);
}
return ret;
}
uint16_t ETH_recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
{
uint8_t head[8];
uint16_t data_len=0;
uint16_t ptr=0;
// Check if there is something to receive
if (len > 0)
{
// Get the receive pointer
ptr = ETH_readSnRX_RD(s);
// Handle receiving according to socket type
switch (ETH_readSnMR(s) & 0x07)
{
case ETH_SMR_UDP :
ETH_read_data(s, ptr, head, 0x08);
ptr += 8;
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
data_len = head[6];
data_len = (data_len << 8) + head[7];
ETH_read_data(s, ptr, buf, data_len);
ptr += data_len;
ETH_writeSnRX_RD(s, ptr);
break;
case ETH_SMR_IPRAW :
ETH_read_data(s, ptr, head, 0x06);
ptr += 6;
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
data_len = head[4];
data_len = (data_len << 8) + head[5];
ETH_read_data(s, ptr, buf, data_len);
ptr += data_len;
ETH_writeSnRX_RD(s, ptr);
break;
case ETH_SMR_MACRAW:
ETH_read_data(s, ptr, head, 2);
ptr+=2;
data_len = head[0];
data_len = (data_len<<8) + head[1] - 2;
ETH_read_data(s, ptr, buf, data_len);
ptr += data_len;
ETH_writeSnRX_RD(s, ptr);
break;
default :
break;
}
ETH_exec_socket_cmd(s, ETH_SCR_RECV);
}
return data_len;
}
void ETH_flush(SOCKET s)
{
// TODO
}
uint16_t ETH_igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint16_t ret=0;
if (len > ETH_SSIZE)
ret = ETH_SSIZE;
else
ret = len;
if (ret == 0)
return 0;
// Process and send IGMP data
ETH_send_data_processing(s, (uint8_t *)buf, ret);
ETH_exec_socket_cmd(s, ETH_SCR_SEND);
// Wairt for data to be sent or timeout
while ((ETH_readSnIR(s) & ETH_SIR_SEND_OK) != ETH_SIR_SEND_OK)
{
if (ETH_readSnIR(s) & ETH_SIR_TIMEOUT)
{
ETH_close(s);
return 0;
}
}
// Reset interrupt
ETH_writeSnIR(s, ETH_SIR_SEND_OK);
return ret;
}
int ETH_start_UDP(SOCKET s, uint8_t* addr, uint16_t port)
{
// Check if address and port are valid
if (is_net_addr(addr) || !is_valid_port(port))
{
return 0;
}
else
{
// Write IP and port
ETH_writeSnDIPR(s, addr);
ETH_writeSnDPORT(s, port);
return 1;
}
}
uint16_t ETH_buffer_data(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
{
uint16_t ret = 0;
if (len > ETH_get_TX_free_size(s))
{
ret = ETH_get_TX_free_size(s);
}
else
{
ret = len;
}
ETH_send_data_processing_offset(s, offset, buf, ret);
return ret;
}
int ETH_send_UDP(SOCKET s)
{
ETH_exec_socket_cmd(s, ETH_SCR_SEND);
while ((ETH_readSnIR(s) & ETH_SIR_SEND_OK) != ETH_SIR_SEND_OK)
{
if (ETH_readSnIR(s) & ETH_SIR_TIMEOUT)
{
ETH_writeSnIR(s, (ETH_SIR_SEND_OK | ETH_SIR_TIMEOUT));
return 0;
}
}
ETH_writeSnIR(s, ETH_SIR_SEND_OK);
return 1;
}

45
Mieke/SW/ETH/socket.h Normal file
View file

@ -0,0 +1,45 @@
/*
Ethernet shield test program
Copyright (C) 2018 Andreas Mieke
Copyright (C) 2010 Arduino LLC
This program 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.
This program 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 <https://www.gnu.org/licenses/>.
*/
#ifndef __SOCKET_H
#define __SOCKET_H
#include "w5100.h"
uint8_t ETH_socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag);
uint8_t ETH_socket_status(SOCKET s);
void ETH_close(SOCKET s);
uint8_t ETH_connect(SOCKET s, uint8_t * addr, uint16_t port);
void ETH_disconnect(SOCKET s);
uint8_t ETH_listen(SOCKET s);
uint16_t ETH_send(SOCKET s, const uint8_t * buf, uint16_t len);
int16_t ETH_recv(SOCKET s, uint8_t * buf, int16_t len);
int16_t ETH_recv_available(SOCKET s);
uint16_t ETH_peek(SOCKET s, uint8_t *buf);
uint16_t ETH_sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
uint16_t ETH_recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
void ETH_flush(SOCKET s);
uint16_t ETH_igmpsend(SOCKET s, const uint8_t * buf, uint16_t len);
int ETH_start_UDP(SOCKET s, uint8_t* addr, uint16_t port);
uint16_t ETH_buffer_data(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len);
int ETH_send_UDP(SOCKET s);
#endif

256
Mieke/SW/ETH/w5100.c Normal file
View file

@ -0,0 +1,256 @@
/*
Ethernet shield test program
Copyright (C) 2018 Andreas Mieke
Copyright (C) 2010 Arduino LLC
This program 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.
This program 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 <https://www.gnu.org/licenses/>.
*/
#include "w5100.h"
uint16_t ETH_SBASE[ETH_SOCKETS]; // Tx buffer base address
uint16_t ETH_RBASE[ETH_SOCKETS]; // Rx buffer base address
#define TX_RX_MAX_BUF_SIZE 2048
#define TX_BUF 0x1100
#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
#define ETH_TXBUF_BASE 0x4000
#define ETH_RXBUF_BASE 0x6000
void SPI_SetSS(void)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);
}
void SPI_ResetSS(void)
{
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET);
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
}
uint8_t SPI_WriteRead(uint8_t write)
{
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI1->DR = write;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI1->DR;
}
void ETH_init(void)
{
// Port init stuff
// PA5 -> SCK
// PA6 -> MISO
// PA7 -> MOSI
// PC8 -> /SS
// Set RCC Registers for GPIOA/C
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
// Init gpio structure to default values
GPIO_InitTypeDef gpio;
GPIO_StructInit(&gpio);
// Set PA5 to alternate function PushPull
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOA, &gpio);
// Set PA7 to alternate function push pull
gpio.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &gpio);
// Set PC8 to push pull
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOC, &gpio);
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
// Set PA6 to input floating
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &gpio);
// Init SPI engine
// Init struct to default values
SPI_InitTypeDef spi;
SPI_StructInit(&spi);
// We are master
spi.SPI_Mode = SPI_Mode_Master;
spi.SPI_NSS = SPI_NSS_Soft;
//spi.SPI_CPHA = SPI_CPHA_2Edge;
spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
// Write the registers
SPI_Init(SPI1, &spi);
// Enable SPI1
SPI_Cmd(SPI1, ENABLE);
for(uint16_t i = 0; i < 65535; i++);
ETH_writeMR(ETH_MR_RST);
ETH_writeRMSR(0x55);
ETH_writeTMSR(0x55);
for (int i=0; i<MAX_SOCK_NUM; i++) {
ETH_SBASE[i] = ETH_TXBUF_BASE + ETH_SSIZE * i;
ETH_RBASE[i] = ETH_RXBUF_BASE + ETH_RSIZE * i;
}
}
uint8_t ETH_write_8(uint16_t addr, uint8_t data)
{
SPI_SetSS();
SPI_WriteRead(0xF0);
SPI_WriteRead(addr >> 8);
SPI_WriteRead(addr & 0xFF);
SPI_WriteRead(data);
SPI_ResetSS();
return 8;
}
uint16_t ETH_write_n(uint16_t addr, const uint8_t *buf, uint16_t len)
{
for (uint16_t i = 0; i < len; i++) {
SPI_SetSS();
SPI_WriteRead(0xF0);
SPI_WriteRead(addr >> 8);
SPI_WriteRead(addr & 0xFF);
addr++;
SPI_WriteRead(buf[i]);
SPI_ResetSS();
}
return len;
}
uint8_t ETH_read_8(uint16_t addr)
{
uint8_t data;
SPI_SetSS();
SPI_WriteRead(0x0F);
SPI_WriteRead(addr >> 8);
SPI_WriteRead(addr & 0xFF);
data = SPI_WriteRead(0x00);
SPI_ResetSS();
return data;
}
uint16_t ETH_read_n(uint16_t addr, uint8_t *buf, uint16_t len)
{
for (uint16_t i = 0; i < len; i++) {
SPI_SetSS();
SPI_WriteRead(0x0F);
SPI_WriteRead(addr >> 8);
SPI_WriteRead(addr & 0xFF);
addr++;
buf[i] = SPI_WriteRead(0x00);
SPI_ResetSS();
}
return len;
}
uint16_t ETH_get_TX_free_size(SOCKET s)
{
uint16_t val=0, val1=0;
do {
val1 = ETH_readSnTX_FSR(s);
if (val1 != 0)
val = ETH_readSnTX_FSR(s);
}
while (val != val1);
return val;
}
uint16_t ETH_get_RX_received_size(SOCKET s)
{
uint16_t val=0,val1=0;
do {
val1 = ETH_readSnRX_RSR(s);
if (val1 != 0)
val = ETH_readSnRX_RSR(s);
}
while (val != val1);
return val;
}
void ETH_read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len)
{
uint16_t size;
uint16_t src_mask;
uint16_t src_ptr;
src_mask = src & ETH_RMASK;
src_ptr = ETH_RBASE[s] + src_mask;
if( (src_mask + len) > ETH_RSIZE )
{
size = ETH_RSIZE - src_mask;
ETH_read_n(src_ptr, (uint8_t *)dst, size);
dst += size;
ETH_read_n(ETH_RBASE[s], (uint8_t *) dst, len - size);
}
else
ETH_read_n(src_ptr, (uint8_t *) dst, len);
}
void ETH_send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
{
ETH_send_data_processing_offset(s, 0, data, len);
}
void ETH_send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
{
uint16_t ptr = ETH_readSnTX_WR(s);
ptr += data_offset;
uint16_t offset = ptr & ETH_SMASK;
uint16_t dstAddr = offset + ETH_SBASE[s];
if (offset + len > ETH_SSIZE)
{
uint16_t size = ETH_SSIZE - offset;
ETH_write_n(dstAddr, data, size);
ETH_write_n(ETH_SBASE[s], data + size, len - size);
}
else {
ETH_write_n(dstAddr, data, len);
}
ptr += len;
ETH_writeSnTX_WR(s, ptr);
}
void ETH_recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
{
uint16_t ptr;
ptr = ETH_readSnRX_RD(s);
ETH_read_data(s, ptr, data, len);
if (!peek)
{
ptr += len;
ETH_writeSnRX_RD(s, ptr);
}
}
void ETH_exec_socket_cmd(SOCKET s, uint8_t cmd)
{
ETH_writeSnCR(s, cmd);
while(ETH_readSnCR(s)) {
// Wait for command to be executed
}
}

302
Mieke/SW/ETH/w5100.h Normal file
View file

@ -0,0 +1,302 @@
/*
Ethernet shield test program
Copyright (C) 2018 Andreas Mieke
Copyright (C) 2010 Arduino LLC
This program 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.
This program 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 <https://www.gnu.org/licenses/>.
*/
#ifndef __W5100_H
#define __W5100_H
#include "stm32f10x.h" // Device header
#include "stm32f10x_rcc.h" // Keil::Device:StdPeriph Drivers:RCC
#include "stm32f10x_gpio.h" // Keil::Device:StdPeriph Drivers:GPIO
#include "stm32f10x_spi.h" // Keil::Device:StdPeriph Drivers:SPI
#define MAX_SOCK_NUM 4
typedef uint8_t SOCKET;
enum {
ETH_MR_RST = 0x80,
ETH_MR_PB = 0x10,
ETH_MR_PPPoE = 0x08,
ETH_MR_AI = 0x02,
ETH_MR_IND = 0x01
};
enum {
ETH_IR_CONFLICT = 0x80,
ETH_IR_UNREACH = 0x40,
ETH_IR_PPPoE = 0x20,
ETH_IR_S3_INT = 0x08,
ETH_IR_S2_INT = 0x04,
ETH_IR_S1_INT = 0x02,
ETH_IR_S0_INT = 0x01
};
enum {
ETH_IMR_IR7 = 0x80,
ETH_IMR_IR6 = 0x40,
ETH_IMR_IR5 = 0x20,
ETH_IMR_IR3 = 0x08,
ETH_IMR_IR2 = 0x04,
ETH_IMR_IR1 = 0x02,
ETH_IMR_IR0 = 0x01
};
enum {
ETH_SMR_MULTI = 0x80,
ETH_SMR_ND = 0x20,
ETH_SMR_CLOSED = 0x00,
ETH_SMR_TCP = 0x01,
ETH_SMR_UDP = 0x02,
ETH_SMR_IPRAW = 0x03,
ETH_SMR_MACRAW = 0x04,
ETH_SMR_PPPoE = 0x05
};
enum {
ETH_SCR_OPEN = 0x01,
ETH_SCR_LISTEN = 0x02,
ETH_SCR_CONNECT = 0x04,
ETH_SCR_DISCON = 0x08,
ETH_SCR_CLOSE = 0x10,
ETH_SCR_SEND = 0x20,
ETH_SCR_SEND_MAC = 0x21,
ETH_SCR_SEND_KEEP = 0x22,
ETH_SCR_RECV = 0x40
};
enum {
ETH_SIR_SEND_OK = 0x10,
ETH_SIR_TIMEOUT = 0x08,
ETH_SIR_RECV = 0x04,
ETH_SIR_DISCON = 0x02,
ETH_SIR_CON = 0x01
};
enum {
ETH_SSR_CLOSED = 0x00,
ETH_SSR_INIT = 0x12, // Actually 13, Cortex doesn't seem to register the LSB
ETH_SSR_LISTEN = 0x14,
ETH_SSR_SYNSENT = 0x15,
ETH_SSR_SYNRECV = 0x16,
ETH_SSR_ESTABLISHED = 0x17,
ETH_SSR_FIN_WAIT = 0x18,
ETH_SSR_CLOSING = 0x1A,
ETH_SSR_TIME_WAIT = 0x1B,
ETH_SSR_CLOSE_WAIT = 0x1C,
ETH_SSR_LAST_ACK = 0x1D,
ETH_SSR_UDP = 0x22,
ETH_SSR_IPRAW = 0x32,
ETH_SSR_MACRAW = 0x42,
ETH_SSR_PPPoE = 0x5F
};
enum {
ETH_SPROTO_IP = 0,
ETH_SPROTO_ICMP = 1,
ETH_SPROTO_IGMP = 2,
ETH_SPROTO_GGP = 3,
ETH_SPROTO_TCP = 6,
ETH_SPROTO_PUP = 12,
ETH_SPROTO_UDP = 17,
ETH_SPROTO_IDP = 22,
ETH_SPROTO_ND = 77,
ETH_SPROTO_RAW = 255
};
void ETH_init(void);
void ETH_read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len);
void ETH_send_data_processing(SOCKET s, const uint8_t *data, uint16_t len);
void ETH_send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len);
void ETH_recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek);
inline void ETH_set_gateway_IP(uint8_t *addr);
inline void ETH_get_gateway_IP(uint8_t *addr);
inline void ETH_set_subnet_mask(uint8_t *addr);
inline void ETH_get_subnet_mask(uint8_t *addr);
inline void ETH_set_mac(uint8_t * addr);
inline void ETH_get_mac(uint8_t * addr);
inline void ETH_set_IP(uint8_t * addr);
inline void ETH_get_IP(uint8_t * addr);
inline void ETH_set_retransmission_time(uint16_t timeout);
inline void ETH_set_retransmission_count(uint8_t retry);
inline void ETH_exec_socket_cmd(SOCKET s, uint8_t cmd);
uint16_t ETH_get_TX_free_size(SOCKET s);
uint16_t ETH_get_RX_received_size(SOCKET s);
uint8_t ETH_write_8(uint16_t addr, uint8_t data);
uint16_t ETH_write_n(uint16_t addr, const uint8_t *buf, uint16_t len);
uint8_t ETH_read_8(uint16_t addr);
uint16_t ETH_read_n(uint16_t addr, uint8_t *buf, uint16_t len);
#define __GP_REGISTER8(name, address) \
static inline void ETH_write##name(uint8_t _data) { \
ETH_write_8(address, _data); \
} \
static inline uint8_t ETH_read##name() { \
return ETH_read_8(address); \
}
#define __GP_REGISTER16(name, address) \
static void ETH_write##name(uint16_t _data) { \
ETH_write_8(address, _data >> 8); \
ETH_write_8(address+1, _data & 0xFF); \
} \
static uint16_t ETH_read##name() { \
uint16_t res = ETH_read_8(address); \
res = (res << 8) + ETH_read_8(address + 1); \
return res; \
}
#define __GP_REGISTER_N(name, address, size) \
static uint16_t ETH_write##name(uint8_t *_buff) { \
return ETH_write_n(address, _buff, size); \
} \
static uint16_t ETH_read##name(uint8_t *_buff) { \
return ETH_read_n(address, _buff, size); \
}
__GP_REGISTER8 (MR, 0x0000); // Mode
__GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address
__GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address
__GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address
__GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address
__GP_REGISTER8 (IR, 0x0015); // Interrupt
__GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask
__GP_REGISTER16(RTR, 0x0017); // Timeout address
__GP_REGISTER8 (RCR, 0x0019); // Retry count
__GP_REGISTER8 (RMSR, 0x001A); // Receive memory size
__GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size
__GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode
__GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer
__GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number
__GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode
__GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode
#undef __GP_REGISTER8
#undef __GP_REGISTER16
#undef __GP_REGISTER_N
static inline uint8_t ETH_sock_read_8(SOCKET _s, uint16_t _addr);
static inline uint8_t ETH_sock_write_8(SOCKET _s, uint16_t _addr, uint8_t _data);
static inline uint16_t ETH_sock_read_n(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static inline uint16_t ETH_sock_write_n(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static const uint16_t ETH_CH_BASE = 0x0400;
static const uint16_t ETH_CH_SIZE = 0x0100;
#define __SOCKET_REGISTER8(name, address) \
static inline void ETH_write##name(SOCKET _s, uint8_t _data) { \
ETH_sock_write_8(_s, address, _data); \
} \
static inline uint8_t ETH_read##name(SOCKET _s) { \
return ETH_sock_read_8(_s, address); \
}
#define __SOCKET_REGISTER16(name, address) \
static void ETH_write##name(SOCKET _s, uint16_t _data) { \
ETH_sock_write_8(_s, address, _data >> 8); \
ETH_sock_write_8(_s, address+1, _data & 0xFF); \
} \
static uint16_t ETH_read##name(SOCKET _s) { \
uint16_t res = ETH_sock_read_8(_s, address); \
uint16_t res2 = ETH_sock_read_8(_s,address + 1); \
res = res << 8; \
res2 = res2 & 0xFF; \
res = res | res2; \
return res; \
}
#define __SOCKET_REGISTER_N(name, address, size) \
static uint16_t ETH_write##name(SOCKET _s, uint8_t *_buff) { \
return ETH_sock_write_n(_s, address, _buff, size); \
} \
static uint16_t ETH_read##name(SOCKET _s, uint8_t *_buff) { \
return ETH_sock_read_n(_s, address, _buff, size); \
}
__SOCKET_REGISTER8(SnMR, 0x0000) // Mode
__SOCKET_REGISTER8(SnCR, 0x0001) // Command
__SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt
__SOCKET_REGISTER8(SnSR, 0x0003) // Status
__SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port
__SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr
__SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr
__SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port
__SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size
__SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode
__SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS
__SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL
__SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size
__SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer
__SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer
__SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size
__SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer
__SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?)
#undef __SOCKET_REGISTER8
#undef __SOCKET_REGISTER16
#undef __SOCKET_REGISTER_N
static const int ETH_SOCKETS = 4;
static const uint16_t ETH_SMASK = 0x07FF; // Tx buffer MASK
static const uint16_t ETH_RMASK = 0x07FF; // Rx buffer MASK
static const uint16_t ETH_SSIZE = 2048; // Max Tx buffer size
static const uint16_t ETH_RSIZE = 2048; // Max Rx buffer size
extern uint16_t ETH_SBASE[ETH_SOCKETS]; // Tx buffer base address
extern uint16_t ETH_RBASE[ETH_SOCKETS]; // Rx buffer base address
uint8_t ETH_sock_read_8(SOCKET s, uint16_t addr)
{
return ETH_read_8(ETH_CH_BASE + s * ETH_CH_SIZE + addr);
}
uint8_t ETH_sock_write_8(SOCKET s, uint16_t addr, uint8_t data)
{
return ETH_write_8(ETH_CH_BASE + s * ETH_CH_SIZE + addr, data);
}
uint16_t ETH_sock_read_n(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len)
{
return ETH_read_n(ETH_CH_BASE + s * ETH_CH_SIZE + addr, buf, len);
}
uint16_t ETH_sock_write_n(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len)
{
return ETH_write_n(ETH_CH_BASE + s * ETH_CH_SIZE + addr, buf, len);
}
void ETH_set_gateway_IP(uint8_t *addr) { ETH_writeGAR(addr); }
void ETH_get_gateway_IP(uint8_t *addr) { ETH_readGAR(addr); }
void ETH_set_subnet_mask(uint8_t *addr) { ETH_writeSUBR(addr); }
void ETH_get_subnet_mask(uint8_t *addr) { ETH_readSUBR(addr); }
void ETH_set_mac(uint8_t * addr) { ETH_writeSHAR(addr); }
void ETH_get_mac(uint8_t * addr) { ETH_readSHAR(addr); }
void ETH_set_IP(uint8_t * addr) { ETH_writeSIPR(addr); }
void ETH_get_IP(uint8_t * addr) { ETH_readSIPR(addr); }
void ETH_set_retransmission_time(uint16_t timeout) { ETH_writeRTR(timeout); }
void ETH_set_retransmission_count(uint8_t retry) { ETH_writeRCR(retry); }
#endif