Added G98/99 to report
Clean up
pull/25/head
Patrick Felixberger 2019-05-13 19:19:56 +02:00
rodzic 05d4c30570
commit 752f0e404d
24 zmienionych plików z 2885 dodań i 58 usunięć

Wyświetl plik

@ -221,6 +221,35 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="HAL\USART\USART.h" />
<Unit filename="Libraries\CRC\CRC.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\CRC\CRC.h" />
<Unit filename="Libraries\Ethernet\Ethernet.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\Ethernet\Ethernet.h" />
<Unit filename="Libraries\Ethernet\ServerTCP.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\Ethernet\ServerTCP.h" />
<Unit filename="Libraries\Ethernet\utility\socket.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\Ethernet\utility\socket.h" />
<Unit filename="Libraries\Ethernet\utility\util2.h" />
<Unit filename="Libraries\Ethernet\utility\W5500.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\Ethernet\utility\W5500.h" />
<Unit filename="Libraries\GrIP\ComIf.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\GrIP\ComIf.h" />
<Unit filename="Libraries\GrIP\GrIP.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="Libraries\GrIP\GrIP.h" />
<Unit filename="main.c">
<Option compilerVar="CC" />
</Unit>

Wyświetl plik

@ -21,7 +21,7 @@
<Cursor1 position="1639" topLine="32" />
</Cursor>
</File>
<File name="grbl\Config.h" open="1" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\Config.h" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="36781" topLine="531" />
</Cursor>
@ -36,7 +36,7 @@
<Cursor1 position="873" topLine="13" />
</Cursor>
</File>
<File name="grbl\defaults.h" open="1" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\defaults.h" open="1" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="2407" topLine="10" />
</Cursor>
@ -116,12 +116,12 @@
<Cursor1 position="842" topLine="3" />
</Cursor>
</File>
<File name="grbl\Report.c" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\Report.c" open="1" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="7135" topLine="235" />
</Cursor>
</File>
<File name="grbl\Report.h" open="1" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\Report.h" open="1" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1483" topLine="9" />
</Cursor>
@ -156,17 +156,17 @@
<Cursor1 position="875" topLine="0" />
</Cursor>
</File>
<File name="grbl\System.c" open="1" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\System.c" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="7435" topLine="208" />
</Cursor>
</File>
<File name="grbl\System.h" open="1" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\System.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="4260" topLine="53" />
</Cursor>
</File>
<File name="grbl\ToolChange.c" open="1" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="grbl\ToolChange.c" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="2162" topLine="66" />
</Cursor>
@ -296,9 +296,9 @@
<Cursor1 position="781" topLine="12" />
</Cursor>
</File>
<File name="main.c" open="1" top="1" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="main.c" open="1" top="1" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="1982" topLine="33" />
<Cursor1 position="2509" topLine="62" />
</Cursor>
</File>
<File name="SPL\inc\stm32f4xx_cryp.h" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
@ -356,9 +356,9 @@
<Cursor1 position="141" topLine="0" />
</Cursor>
</File>
<File name="Src\Platform.h" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<File name="Src\Platform.h" open="1" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="530" topLine="0" />
<Cursor1 position="719" topLine="9" />
</Cursor>
</File>
<File name="Src\Print.c" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">

Wyświetl plik

@ -22,6 +22,7 @@
* A5: PROBE_BIT: PC0
*/
#include "GPIO.h"
#include "Platform.h"
static void GPIO_InitStepper(void);
@ -167,6 +168,18 @@ static void GPIO_InitSystem(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef ETH_IF
// W5500 Reset Pin
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_15);
#endif
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;

Wyświetl plik

@ -36,6 +36,8 @@
#include "Settings.h"
#include "Config.h"
#include "MotionControl.h"
#include "Platform.h"
/** @addtogroup Template_Project
* @{
@ -68,6 +70,59 @@ uint32_t millis(void)
}
void ProcessReceive(char c)
{
// Pick off realtime command characters directly from the serial stream. These characters are
// not passed into the main buffer, but these set system state flag bits for realtime execution.
switch(c)
{
case CMD_RESET: MC_Reset(); break; // Call motion control reset routine.
case CMD_RESET_HARD: NVIC_SystemReset(); // Perform hard reset
case CMD_STATUS_REPORT: System_SetExecStateFlag(EXEC_STATUS_REPORT);break;
case CMD_CYCLE_START: System_SetExecStateFlag(EXEC_CYCLE_START); break; // Set as true
case CMD_FEED_HOLD: System_SetExecStateFlag(EXEC_FEED_HOLD); break; // Set as true
case CMD_STEPPER_DISABLE: Stepper_Disable(1); break; // Set as true
default:
if(c > 0x7F) { // Real-time control characters are extended ACSII only.
switch(c)
{
case CMD_SAFETY_DOOR: System_SetExecStateFlag(EXEC_SAFETY_DOOR); break; // Set as true
case CMD_JOG_CANCEL:
if(sys.state & STATE_JOG) { // Block all other states from invoking motion cancel.
System_SetExecStateFlag(EXEC_MOTION_CANCEL);
}
break;
case CMD_FEED_OVR_RESET: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_RESET); break;
case CMD_FEED_OVR_COARSE_PLUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_COARSE_PLUS); break;
case CMD_FEED_OVR_COARSE_MINUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_COARSE_MINUS); break;
case CMD_FEED_OVR_FINE_PLUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_FINE_PLUS); break;
case CMD_FEED_OVR_FINE_MINUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_FINE_MINUS); break;
case CMD_RAPID_OVR_RESET: System_SetExecMotionOverrideFlag(EXEC_RAPID_OVR_RESET); break;
case CMD_RAPID_OVR_MEDIUM: System_SetExecMotionOverrideFlag(EXEC_RAPID_OVR_MEDIUM); break;
case CMD_RAPID_OVR_LOW: System_SetExecMotionOverrideFlag(EXEC_RAPID_OVR_LOW); break;
case CMD_SPINDLE_OVR_RESET: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_RESET); break;
case CMD_SPINDLE_OVR_COARSE_PLUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_COARSE_PLUS); break;
case CMD_SPINDLE_OVR_COARSE_MINUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_COARSE_MINUS); break;
case CMD_SPINDLE_OVR_FINE_PLUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_FINE_PLUS); break;
case CMD_SPINDLE_OVR_FINE_MINUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_FINE_MINUS); break;
case CMD_SPINDLE_OVR_STOP: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_STOP); break;
case CMD_COOLANT_FLOOD_OVR_TOGGLE: System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break;
#ifdef ENABLE_M7
case CMD_COOLANT_MIST_OVR_TOGGLE: System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_MIST_OVR_TOGGLE); break;
#endif
}
// Throw away any unfound extended-ASCII character by not passing it to the serial buffer.
}
else {
// Write character to buffer
FifoUsart_Insert(USART2_NUM, USART_DIR_RX, c);
}
}
}
/**
* @brief This function handles NMI exception.
* @param None
@ -292,52 +347,7 @@ void USART2_IRQHandler(void)
/* Read one byte from the receive data register */
unsigned char c = (USART_ReceiveData(USART2) & 0xFF);
// Pick off realtime command characters directly from the serial stream. These characters are
// not passed into the main buffer, but these set system state flag bits for realtime execution.
switch(c)
{
case CMD_RESET: MC_Reset(); break; // Call motion control reset routine.
case CMD_RESET_HARD: NVIC_SystemReset(); // Perform hard reset
case CMD_STATUS_REPORT: System_SetExecStateFlag(EXEC_STATUS_REPORT);break;
case CMD_CYCLE_START: System_SetExecStateFlag(EXEC_CYCLE_START); break; // Set as true
case CMD_FEED_HOLD: System_SetExecStateFlag(EXEC_FEED_HOLD); break; // Set as true
default:
if(c > 0x7F) { // Real-time control characters are extended ACSII only.
switch(c)
{
case CMD_SAFETY_DOOR: System_SetExecStateFlag(EXEC_SAFETY_DOOR); break; // Set as true
case CMD_JOG_CANCEL:
if(sys.state & STATE_JOG) { // Block all other states from invoking motion cancel.
System_SetExecStateFlag(EXEC_MOTION_CANCEL);
}
break;
case CMD_FEED_OVR_RESET: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_RESET); break;
case CMD_FEED_OVR_COARSE_PLUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_COARSE_PLUS); break;
case CMD_FEED_OVR_COARSE_MINUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_COARSE_MINUS); break;
case CMD_FEED_OVR_FINE_PLUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_FINE_PLUS); break;
case CMD_FEED_OVR_FINE_MINUS: System_SetExecMotionOverrideFlag(EXEC_FEED_OVR_FINE_MINUS); break;
case CMD_RAPID_OVR_RESET: System_SetExecMotionOverrideFlag(EXEC_RAPID_OVR_RESET); break;
case CMD_RAPID_OVR_MEDIUM: System_SetExecMotionOverrideFlag(EXEC_RAPID_OVR_MEDIUM); break;
case CMD_RAPID_OVR_LOW: System_SetExecMotionOverrideFlag(EXEC_RAPID_OVR_LOW); break;
case CMD_SPINDLE_OVR_RESET: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_RESET); break;
case CMD_SPINDLE_OVR_COARSE_PLUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_COARSE_PLUS); break;
case CMD_SPINDLE_OVR_COARSE_MINUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_COARSE_MINUS); break;
case CMD_SPINDLE_OVR_FINE_PLUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_FINE_PLUS); break;
case CMD_SPINDLE_OVR_FINE_MINUS: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_FINE_MINUS); break;
case CMD_SPINDLE_OVR_STOP: System_SetExecAccessoryOverrideFlag(EXEC_SPINDLE_OVR_STOP); break;
case CMD_COOLANT_FLOOD_OVR_TOGGLE: System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_FLOOD_OVR_TOGGLE); break;
#ifdef ENABLE_M7
case CMD_COOLANT_MIST_OVR_TOGGLE: System_SetExecAccessoryOverrideFlag(EXEC_COOLANT_MIST_OVR_TOGGLE); break;
#endif
}
// Throw away any unfound extended-ASCII character by not passing it to the serial buffer.
}
else {
// Write character to buffer
FifoUsart_Insert(USART2_NUM, USART_DIR_RX, c);
}
}
ProcessReceive(c);
}
if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET) {

338
Libraries/CRC/CRC.c 100644
Wyświetl plik

@ -0,0 +1,338 @@
/*
CRC.c - Simple library to calculate 8-, 16-, and 32-Bit CRC
Copyright (c) 2018 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "CRC.h"
//---- Prototypes ----//
static void CRC_CalculateCRC8Table(void);
static void CRC_CalculateCRC16Table(void);
static void CRC_CalculateCRC32Table(void);
static uint8_t CRC_ReverseBitOrder8(uint8_t value);
static uint32_t CRC_ReverseBitOrder32(uint32_t value);
#if (CRC_8_MODE == TABLE)
static uint8_t CRC8Table[256u];
#endif
#if (CRC_16_MODE == TABLE)
static uint16_t CRC16Table[256u];
#endif
#if (CRC_32_MODE == TABLE)
static uint32_t CRC32Table[256u];
#endif
void CRC_Init(void)
{
CRC_CalculateCRC8Table();
CRC_CalculateCRC16Table();
CRC_CalculateCRC32Table();
}
uint8_t CRC_CalculateCRC8(const uint8_t *Buffer, uint16_t Length)
{
uint8_t retVal = 0u;
uint16_t byteIndex = 0u;
if(Buffer != NULL)
{
#if (CRC_8_MODE == RUNTTIME)
uint8_t bitIndex = 0u;
retVal = CRC_8_INIT_VALUE;
/* Do calculation procedure for each byte */
for(byteIndex = 0u; byteIndex < Length; byteIndex++)
{
/* XOR new byte with temp result */
retVal ^= (Buffer[byteIndex] << (CRC_8_RESULT_WIDTH - 8u));
/* Do calculation for current data */
for(bitIndex = 0u; bitIndex < 8u; bitIndex++)
{
if(retVal & (1u << (CRC_8_RESULT_WIDTH - 1u)))
{
retVal = (retVal << 1u) ^ CRC_8_POLYNOMIAL;
}
else
{
retVal = (retVal << 1u);
}
}
}
/* XOR result with specified value */
retVal ^= CRC_8_XOR_VALUE;
#elif (CRC_8_MODE == TABLE)
retVal = CRC_8_INIT_VALUE;
for(byteIndex = 0u; byteIndex < Length; byteIndex++)
{
retVal = CRC8Table[(retVal) ^ Buffer[byteIndex]];
}
/* XOR result with specified value */
retVal ^= CRC_8_XOR_VALUE;
#else
/* Mode not implemented */
retVal = 0x00u;
#endif
}
return retVal;
}
uint16_t CRC_CalculateCRC16(const uint8_t *Buffer, uint16_t Length)
{
uint16_t retVal = 0u;
uint16_t byteIndex = 0u;
if(Buffer != NULL)
{
#if (CRC_16_MODE==RUNTTIME)
retVal = CRC_16_INIT_VALUE;
/* Do calculation procedure for each byte */
for(byteIndex = 0u; byteIndex < Length; byteIndex++)
{
/* XOR new byte with temp result */
retVal ^= (Buffer[byteIndex] << (CRC_16_RESULT_WIDTH - 8u));
uint8_t bitIndex = 0u;
/* Do calculation for current data */
for(bitIndex = 0u; bitIndex < 8u; bitIndex++)
{
if(retVal & (1u << (CRC_16_RESULT_WIDTH - 1u)))
{
retVal = (retVal << 1u) ^ CRC_16_POLYNOMIAL;
}
else
{
retVal = (retVal << 1u);
}
}
}
/* XOR result with specified value */
retVal ^= CRC_16_XOR_VALUE;
#elif (CRC_16_MODE==TABLE)
retVal = CRC_16_INIT_VALUE;
/* Update the CRC using the data */
for(byteIndex = 0u; byteIndex < Length; byteIndex++)
{
retVal = (retVal << 8u) ^ CRC16Table[(retVal >> 8u) ^ Buffer[byteIndex]];
}
/* XOR result with specified value */
retVal ^= CRC_16_XOR_VALUE;
#else
/* Mode not implemented */
retVal = 0x0000u;
#endif
}
return retVal;
}
uint32_t CRC_CalculateCRC32(const uint8_t *Buffer, uint16_t Length)
{
uint32_t retVal = 0u;
uint16_t byteIndex = 0u;
if(Buffer != NULL)
{
#if (CRC_32_MODE==RUNTTIME)
retVal = CRC_32_INIT_VALUE;
/* Do calculation procedure for each byte */
for(byteIndex = 0u; byteIndex < Length; byteIndex++)
{
/* XOR new byte with temp result */
retVal ^= (CRC_ReverseBitOrder8(Buffer[byteIndex]) << (CRC_32_RESULT_WIDTH - 8u));
uint8_t bitIndex = 0u;
/* Do calculation for current data */
for(bitIndex = 0u; bitIndex < 8u; bitIndex++)
{
if(retVal & (1u << (CRC_32_RESULT_WIDTH - 1u)))
{
retVal = (retVal << 1u) ^ CRC_32_POLYNOMIAL;
}
else
{
retVal = (retVal << 1u);
}
}
}
/* XOR result with specified value */
retVal ^= CRC_32_XOR_VALUE;
#elif (CRC_32_MODE==TABLE)
uint8_t data = 0u;
retVal = CRC_32_INIT_VALUE;
for(byteIndex = 0u; byteIndex < Length; ++byteIndex)
{
data = CRC_ReverseBitOrder8(Buffer[byteIndex]) ^ (retVal >> (CRC_32_RESULT_WIDTH - 8u));
retVal = CRC32Table[data] ^ (retVal << 8u);
}
/* XOR result with specified value */
retVal ^= CRC_32_XOR_VALUE;
#else
/* Mode not implemented */
retVal = 0x00000000u;
#endif
}
/* Reflect result */
retVal = CRC_ReverseBitOrder32(retVal);
return retVal;
}
static void CRC_CalculateCRC8Table(void)
{
#if (CRC_8_MODE==TABLE)
uint16_t i = 0u, j = 0u;
for(i = 0u; i < 256u; ++i)
{
uint8_t curr = i;
for(j = 0u; j < 8u; ++j)
{
if((curr & 0x80u) != 0u)
{
curr = (curr << 1u) ^ CRC_8_POLYNOMIAL;
}
else
{
curr <<= 1u;
}
}
CRC8Table[i] = curr;
}
#endif
}
static void CRC_CalculateCRC16Table(void)
{
#if (CRC_16_MODE==TABLE)
uint16_t i = 0u, j = 0u;
uint16_t result = 0u;
uint16_t xor_flag = 0u;
for(i = 0u; i < 256u; i++)
{
result = i << 8u;
for(j = 0u; j < 8u; j++)
{
/* Flag for XOR if leftmost bit is set */
xor_flag = result & 0x8000u;
/* Shift CRC */
result <<= 1u;
/* Perform the XOR */
if(xor_flag != 0u)
result ^= CRC_16_POLYNOMIAL;
}
CRC16Table[i] = result;
}
#endif
}
static void CRC_CalculateCRC32Table(void)
{
#if (CRC_32_MODE==TABLE)
uint32_t remainder = 0u;
for(uint32_t dividend = 0u; dividend < 256u; ++dividend)
{
remainder = dividend << (CRC_32_RESULT_WIDTH - 8u);
for(uint8_t bit = 8u; bit > 0u; --bit)
{
if(remainder & (1u << (CRC_32_RESULT_WIDTH - 1u)))
{
remainder = (remainder << 1u) ^ CRC_32_POLYNOMIAL;
}
else
{
remainder = (remainder << 1u);
}
}
CRC32Table[dividend] = remainder;
}
#endif
}
static uint8_t CRC_ReverseBitOrder8(uint8_t value)
{
value = (value & 0xF0) >> 4u | (value & 0x0F) << 4u;
value = (value & 0xCC) >> 2u | (value & 0x33) << 2u;
value = (value & 0xAA) >> 1u | (value & 0x55) << 1u;
return value;
}
static uint32_t CRC_ReverseBitOrder32(uint32_t value)
{
uint32_t reversed = 0u;
for(uint8_t i = 31u; value; )
{
reversed |= (value & 1u) << i;
value >>= 1u;
-- i;
}
return reversed;
}

Wyświetl plik

@ -0,0 +1,87 @@
/*
CRC.h - Simple library to calculate 8-, 16-, and 32-Bit CRC
Copyright (c) 2018 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CRC_H_INCLUDED
#define CRC_H_INCLUDED
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RUNTTIME 0
#define TABLE 1
#define HARDWARE 2
/* ---------- Defines for 8-bit SAE J1850 CRC calculation (Not reflected) ------------------------------------------------------- */
#define CRC_8_RESULT_WIDTH 8u
#define CRC_8_POLYNOMIAL 0x1Du
#define CRC_8_INIT_VALUE 0xFFu
#define CRC_8_XOR_VALUE 0xFFu
#define CRC_8_MODE TABLE
/* ---------- Defines for 16-bit CCITT CRC calculation (Not reflected) ---------------------------------------------------------- */
#define CRC_16_RESULT_WIDTH 16u
#define CRC_16_POLYNOMIAL 0x1021u
#define CRC_16_INIT_VALUE 0xFFFFu
#define CRC_16_XOR_VALUE 0x0000u
#define CRC_16_MODE RUNTTIME
/* ---------- Defines for 32-bit CCITT CRC calculation (Reflected) -------------------------------------------------------------- */
#define CRC_32_RESULT_WIDTH 32u
#define CRC_32_POLYNOMIAL 0x04C11DB7u
#define CRC_32_INIT_VALUE 0xFFFFFFFFu
#define CRC_32_XOR_VALUE 0xFFFFFFFFu
#define CRC_32_MODE RUNTTIME
void CRC_Init(void);
/**
* This function makes a CRC8 calculation on Length data bytes with SAEJ1850 parameters
*
* RETURN VALUE: 8 bit result of CRC calculation
*/
uint8_t CRC_CalculateCRC8(const uint8_t *Buffer, uint16_t Length);
/**
* This function makes a CRC16 calculation on Length data bytes
*
* RETURN VALUE: 16 bit result of CRC calculation
*/
uint16_t CRC_CalculateCRC16(const uint8_t *Buffer, uint16_t Length);
/**
* This function makes a CRC32 calculation on Length data bytes
*
* RETURN VALUE: 32 bit result of CRC calculation
*/
uint32_t CRC_CalculateCRC32(const uint8_t *Buffer, uint16_t Length);
#ifdef __cplusplus
}
#endif
#endif // CRC_H_INCLUDED

Wyświetl plik

@ -0,0 +1,63 @@
/*
modified 12 Aug 2013
by Soohwan Kim (suhwan@wiznet.co.kr)
*/
#include "Ethernet.h"
#include "W5500.h"
IPAddress_t _dnsServerAddress = {{0, 0, 0, 0}};
void Ethernet_Init(uint8_t *mac, IPAddress_t *local_ip, IPAddress_t *dns_server, IPAddress_t *gateway, IPAddress_t *subnet)
{
W5500_Init();
W5500_SetMACAddress(mac);
W5500_SetIPAddress(local_ip->IP);
W5500_SetGatewayIp(gateway->IP);
W5500_SetSubnetMask(subnet->IP);
_dnsServerAddress = *dns_server;
}
IPAddress_t Ethernet_LocalIP(void)
{
IPAddress_t ret;
W5500_GetIPAddress(ret.IP);
return ret;
}
IPAddress_t Ethernet_SubnetMask(void)
{
IPAddress_t ret;
W5500_GetSubnetMask(ret.IP);
return ret;
}
IPAddress_t Ethernet_GatewayIP(void)
{
IPAddress_t ret;
W5500_GetGatewayIp(ret.IP);
return ret;
}
IPAddress_t Ethernet_DnsServerIP(void)
{
return _dnsServerAddress;
}
uint8_t Ethernet_LinkStatus(void)
{
return (W5500_GetPHYCFGR() & 0x01);
}

Wyświetl plik

@ -0,0 +1,33 @@
/*
modified 12 Aug 2013
by Soohwan Kim (suhwan@wiznet.co.kr)
*/
#ifndef ETHERNET_H_INLUDED
#define ETHERNET_H_INLUDED
#include <stdint.h>
#include "util2.h"
#ifdef __cplusplus
extern "C" {
#endif
void Ethernet_Init(uint8_t *mac_address, IPAddress_t *local_ip, IPAddress_t *dns_server, IPAddress_t *gateway, IPAddress_t *subnet);
IPAddress_t Ethernet_LocalIP(void);
IPAddress_t Ethernet_SubnetMask(void);
IPAddress_t Ethernet_GatewayIP(void);
IPAddress_t Ethernet_DnsServerIP(void);
uint8_t Ethernet_LinkStatus(void);
#ifdef __cplusplus
}
#endif
#endif // ETHERNET_H_INLUDED

Wyświetl plik

@ -0,0 +1,109 @@
/*
* TcpServer.c
*
* Created: 24.01.2018 21:49:52
* Author: PatrickVM
*/
#include "ServerTCP.h"
#include "W5500.h"
#include "socket.h"
#include "System32.h"
static uint8_t mSock = 0;
static uint16_t mPort = 0;
uint8_t ServerTCP_Init(uint8_t sock, uint16_t port)
{
mSock = sock;
mPort = port;
// Check if socket is available
if(W5500_READ_SOCK_REG8(sock, REG8_SnSR) == SnSR_CLOSED)
{
// Set socket to TCP listen mode
socket(sock, SnMR_TCP, port, 0);
listen(sock);
// OK
return 0;
}
// Socket occupied
return 1;
}
void ServerTCP_DeInit(uint8_t sock)
{
// Release socket
disconnect(sock);
Delay_ms(5);
// Check if socket is released
if(W5500_READ_SOCK_REG8(sock, REG8_SnSR) != SnSR_CLOSED)
{
// Force release
close(sock);
}
}
uint8_t ServerTCP_Send(uint8_t sock, uint8_t *data, uint16_t len)
{
// Check if socket available
if(W5500_READ_SOCK_REG8(sock, REG8_SnSR) == SnSR_ESTABLISHED)
{
// Send data
if(send(sock, data, len) <= 0)
{
return 1;
}
// OK
return 0;
}
return 2;
}
int32_t ServerTCP_Receive(uint8_t sock, uint8_t *data, uint16_t len)
{
// Check if data is available
if(W5500_GetRXReceivedSize(sock))
{
// Read data
return recv(sock, data, len);
}
// No data available
return -1;
}
uint16_t ServerTCP_DataAvailable(uint8_t sock)
{
return W5500_GetRXReceivedSize(sock);
}
void ServerTCP_Update(void)
{
// If socket is closed, reinitalize it.
uint8_t ret = 0;
ret = W5500_READ_SOCK_REG8(mSock, REG8_SnSR);
if(ret == SnSR_CLOSE_WAIT)
{
ServerTCP_DeInit(mSock);
ServerTCP_Init(mSock, mPort);
}
if(ret == SnSR_CLOSED)
{
ServerTCP_Init(mSock, mPort);
}
}

Wyświetl plik

@ -0,0 +1,25 @@
/*
* TcpServer.h
*
* Created: 24.01.2018 21:49:39
* Author: PatrickVM
*/
#ifndef TCPSERVER_H_
#define TCPSERVER_H_
#include <stdint.h>
uint8_t ServerTCP_Init(uint8_t sock, uint16_t port);
void ServerTCP_DeInit(uint8_t sock);
uint8_t ServerTCP_Send(uint8_t sock, uint8_t *data, uint16_t len);
int32_t ServerTCP_Receive(uint8_t sock, uint8_t *data, uint16_t len);
uint16_t ServerTCP_DataAvailable(uint8_t sock);
void ServerTCP_Update(void);
#endif /* TCPSERVER_H_ */

Wyświetl plik

@ -0,0 +1,439 @@
/*
W5500.c - Driver for WIZnet W5500.
Copyright (c) 2018 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "W5500.h"
#include "SPI.h"
#include "System32.h"
#ifndef SPI_W5500
#define SPI_W5500 SPI3
#endif
#define RESET_BIT 7
static inline void Write(uint16_t _addr, uint8_t _cb, uint8_t _data);
static inline uint16_t WriteArray(uint16_t addr, uint8_t _cb, const uint8_t *buf, uint16_t len);
static inline uint8_t Read(uint16_t addr, uint8_t _cb);
static inline uint16_t ReadArray(uint16_t addr, uint8_t _cb, uint8_t *buf, uint16_t len);
static inline uint8_t ReadSn(SOCKET _s, uint16_t _addr);
static inline void WriteSn(SOCKET _s, uint16_t _addr, uint8_t _data);
static inline uint16_t ReadSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static inline uint16_t WriteSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
void W5500_Init(void)
{
Spi_Init(SPI_W5500, SPI_MODE0);
// Set clock to 21 Mhz (W5500 should support up to about 80 Mhz)
Spi_SetPrescaler(SPI_W5500, SPI_PRESCALER_2);
GPIO_ResetBits(GPIOA, GPIO_Pin_15);
Delay_ms(40);
GPIO_SetBits(GPIOA, GPIO_Pin_15);
Delay_ms(25);
W5500_SoftReset();
Delay_ms(20);
for(uint8_t i = 0; i < MAX_SOCK_NUM; i++)
{
uint8_t cntl_byte = (0x0C + (i<<5));
Write(0x1E, cntl_byte, 4); //0x1E - Sn_RXBUF_SIZE
Write(0x1F, cntl_byte, 2); //0x1F - Sn_TXBUF_SIZE
}
}
void W5500_SoftReset(void)
{
uint8_t cnt = 0;
// Write reset bit
W5500_WRITE_GP_REG8(REG8_MR, 1<<RESET_BIT);
Delay_ms(1);
// Wait until reset is complete or timeout
while(cnt++ < 32)
{
if(W5500_READ_GP_REG8(REG8_MR) == 0)
{
return;
}
Delay_ms(1);
}
}
void W5500_ReadData(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len)
{
uint8_t cntl_byte = (0x18 + (s<<5));
ReadArray((uint16_t)src , cntl_byte, (uint8_t*)dst, len);
}
void W5500_SendDataProcessing(SOCKET s, const uint8_t *data, uint16_t len)
{
W5500_SendDataProcessingOffset(s, 0, data, len);
}
void W5500_SendDataProcessingOffset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
{
uint16_t ptr = W5500_READ_SOCK_REG16(s, REG16_SnTX_WR);
uint8_t cntl_byte = (0x14+(s<<5));
ptr += data_offset;
WriteArray(ptr, cntl_byte, data, len);
ptr += len;
W5500_WRITE_SOCK_REG16(s, REG16_SnTX_WR, ptr);
}
void W5500_RecvDataProcessing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
{
uint16_t ptr;
ptr = W5500_READ_SOCK_REG16(s, REG16_SnRX_RD);
W5500_ReadData(s, ptr, data, len);
if(!peek)
{
ptr += len;
W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr);
}
}
void W5500_GetGatewayIp(uint8_t *_addr)
{
W5500_READ_GP_REGN(REGN_GAR_4, _addr, 4);
}
void W5500_SetGatewayIp(uint8_t *_addr)
{
W5500_WRITE_GP_REGN(REGN_GAR_4, _addr, 4);
}
void W5500_GetSubnetMask(uint8_t *_addr)
{
W5500_READ_GP_REGN(REGN_SUBR_4, _addr, 4);
}
void W5500_SetSubnetMask(uint8_t *_addr)
{
W5500_WRITE_GP_REGN(REGN_SUBR_4, _addr, 4);
}
void W5500_GetMACAddress(uint8_t *_addr)
{
W5500_READ_GP_REGN(REGN_SHAR_6, _addr, 6);
}
void W5500_SetMACAddress(uint8_t *_addr)
{
W5500_WRITE_GP_REGN(REGN_SHAR_6, _addr, 6);
}
void W5500_GetIPAddress(uint8_t *_addr)
{
W5500_READ_GP_REGN(REGN_SIPR_4, _addr, 4);
}
void W5500_SetIPAddress(uint8_t *_addr)
{
W5500_WRITE_GP_REGN(REGN_SIPR_4, _addr, 4);
}
void W5500_SetRetransmissionTime(uint16_t _timeout)
{
W5500_WRITE_GP_REG16(REG16_RTR, _timeout);
}
void W5500_SetRetransmissionCount(uint8_t _retry)
{
W5500_WRITE_GP_REG8(REG8_RCR, _retry);
}
void W5500_ExecCmdSn(SOCKET s, SockCMD_e _cmd)
{
// Send command to socket
W5500_WRITE_SOCK_REG8(s, REG8_SnCR, _cmd);
// Wait for command to complete
while(W5500_READ_SOCK_REG8(s, REG8_SnCR));
}
uint16_t W5500_GetTXFreeSize(SOCKET s)
{
uint16_t val = 0, val1 = 0;
do
{
val1 = W5500_READ_SOCK_REG16(s, REG16_SnTX_FSR);
if(val1 != 0)
{
val = W5500_READ_SOCK_REG16(s, REG16_SnTX_FSR);
}
} while(val != val1);
return val;
}
uint16_t W5500_GetRXReceivedSize(SOCKET s)
{
uint16_t val = 0, val1 = 0;
do
{
val1 = W5500_READ_SOCK_REG16(s, REG16_SnRX_RSR);
if(val1 != 0)
{
val = W5500_READ_SOCK_REG16(s, REG16_SnRX_RSR);
}
} while (val != val1);
return val;
}
void W5500_SetPHYCFGR(uint8_t _val)
{
W5500_WRITE_GP_REG8(REG8_PHYCFGR, _val);
}
uint8_t W5500_GetPHYCFGR(void)
{
return Read(0x002E, 0x00);
}
static inline void Write(uint16_t _addr, uint8_t _cb, uint8_t _data)
{
Spi_ChipSelect(SPI_W5500, true);
Spi_WriteByte(SPI_W5500, _addr >> 8);
Spi_WriteByte(SPI_W5500, _addr & 0xFF);
Spi_WriteByte(SPI_W5500, _cb);
Spi_WriteByte(SPI_W5500, _data);
Spi_ChipSelect(SPI_W5500, false);
__ASM("nop");
__ASM("nop");
}
static inline uint16_t WriteArray(uint16_t _addr, uint8_t _cb, const uint8_t *_buf, uint16_t _len)
{
Spi_ChipSelect(SPI_W5500, true);
Spi_WriteByte(SPI_W5500, _addr >> 8);
Spi_WriteByte(SPI_W5500, _addr & 0xFF);
Spi_WriteByte(SPI_W5500, _cb);
for(uint16_t i = 0; i < _len; i++)
{
Spi_WriteByte(SPI_W5500, _buf[i]);
}
Spi_ChipSelect(SPI_W5500, false);
__ASM("nop");
__ASM("nop");
return _len;
}
static inline uint8_t Read(uint16_t _addr, uint8_t _cb)
{
Spi_ChipSelect(SPI_W5500, true);
Spi_WriteByte(SPI_W5500, _addr >> 8);
Spi_WriteByte(SPI_W5500, _addr & 0xFF);
Spi_WriteByte(SPI_W5500, _cb);
uint8_t _data = Spi_ReadByte(SPI_W5500);
Spi_ChipSelect(SPI_W5500, false);
__ASM("nop");
__ASM("nop");
return _data;
}
static inline uint16_t ReadArray(uint16_t _addr, uint8_t _cb, uint8_t *_buf, uint16_t _len)
{
Spi_ChipSelect(SPI_W5500, true);
Spi_WriteByte(SPI_W5500, _addr >> 8);
Spi_WriteByte(SPI_W5500, _addr & 0xFF);
Spi_WriteByte(SPI_W5500, _cb);
for(uint16_t i = 0; i < _len; i++)
{
_buf[i] = Spi_ReadByte(SPI_W5500);
}
Spi_ChipSelect(SPI_W5500, false);
__ASM("nop");
__ASM("nop");
return _len;
}
static inline uint8_t ReadSn(SOCKET _s, uint16_t _addr)
{
uint8_t cntl_byte = (_s<<5) + 0x08;
return Read(_addr, cntl_byte);
}
static inline void WriteSn(SOCKET _s, uint16_t _addr, uint8_t _data)
{
uint8_t cntl_byte = (_s<<5) + 0x0C;
Write(_addr, cntl_byte, _data);
}
static inline uint16_t ReadSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len)
{
uint8_t cntl_byte = (_s<<5) + 0x08;
return ReadArray(_addr, cntl_byte, _buf, _len);
}
static inline uint16_t WriteSnArray(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len)
{
uint8_t cntl_byte = (_s<<5) + 0x0C;
return WriteArray(_addr, cntl_byte, _buf, _len);
}
// W5500 Registers
// ---------------
void W5500_WRITE_GP_REG8(uint16_t address, uint8_t _data)
{
Write(address, 0x04, _data);
}
uint8_t W5500_READ_GP_REG8(uint16_t address)
{
return Read(address, 0x00);
}
void W5500_WRITE_GP_REG16(uint16_t address, uint16_t _data)
{
Write(address, 0x04, _data >> 8);
Write(address + 1, 0x04, _data & 0xFF);
}
uint16_t W5500_READ_GP_REG16(uint16_t address)
{
uint16_t res = Read(address, 0x00);
res = (res << 8) + Read(address + 1, 0x00);
return res;
}
uint16_t W5500_WRITE_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size)
{
return WriteArray(address, 0x04, _buff, size);
}
uint16_t W5500_READ_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size)
{
return ReadArray(address, 0x00, _buff, size);
}
// W5500 Socket registers
// ----------------------
void W5500_WRITE_SOCK_REG8(SOCKET _s, uint16_t address, uint8_t _data)
{
WriteSn(_s, address, _data);
}
uint8_t W5500_READ_SOCK_REG8(SOCKET _s, uint16_t address)
{
return ReadSn(_s, address);
}
void W5500_WRITE_SOCK_REG16(SOCKET _s, uint16_t address, uint16_t _data)
{
WriteSn(_s, address, _data >> 8); \
WriteSn(_s, address+1, _data & 0xFF);
}
uint16_t W5500_READ_SOCK_REG16(SOCKET _s, uint16_t address)
{
uint16_t res = ReadSn(_s, address);
uint16_t res2 = ReadSn(_s, address + 1);
res = res << 8;
res2 = res2 & 0xFF;
res = res | res2;
return res;
}
uint16_t W5500_WRITE_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size)
{
return WriteSnArray(_s, address, _buff, size);
}
uint16_t W5500_READ_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size)
{
return ReadSnArray(_s, address, _buff, size);
}

Wyświetl plik

@ -0,0 +1,237 @@
/*
W5500.h - Driver for WIZnet W5500.
Copyright (c) 2018 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef W5500_H_INCLUDED
#define W5500_H_INCLUDED
#include "util2.h"
#define MAX_SOCK_NUM 8
#define W5500_SSIZE 2048 // Max Tx buffer size
#define W5500_RSIZE 2048 // Max Rx buffer size
// W5500 Registers
#define REG8_MR 0x0000 // Mode
#define REGN_GAR_4 0x0001 // Gateway IP address
#define REGN_SUBR_4 0x0005 // Subnet mask address
#define REGN_SHAR_6 0x0009 // Source MAC address
#define REGN_SIPR_4 0x000F // Source IP address
#define REG8_IR 0x0015 // Interrupt
#define REG8_IMR 0x0016 // Interrupt Mask
#define REG16_RTR 0x0019 // Timeout address
#define REG8_RCR 0x001B // Retry count
#define REGN_UIPR_4 0x0028 // Unreachable IP address in UDP mode
#define REG16_UPORT 0x002C // Unreachable Port address in UDP mode
#define REG8_PHYCFGR 0x002E // PHY Configuration register, default value: 0b1011 1XXX
// W5500 Socket registers
#define REG8_SnMR 0x0000 // Mode
#define REG8_SnCR 0x0001 // Command
#define REG8_SnIR 0x0002 // Interrupt
#define REG8_SnSR 0x0003 // Status
#define REG16_SnPORT 0x0004 // Source Port
#define REGN_SnDHAR_6 0x0006 // Destination Hardw Addr
#define REGN_SnDIPR_4 0x000C // Destination IP Addr
#define REG16_SnDPORT 0x0010 // Destination Port
#define REG16_SnMSSR 0x0012 // Max Segment Size
#define REG8_SnPROTO 0x0014 // Protocol in IP RAW Mode
#define REG8_SnTOS 0x0015 // IP TOS
#define REG8_SnTTL 0x0016 // IP TTL
#define REG16_SnTX_FSR 0x0020 // TX Free Size
#define REG16_SnTX_RD 0x0022 // TX Read Pointer
#define REG16_SnTX_WR 0x0024 // TX Write Pointer
#define REG16_SnRX_RSR 0x0026 // RX Free Size
#define REG16_SnRX_RD 0x0028 // RX Read Pointer
#define REG16_SnRX_WR 0x002A // RX Write Pointer (supported?)
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
SnMR_CLOSE = 0x00,
SnMR_TCP = 0x01,
SnMR_UDP = 0x02,
SnMR_IPRAW = 0x03,
SnMR_MACRAW = 0x04,
SnMR_PPPOE = 0x05,
SnMR_ND = 0x20,
SnMR_MULTI = 0x80
} SnMR_e;
typedef enum
{
Sock_OPEN = 0x01,
Sock_LISTEN = 0x02,
Sock_CONNECT = 0x04,
Sock_DISCON = 0x08,
Sock_CLOSE = 0x10,
Sock_SEND = 0x20,
Sock_SEND_MAC = 0x21,
Sock_SEND_KEEP = 0x22,
Sock_RECV = 0x40
} SockCMD_e;
typedef enum
{
SnIR_SEND_OK = 0x10,
SnIR_TIMEOUT = 0x08,
SnIR_RECV = 0x04,
SnIR_DISCON = 0x02,
SnIR_CON = 0x01
} SnIR_e;
typedef enum SnSR
{
SnSR_CLOSED = 0x00,
SnSR_INIT = 0x13,
SnSR_LISTEN = 0x14,
SnSR_SYNSENT = 0x15,
SnSR_SYNRECV = 0x16,
SnSR_ESTABLISHED = 0x17,
SnSR_FIN_WAIT = 0x18,
SnSR_CLOSING = 0x1A,
SnSR_TIME_WAIT = 0x1B,
SnSR_CLOSE_WAIT = 0x1C,
SnSR_LAST_ACK = 0x1D,
SnSR_UDP = 0x22,
SnSR_IPRAW = 0x32,
SnSR_MACRAW = 0x42,
SnSR_PPPOE = 0x5F
} SnSR_e;
typedef enum
{
IPPROTO_IP = 0,
IPPROTO_ICMP = 1,
IPPROTO_IGMP = 2,
IPPROTO_GGP = 3,
IPPROTO_TCP = 6,
IPPROTO_PUP = 12,
IPPROTO_UDP = 17,
IPPROTO_IDP = 22,
IPPROTO_ND = 77,
IPPROTO_RAW = 255,
} IPPROTO_e;
void W5500_Init(void);
void W5500_SoftReset(void);
/**
* @brief This function is being used for copy the data form Receive buffer of the chip to application buffer.
*
* It calculate the actual physical address where one has to read
* the data from Receive buffer. Here also take care of the condition while it exceed
* the Rx memory uper-bound of socket.
*/
void W5500_ReadData(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len);
/**
* @brief This function is being called by send() and sendto() function also.
*
* This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
* register. User should read upper byte first and lower byte later to get proper value.
*/
void W5500_SendDataProcessing(SOCKET s, const uint8_t *data, uint16_t len);
/**
* @brief A copy of send_data_processing that uses the provided ptr for the
* write offset. Only needed for the "streaming" UDP API, where
* a single UDP packet is built up over a number of calls to
* send_data_processing_ptr, because TX_WR doesn't seem to get updated
* correctly in those scenarios
* @param ptr value to use in place of TX_WR. If 0, then the value is read
* in from TX_WR
* @return New value for ptr, to be used in the next call
*/
void W5500_SendDataProcessingOffset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len);
/**
* @brief This function is being called by recv() also.
*
* This function read the Rx read pointer register
* and after copy the data from receive buffer update the Rx write pointer register.
* User should read upper byte first and lower byte later to get proper value.
*/
void W5500_RecvDataProcessing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek);
void W5500_SetGatewayIp(uint8_t *_addr);
void W5500_GetGatewayIp(uint8_t *_addr);
void W5500_SetSubnetMask(uint8_t *_addr);
void W5500_GetSubnetMask(uint8_t *_addr);
void W5500_SetMACAddress(uint8_t *_addr);
void W5500_GetMACAddress(uint8_t *_addr);
void W5500_SetIPAddress(uint8_t *_addr);
void W5500_GetIPAddress(uint8_t *_addr);
void W5500_SetRetransmissionTime(uint16_t timeout);
void W5500_SetRetransmissionCount(uint8_t _retry);
void W5500_ExecCmdSn(SOCKET s, SockCMD_e _cmd);
uint16_t W5500_GetTXFreeSize(SOCKET s);
uint16_t W5500_GetRXReceivedSize(SOCKET s);
void W5500_SetPHYCFGR(uint8_t _val);
uint8_t W5500_GetPHYCFGR(void);
// W5500 Registers
// ---------------
void W5500_WRITE_GP_REG8(uint16_t address, uint8_t _data);
uint8_t W5500_READ_GP_REG8(uint16_t address);
void W5500_WRITE_GP_REG16(uint16_t address, uint16_t _data);
uint16_t W5500_READ_GP_REG16(uint16_t address);
uint16_t W5500_WRITE_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size);
uint16_t W5500_READ_GP_REGN(uint16_t address, uint8_t *_buff, uint16_t size);
// W5500 Socket registers
// ----------------------
void W5500_WRITE_SOCK_REG8(SOCKET _s, uint16_t address, uint8_t _data);
uint8_t W5500_READ_SOCK_REG8(SOCKET _s, uint16_t address);
void W5500_WRITE_SOCK_REG16(SOCKET _s, uint16_t address, uint16_t _data);
uint16_t W5500_READ_SOCK_REG16(SOCKET _s, uint16_t address);
uint16_t W5500_WRITE_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size);
uint16_t W5500_READ_SOCK_REGN(SOCKET _s, uint16_t address, uint8_t *_buff, uint16_t size);
#ifdef __cplusplus
}
#endif
#endif

Wyświetl plik

@ -0,0 +1,507 @@
/*
socket.c - SOCKET APIs like as berkeley socket api.
Copyright (c) 2018 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "W5500.h"
#include "socket.h"
/**
* @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it.
* @return 1 for success else 0.
*/
int8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag)
{
if(s < MAX_SOCK_NUM)
{
if((protocol == SnMR_TCP) || (protocol == SnMR_UDP) || (protocol == SnMR_IPRAW) || (protocol == SnMR_MACRAW) || (protocol == SnMR_PPPOE))
{
close(s);
W5500_WRITE_SOCK_REG8(s, REG8_SnMR, protocol | flag);
if(port)
{
W5500_WRITE_SOCK_REG16(s, REG16_SnPORT, port);
W5500_ExecCmdSn(s, Sock_OPEN);
return SOCK_OK;
}
else
{
return SOCKERR_PORTZERO;
}
}
else
{
return SOCKERR_SOCKMODE;
}
}
return SOCKERR_SOCKNUM;
}
/**
* @brief This function close the socket and parameter is "s" which represent the socket number
*/
int8_t close(SOCKET s)
{
if(s < MAX_SOCK_NUM)
{
W5500_ExecCmdSn(s, Sock_CLOSE);
// Clear interrupts
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, 0xFF);
}
return SOCKERR_SOCKNUM;
}
/**
* @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer.
* @return 1 for success else 0.
*/
int8_t listen(SOCKET s)
{
if(s < MAX_SOCK_NUM)
{
if(W5500_READ_SOCK_REG8(s, REG8_SnSR) != (uint8_t)SnSR_INIT)
{
return SOCKERR_SOCKINIT;
}
W5500_ExecCmdSn(s, Sock_LISTEN);
return SOCK_OK;
}
return SOCKERR_SOCKNUM;
}
/**
* @brief This function established the connection for the channel in Active (client) mode.
* This function waits for the untill the connection is established.
*
* @return 1 for success else 0.
*/
int8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
{
if(s < MAX_SOCK_NUM)
{
if(((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00))
{
return SOCKERR_IPINVALID;
}
// Set destination IP
W5500_WRITE_SOCK_REGN(s, REGN_SnDIPR_4, addr, 4);
W5500_WRITE_SOCK_REG16(s, REG16_SnDPORT, port);
W5500_ExecCmdSn(s, Sock_CONNECT);
return SOCK_OK;
}
return SOCKERR_SOCKNUM;
}
/**
* @brief This function used for disconnect the socket and parameter is "s" which represent the socket number
* @return 1 for success else 0.
*/
int8_t disconnect(SOCKET s)
{
if(s < MAX_SOCK_NUM)
{
W5500_ExecCmdSn(s, Sock_DISCON);
return SOCK_OK;
}
return SOCKERR_SOCKNUM;
}
/**
* @brief This function used to send the data in TCP mode
* @return 1 for success else 0.
*/
int32_t send(SOCKET s, const uint8_t * buf, uint16_t len)
{
uint8_t status = 0;
uint16_t ret = 0;
uint16_t freesize = 0;
if(len > W5500_SSIZE)
ret = W5500_SSIZE; // check size not to exceed MAX size.
else
ret = len;
if(s < MAX_SOCK_NUM)
{
// if freebuf is available, start.
do
{
freesize = W5500_GetTXFreeSize(s);
status = W5500_READ_SOCK_REG8(s, REG8_SnSR);
if((status != SnSR_ESTABLISHED) && (status != SnSR_CLOSE_WAIT))
{
ret = 0;
break;
}
} while(freesize < ret);
// copy data
W5500_SendDataProcessing(s, (uint8_t *)buf, ret);
W5500_ExecCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK)
{
/* m2008.01 [bj] : reduce code */
if(W5500_READ_SOCK_REG8(s, REG8_SnSR) == SnSR_CLOSED)
{
close(s);
return SOCKERR_SOCKCLOSED;
}
}
/* +2008.01 bj */
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK);
}
return ret;
}
/**
* @brief This function is an application I/F function which is used to receive the data in TCP mode.
* It continues to wait for data as much as the application wants to receive.
*
* @return received data size for success else -1.
*/
int32_t recv(SOCKET s, uint8_t *buf, int16_t len)
{
uint16_t ret = 0;
if(s < MAX_SOCK_NUM)
{
// Check how much data is available
ret = W5500_GetRXReceivedSize(s);
if(ret == 0)
{
// No data available.
uint8_t status = W5500_READ_SOCK_REG8(s, REG8_SnSR);
if(status == SnSR_LISTEN || status == SnSR_CLOSED || status == SnSR_CLOSE_WAIT)
{
// The remote end has closed its side of the connection, so this is the eof state
ret = 0;
}
else
{
// The connection is still up, but there's no data waiting to be read
ret = -1;
}
}
else if(ret > len)
{
ret = len;
}
if(ret > 0)
{
W5500_RecvDataProcessing(s, buf, ret, 0);
W5500_ExecCmdSn(s, Sock_RECV);
}
}
else
{
return SOCKERR_SOCKNUM;
}
return ret;
}
/**
* @brief Returns the first byte in the receive queue (no checking)
*
* @return
*/
uint16_t peek(SOCKET s, uint8_t *buf)
{
if(s < MAX_SOCK_NUM)
{
W5500_RecvDataProcessing(s, buf, 1, 1);
return SOCK_OK;
}
return SOCKERR_SOCKNUM;
}
/**
* @brief This function is an application I/F function which is used to send the data for other then TCP mode.
* Unlike TCP transmission, The peer's destination address and the port is needed.
*
* @return This function return send data size for success else -1.
*/
int32_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port)
{
uint16_t ret = 0;
if(len > W5500_SSIZE)
ret = W5500_SSIZE; // check size not to exceed MAX size.
else
ret = len;
if(s < MAX_SOCK_NUM)
{
if(((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || ((port == 0x00)) || (ret == 0))
{
/* +2008.01 [bj] : added return value */
ret = 0;
}
else
{
W5500_WRITE_SOCK_REGN(s, REGN_SnDIPR_4, addr, 4);
W5500_WRITE_SOCK_REG16(s, REG16_SnDPORT, port);
// copy data
W5500_SendDataProcessing(s, (uint8_t *)buf, ret);
W5500_ExecCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK)
{
if(W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, (SnIR_SEND_OK | SnIR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
return 0;
}
}
/* +2008.01 bj */
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK);
}
}
return ret;
}
/**
* @brief This function is an application I/F function which is used to receive the data in other then
* TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.
*
* @return This function return received data size for success else -1.
*/
int32_t 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;
if((s < MAX_SOCK_NUM) && (len > 0))
{
ptr = W5500_READ_SOCK_REG16(s, REG16_SnRX_RD);
switch(W5500_READ_SOCK_REG8(s, REG8_SnMR) & 0x07)
{
case SnMR_UDP :
W5500_ReadData(s, ptr, head, 0x08);
ptr += 8;
// read peer's IP address, port number.
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];
W5500_ReadData(s, ptr, buf, data_len); // data copy.
ptr += data_len;
W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr);
break;
case SnMR_IPRAW :
W5500_ReadData(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];
W5500_ReadData(s, ptr, buf, data_len); // data copy.
ptr += data_len;
W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr);
break;
case SnMR_MACRAW:
W5500_ReadData(s, ptr, head, 2);
ptr+=2;
data_len = head[0];
data_len = (data_len<<8) + head[1] - 2;
W5500_ReadData(s, ptr, buf, data_len);
ptr += data_len;
W5500_WRITE_SOCK_REG16(s, REG16_SnRX_RD, ptr);
break;
default :
break;
}
W5500_ExecCmdSn(s, Sock_RECV);
}
return data_len;
}
/**
* @brief Wait for buffered transmission to complete.
*/
void flush(SOCKET s)
{
if(s < MAX_SOCK_NUM)
{
// TODO
(void)s;
}
}
uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len)
{
//uint8_t status = 0;
uint16_t ret = 0;
if(len > W5500_SSIZE)
ret = W5500_SSIZE; // check size not to exceed MAX size.
else
ret = len;
if(ret == 0)
return 0;
if(s < MAX_SOCK_NUM)
{
W5500_SendDataProcessing(s, (uint8_t *)buf, ret);
W5500_ExecCmdSn(s, Sock_SEND);
while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK)
{
//status = W5100_READ_SOCK_REG8(s, REG8_SnSR);
W5500_READ_SOCK_REG8(s, REG8_SnSR);
if(W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_TIMEOUT)
{
/* in case of igmp, if send fails, then socket closed */
/* if you want change, remove this code. */
close(s);
return 0;
}
}
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK);
}
return ret;
}
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
{
uint16_t ret = 0;
if(len > W5500_GetTXFreeSize(s))
{
ret = W5500_GetTXFreeSize(s); // check size not to exceed MAX size.
}
else
{
ret = len;
}
W5500_SendDataProcessingOffset(s, offset, buf, ret);
return ret;
}
int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
{
if(((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || ((port == 0x00)))
{
return 0;
}
else
{
W5500_WRITE_SOCK_REGN(s, REGN_SnDIPR_4, addr, 4);
W5500_WRITE_SOCK_REG16(s, REG16_SnDPORT, port);
return 1;
}
}
int sendUDP(SOCKET s)
{
W5500_ExecCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while((W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_SEND_OK) != SnIR_SEND_OK )
{
if(W5500_READ_SOCK_REG8(s, REG8_SnIR) & SnIR_TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, (SnIR_SEND_OK | SnIR_TIMEOUT));
return 0;
}
}
/* +2008.01 bj */
W5500_WRITE_SOCK_REG8(s, REG8_SnIR, SnIR_SEND_OK);
/* Sent ok */
return 1;
}

Wyświetl plik

@ -0,0 +1,122 @@
/*
socket.c - SOCKET APIs like as berkeley socket api.
Copyright (c) 2018 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include <stdint.h>
#include "util.h"
#define SOCK_OK 1 ///< Result is OK about socket process.
#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
#define SOCK_FATAL -1000 ///< Result is fatal error about socket process.
#define SOCK_ERROR 0
#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number
#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option
#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized
#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed.
#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation.
#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag
#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.
#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argrument.
#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero
#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address
#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred
#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size.
#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication.
#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error.
#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket().
/*
* UDP & MACRAW Packet Infomation
*/
#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet.
#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received.
#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet.
#ifdef __cplusplus
extern "C" {
#endif
// Opens a socket(TCP or UDP or IP_RAW mode)
int8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag);
// Close socket
int8_t close(SOCKET s);
// Establish TCP connection (Active connection)
int8_t connect(SOCKET s, uint8_t * addr, uint16_t port);
// disconnect the connection
int8_t disconnect(SOCKET s);
// Establish TCP connection (Passive connection)
int8_t listen(SOCKET s);
// Send data (TCP)
int32_t send(SOCKET s, const uint8_t * buf, uint16_t len);
// Receive data (TCP)
int32_t recv(SOCKET s, uint8_t * buf, int16_t len);
uint16_t peek(SOCKET s, uint8_t *buf);
// Send data (UDP/IP RAW)
int32_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
// Receive data (UDP/IP RAW)
int32_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
// Wait for transmission to complete
void flush(SOCKET s);
uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len);
// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a
// number of calls before being sent
/*
@brief This function sets up a UDP datagram, the data for which will be provided by one
or more calls to bufferData and then finally sent with sendUDP.
@return 1 if the datagram was successfully set up, or 0 if there was an error
*/
int startUDP(SOCKET s, uint8_t* addr, uint16_t port);
/*
@brief This function copies up to len bytes of data from buf into a UDP datagram to be
sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls.
@return Number of bytes successfully buffered
*/
uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len);
/*
@brief Send a UDP datagram built up from a sequence of startUDP followed by one or more
calls to bufferData.
@return 1 if the datagram was successfully sent, or 0 if there was an error
*/
int sendUDP(SOCKET s);
#ifdef __cplusplus
}
#endif
#endif /* _SOCKET_H_ */

Wyświetl plik

@ -0,0 +1,37 @@
#ifndef UTIL2_H
#define UTIL2_H
#include <stdint.h>
#include <stdlib.h>
#define htons(x) ((uint16_t)(((x)<<8) | (((x)>>8)&0xFF)))
#define ntohs(x) htons(x)
#define htonl(x) (((x)<<24 & 0xFF000000UL) | ((x)<< 8 & 0x00FF0000UL) | ((x)>> 8 & 0x0000FF00UL) | ((x)>>24 & 0x000000FFUL))
#define ntohl(x) htonl(x)
#ifdef __cplusplus
extern "C" {
#endif
typedef uint8_t SOCKET;
typedef struct
{
uint8_t IP[4];
} IPAddress_t;
static const IPAddress_t INADDR_NONE = {0};
#ifdef __cplusplus
}
#endif
#endif

Wyświetl plik

@ -0,0 +1,192 @@
/*
ComIf.c - Communication Interface
Copyright (c) 2018-2019 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ComIf.h"
#include "ServerTCP.h"
#include "Platform.h"
#include "Print.h"
#include "Usart.h"
#include <string.h>
// Buffer size of interface
#ifndef COMIF_BUFFER_SIZE
#define COMIF_BUFFER_SIZE 512
#endif
#define MAX_READ_SIZE 64
static inline uint16_t BufferFreeBytes(void);
static inline void BufferWriteByte(uint8_t data);
static inline uint8_t BufferReadByte(void);
static uint8_t RxBuffer[COMIF_BUFFER_SIZE] = {0};
static uint16_t Head = 0, Tail = 0, Size = 0;
static uint8_t Socket = 0;
static uint8_t Interface = IF_USB;
void ComIf_Init(uint8_t interface, uint8_t sock)
{
Head = 0, Tail = 0, Size = 0;
memset(RxBuffer, 0, COMIF_BUFFER_SIZE);
Socket = sock;
Interface = interface;
}
void ComIf_DeInit(void)
{
ComIf_Init(Interface, 0);
}
uint8_t ComIf_Send(uint8_t *data, uint16_t len)
{
if(Interface == IF_ETH)
{
return ServerTCP_Send(Socket, data, len);
}
else
{
Usart_Write(STDOUT, false, (char*)data, len);
}
return 0;
}
uint16_t ComIf_Receive(uint8_t *data, uint16_t len)
{
// Check if data available
uint16_t rec = ComIf_DataAvailable();
if(rec)
{
if(len > rec)
{
len = rec;
}
for(uint16_t i = 0; i < len; i++)
{
data[i] = BufferReadByte();
}
return len;
}
// No data available
return 0;
}
uint16_t ComIf_DataAvailable(void)
{
return (COMIF_BUFFER_SIZE - BufferFreeBytes());
}
void ComIf_Update(void)
{
uint8_t ret = 0;
if(Interface == IF_ETH)
{
ret = ServerTCP_DataAvailable(Socket);
}
else
{
// Assume, that there is always data available on serial
ret = 1;
}
if(ret && (MAX_READ_SIZE <= BufferFreeBytes()))
{
uint8_t buf[MAX_READ_SIZE];
// Read max 64 bytes
if(ret > MAX_READ_SIZE)
{
ret = MAX_READ_SIZE;
}
if(Interface == IF_ETH)
{
// Read max 64 bytes from TCP socket and write it into buffer
uint8_t read = ServerTCP_Receive(Socket, buf, ret);
for(uint8_t i = 0; i < read; i++)
{
BufferWriteByte(buf[i]);
}
}
else
{
// Read max 64 bytes from usart buffer
for(uint16_t read = 0; read < MAX_READ_SIZE; read++)
{
char c;
if(Getc(&c) == 0)
{
BufferWriteByte((uint8_t)c);
}
else
{
break;
}
}
}
}
}
static inline void BufferWriteByte(uint8_t data)
{
if(Size > (COMIF_BUFFER_SIZE-1))
{
// Queue full
return;
}
RxBuffer[Head] = data;
Head = (Head + 1) % COMIF_BUFFER_SIZE;
Size++;
}
static inline uint8_t BufferReadByte(void)
{
uint8_t ret = 0;
if(Size)
{
ret = RxBuffer[Tail];
Tail = (Tail + 1) % COMIF_BUFFER_SIZE;
Size--;
}
return ret;
}
static inline uint16_t BufferFreeBytes(void)
{
return (COMIF_BUFFER_SIZE - Size);
}

Wyświetl plik

@ -0,0 +1,89 @@
/*
ComIf.h - Communication Interface
Copyright (c) 2018-2019 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMUNICATIONINTERFACE_H_INCLUDED
#define COMMUNICATIONINTERFACE_H_INCLUDED
#include <stdint.h>
#define IF_USB 0
#define IF_ETH 1
#ifdef __cplusplus
extern "C" {
#endif
/** \brief Initialize communication interface.
*
* \param sock Socket number of TCP server.
* \return None.
*
*/
void ComIf_Init(uint8_t interface, uint8_t sock);
/** \brief Deinitalize communication interface.
*
* \return None.
*
*/
void ComIf_DeInit(void);
/** \brief Transmit data.
*
* \param data Data array to transmit.
* \param len Length of data array in bytes.
* \return 0 if success.
*
*/
uint8_t ComIf_Send(uint8_t *data, uint16_t len);
/** \brief Get data from communication interface.
*
* \param data Pointer where to store the data.
* \param len Max number of bytes to read.
* \return Number of read bytes. 0 if no bytes were read.
*
*/
uint16_t ComIf_Receive(uint8_t *data, uint16_t len);
/** \brief Return if data is available.
*
* \return Number of bytes available.
*
*/
uint16_t ComIf_DataAvailable(void);
/** \brief Cyclic update function. Gets data from hardware interface and stores it in internal buffer. Should be called periodically.
*
* \return None.
*
*/
void ComIf_Update(void);
#ifdef __cplusplus
}
#endif
#endif // COMMUNICATIONINTERFACE_H_INCLUDED

Wyświetl plik

@ -0,0 +1,292 @@
/*
GrIP.c - GRBL over IP
Copyright (c) 2018-2019 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GrIP.h"
#include "CRC.h"
#include "util2.h"
#include "ComIf.h"
#include "Print.h"
#include <stdio.h>
#include <string.h>
// GrIP states
#define GRIP_IDLE 0
#define GRIP_RX_HEADER 1
#define GRIP_RX_DATA 2
// Magic byte - Marks start of transmission
#define MAGIC 0x55
// Size of header packet
#define GRIP_HEADER_SIZE (sizeof(GrIP_PacketHeader_t))
static uint8_t CheckHeader(GrIP_PacketHeader_t *paket);
static GrIP_PacketHeader_t TX_Header;
// Transmit Buffer
static uint8_t TX_Buffer[GRIP_BUFFER_SIZE + GRIP_HEADER_SIZE];
// Receive Data Array
static RX_Packet_t RX_Buff[GRIP_RX_NUM] = {0};
static uint8_t GrIP_Status = GRIP_IDLE;
static uint8_t GrIP_Response = RESPONSE_OK;
static uint8_t GrIP_idx = 0;
void GrIP_Init(void)
{
// Initialize to default values
GrIP_Status = GRIP_IDLE;
GrIP_idx = 0;
memset(&TX_Header, 0, GRIP_HEADER_SIZE);
memset(TX_Buffer, 0, GRIP_BUFFER_SIZE + GRIP_HEADER_SIZE);
memset(RX_Buff, 0, sizeof(RX_Buff));
// Init generic interface
ComIf_Init(IF_ETH, 0);
// Init CRC module
CRC_Init();
}
uint8_t GrIP_Transmit(uint8_t MsgType, uint8_t ReturnCode, Pdu_t *data)
{
// Prepare header
TX_Header.Version = GRIP_VERSION;
TX_Header.MsgType = MsgType;
TX_Header.ReturnCode = ReturnCode;
if(data)
{
// Convert length to network order
TX_Header.Length = htons(data->Length);
// Check if data fits into transmit buffer
if(data->Length > GRIP_BUFFER_SIZE)
{
return RET_NOK;
}
else if(data->Length > 0)
{
// Calculate CRC of data
TX_Header.CRC8 = CRC_CalculateCRC8(data->Data, data->Length);
}
else
{
// No data, no CRC
TX_Header.CRC8 = 0;
}
// Prepare transmit buffer
TX_Buffer[0] = MAGIC;
memcpy(&TX_Buffer[1], &TX_Header, GRIP_HEADER_SIZE);
memcpy(&TX_Buffer[1] + GRIP_HEADER_SIZE, data->Data, data->Length);
// Transmit paket
ComIf_Send(TX_Buffer, data->Length + GRIP_HEADER_SIZE + 1);
// Check if we are expecting a response
GrIP_Response = RESPONSE_OK;
if(MsgType == MSG_DATA)
{
GrIP_Response = RESPONSE_WAIT;
}
return RET_OK;
}
else // Response
{
// No data available -> Response
// No data to transmit, only header
TX_Header.Length = 0;
memcpy(TX_Buffer, &TX_Header, GRIP_HEADER_SIZE);
// Transmit paket
ComIf_Send(TX_Buffer, GRIP_HEADER_SIZE);
return RET_OK;
}
// Clear memory
memset(&TX_Header, 0, GRIP_HEADER_SIZE);
memset(TX_Buffer, 0, GRIP_BUFFER_SIZE);
return RET_NOK;
}
uint8_t GrIP_Receive(RX_Packet_t *pData)
{
if(pData)
{
for(uint8_t i = 0; i < GRIP_RX_NUM; i++)
{
if(RX_Buff[i].isValid)
{
memcpy(pData, &RX_Buff[i], sizeof(RX_Packet_t));
// Clear rx slot
memset(&RX_Buff[i], 0, sizeof(RX_Packet_t));
return 1;
}
}
}
// No data available
return 0;
}
uint8_t GrIP_ResponseStatus(void)
{
return GrIP_Response;
}
void GrIP_Update(void)
{
switch(GrIP_Status)
{
case GRIP_IDLE:
// Check if data is available
if(ComIf_DataAvailable())
{
uint8_t magic = 0;
// Read Magic byte
ComIf_Receive(&magic, 1);
if(magic == MAGIC)
{
// Received valid packet
GrIP_Status = GRIP_RX_HEADER;
}
}
break;
case GRIP_RX_HEADER:
// Check if header is available
if(ComIf_DataAvailable() > (GRIP_HEADER_SIZE-1))
{
uint8_t head_buff[GRIP_HEADER_SIZE] = {0};
// Get header
ComIf_Receive(head_buff, GRIP_HEADER_SIZE);
// Fill struct
memcpy(&RX_Buff[GrIP_idx].RX_Header, head_buff, GRIP_HEADER_SIZE);
// Convert length to host order
RX_Buff[GrIP_idx].RX_Header.Length = ntohs(RX_Buff[GrIP_idx].RX_Header.Length);
// Check if header is valid
uint8_t ret = CheckHeader(&RX_Buff[GrIP_idx].RX_Header);
if(ret != RET_OK)
{
// Header is invalid
GrIP_Status = GRIP_IDLE;
//Printf("Wrong header: %d\n", ret);
break;
}
if(RX_Buff[GrIP_idx].RX_Header.Length > GRIP_BUFFER_SIZE)
{
// Payload too big
GrIP_Status = GRIP_IDLE;
//Printf("Payload exceeds limit: %d\n", RX_Buff[GrIP_idx].RX_Header.Length);
break;
}
// If payload is available
if(RX_Buff[GrIP_idx].RX_Header.Length)
{
// Payload is available
GrIP_Status = GRIP_RX_DATA;
}
else
{
// No payload
GrIP_Status = GRIP_IDLE;
RX_Buff[GrIP_idx].isValid = 1;
if(GrIP_idx < (GRIP_RX_NUM-1))
{
GrIP_idx++;
}
else
{
GrIP_idx = 0;
}
}
}
break;
case GRIP_RX_DATA:
// Check if entire payload is available
if(ComIf_DataAvailable() > (RX_Buff[GrIP_idx].RX_Header.Length-1))
{
// Get payload
//GenIf_Receive(RX_Buffer, RX_Header.Length);
ComIf_Receive(RX_Buff[GrIP_idx].Data, RX_Buff[GrIP_idx].RX_Header.Length);
if(RX_Buff[GrIP_idx].RX_Header.CRC8 == CRC_CalculateCRC8(RX_Buff[GrIP_idx].Data, RX_Buff[GrIP_idx].RX_Header.Length))
{
RX_Buff[GrIP_idx].isValid = 1;
if(GrIP_idx < (GRIP_RX_NUM-1))
{
GrIP_idx++;
}
else
{
GrIP_idx = 0;
}
}
GrIP_Status = GRIP_IDLE;
}
break;
}
// Check for new data
ComIf_Update();
}
static uint8_t CheckHeader(GrIP_PacketHeader_t *paket)
{
if(paket->Version != GRIP_VERSION)
{
// Wrong version
return RET_WRONG_VERSION;
}
if(paket->MsgType >= MSG_MAX_NUM)
{
// Wrong message type
return RET_WRONG_TYPE;
}
// Everything OK
return RET_OK;
}

Wyświetl plik

@ -0,0 +1,154 @@
/*
GrIP.h - GRBL over IP
Copyright (c) 2018-2019 Patrick F.
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 program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRIP_H_INCLUDED
#define GRIP_H_INCLUDED
#include <stdint.h>
// Current protocol version
#define GRIP_VERSION 1
// Transmit/Receive buffer size - Do not exceed (GRIP_BUFFER_SIZE - 10)
#define GRIP_BUFFER_SIZE 256
#define GRIP_RX_NUM 3
#ifdef __cplusplus
extern "C" {
#endif
/**
* Available message types.
*
*/
typedef enum
{
MSG_SYSTEM_CMD = 0,
MSG_REALTIME_CMD = 1,
MSG_DATA = 2,
MSG_DATA_NO_RESPONSE = 3,
MSG_NOTIFICATION = 4,
MSG_RESPONSE = 5,
MSG_ERROR = 6,
MSG_MAX_NUM = 7
} MessageType_e;
/**
* Return Types.
*
*/
typedef enum
{
RET_OK = 0,
RET_NOK = 1,
RET_WRONG_VERSION = 2,
RET_WRONG_CRC = 3,
RET_WRONG_MAGIC = 4,
RET_WRONG_PARAM = 5,
RET_WRONG_TYPE = 6
} ReturnType_e;
/**
* Types for response status.
*
*/
typedef enum
{
RESPONSE_OK = 0,
RESPONSE_WAIT = 1,
RESPONSE_FAIL = 2
} ResponseStatus_e;
/**
* GrIP Packet Header
*/
#pragma pack(push, 1)
typedef struct
{
uint8_t Version;
uint8_t MsgType;
uint8_t ReturnCode;
uint16_t Length;
uint8_t CRC8;
uint8_t Counter;
} GrIP_PacketHeader_t;
#pragma pack(pop)
/**
* GrIP Receive Packet
*/
typedef struct
{
GrIP_PacketHeader_t RX_Header;
uint8_t isValid;
uint8_t Data[GRIP_BUFFER_SIZE];
} RX_Packet_t;
/**
* Data struct.
* Data: Pointer to data.
* Length: Length of data in bytes.
*/
typedef struct
{
uint8_t *Data;
uint16_t Length;
} Pdu_t;
/**
* Initialize the module
*/
void GrIP_Init(void);
/**
* Transmit a message over GrIP
*/
uint8_t GrIP_Transmit(uint8_t MsgType, uint8_t ReturnCode, Pdu_t *data);
/**
* Returns the current response state
*/
uint8_t GrIP_ResponseStatus(void);
/**
* Get data if available
*/
uint8_t GrIP_Receive(RX_Packet_t *pData);
/**
* Continuously call this function to process RX messages
*/
void GrIP_Update(void);
#ifdef __cplusplus
}
#endif
#endif // GRIP_H_INCLUDED

Wyświetl plik

@ -25,7 +25,7 @@
// USART used for Printf(...)
#define STDOUT USART2
#define STDOUT_NUM USART2_NUM
#define STDOUT_BAUD 230400
//#define STDOUT_BAUD 115200
//---- Defines ----//

Wyświetl plik

@ -7,6 +7,7 @@
#include "USART.h"
#include "FIFO_USART.h"
#include "Settings.h"
#include "GrIP.h"
#include "Platform.h"

Wyświetl plik

@ -31,6 +31,10 @@
#include "Protocol.h"
#include "MotionControl.h"
#include "GrIP.h"
#include "Platform.h"
#include "ServerTCP.h"
#include "Print.h"
@ -254,8 +258,24 @@ void Protocol_AutoCycleStart(void)
// limit switches, or the main program.
void Protocol_ExecuteRealtime(void)
{
RX_Packet_t packet;
Protocol_ExecRtSystem();
#ifdef ETH_IF
GrIP_Update();
if(GrIP_Receive(&packet))
{
for(int i = 0; i < packet.RX_Header.Length; i++)
{
ProcessReceive(packet.Data[i]);
}
}
ServerTCP_Update();
#else
(void)packet;
#endif
if(sys.suspend) {
Protocol_ExecRtSuspend();
}

Wyświetl plik

@ -409,6 +409,9 @@ void Report_GCodeModes(void)
report_util_gcode_modes_G();
Printf("%d", 94-gc_state.modal.feed_rate);
report_util_gcode_modes_G();
Printf("%d", 98+gc_state.modal.retract);
if(gc_state.modal.program_flow) {
report_util_gcode_modes_M();

27
main.c
Wyświetl plik

@ -23,9 +23,15 @@
#include "System32.h"
#include "grbl_advance.h"
#include "Ethernet.h"
#include "GrIP.h"
#include "ServerTCP.h"
#include "util2.h"
#include "Print.h"
#include "FIFO_USART.h"
#include "ComIf.h"
#include "Platform.h"
// Declare system global variable structure
@ -38,6 +44,16 @@ volatile uint8_t sys_rt_exec_alarm; // Global realtime executor bitflag variab
volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides.
volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
#ifdef ETH_IF
uint8_t MAC[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// IP Address of tcp server
IPAddress_t IP = {{192, 168, 1, 20}};
IPAddress_t GatewayIP = {{192, 168, 1, 1}};
IPAddress_t SubnetMask = {{255, 255, 255, 0}};
IPAddress_t MyDns = {{8, 8, 8, 8}};
#endif
int main(void)
{
@ -50,6 +66,17 @@ int main(void)
System_ResetPosition();
#ifdef ETH_IF
// Initialize W5500
Ethernet_Init(MAC, &IP, &MyDns, &GatewayIP, &SubnetMask);
// Initialize TCP server
ServerTCP_Init(ETH_SOCK, ETH_PORT);
#endif
// Initialize GrIP protocol
GrIP_Init();
// Init SysTick 1ms
SysTick_Init();