AMTS/Mieke/SW/ETH/w5100.c

257 lines
6 KiB
C
Raw Normal View History

2018-04-03 20:50:13 +00:00
/*
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
}
}