Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • arp
  • arp-gyro
  • async-fsm
  • cc3135
  • chipselect-mux
  • logger-V2
  • main
  • mockup-main-software
  • nas-catch-dev
  • nd015x-dma
  • nokia-tm-dev
  • parafoil-mavlink-upd
  • quadspi-flash
  • quadspi-flash2
  • spi
  • spi-transaction-dma
  • sx1278-resilience
  • units-impl
  • ARP-pre-2.7
  • PYXIS_EUROC
  • PYXIS_ROCCARASO
  • hermes-flight-1
  • hermes-v1.0
  • lynx-euroc
24 results

Target

Select target project
  • avn/swd/skyward-boardcore
  • emilio.corigliano/skyward-boardcore
  • ettore.pane/skyward-boardcore
  • giulia.facchi/skyward-boardcore
  • valerio.flamminii/skyward-boardcore
  • nicolo.caruso/skyward-boardcore
6 results
Select Git revision
  • ASM330LHH-dev
  • LSM9DS1-test
  • Lis3mdl-bugfix
  • ads131m08
  • aspis-dev
  • build-system
  • cc3135
  • clang
  • clang-support-dev
  • f769-disco
  • hil-upd
  • kalman-fix
  • lps22df-dev
  • lps28dfw
  • lsm6dsrx
  • main
  • neo-m6
  • parafoil
  • parafoil-f103-SDlog
  • parafoil-sensortile
  • rd-gs-nas-extractor
  • stepper-logging-upd
  • sx1278
  • tfmicro-dev
  • timed-wait
  • timed-wait2
  • ubxgps-serial-upd
  • vcm
  • vl53l7cxa-dev
  • vn100-upd
  • vn300
  • PYXIS_EUROC
  • PYXIS_ROCCARASO
  • hermes-flight-1
  • hermes-v1.0
  • lynx-euroc
36 results
Show changes
Showing
with 0 additions and 4308 deletions
/* Copyright (c) 2016-2017 Skyward Experimental Rocketry
* Author: Silvano Seva
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "PacketBuffer.h"
#include <utils/Debug.h>
using namespace std;
using namespace miosix;
PacketBuffer::PacketBuffer(size_t storageSize)
: storageSize(storageSize), usedSize(0), writeIndex(0), readIndex(0),
valid(true)
{
#ifndef __NO_EXCEPTIONS
try
{
buffer = new uint8_t[storageSize];
}
catch (std::bad_alloc& exc)
{
TRACE("bad alloc!\n");
valid = false;
}
#else
buffer = new (std::nothrow) uint8_t[storageSize];
if (buffer == nullptr)
{
valid = false;
}
#endif
}
PacketBuffer::~PacketBuffer()
{
if (valid)
delete[] buffer;
}
bool PacketBuffer::push(packet_header_t& header, const uint8_t* payload)
{
if (!valid)
return false;
size_t packetSize = sizeof(packet_header_t) + header.payloadSize;
// Simple technique to avoid ring buffer writeIndex slip ahead readIndex:
// we keep track of the amount of space used and we reject a new incoming
// packet if usedSize + packetSize is greater that the ring buffer size.
if (usedSize + packetSize >= storageSize)
return false;
// to store the packet into the ring buffer first copy the header
// and then copy the payload
{
Lock<FastMutex> l(mutex);
uint8_t* head = reinterpret_cast<uint8_t*>(&header);
for (unsigned int i = 0; i < sizeof(packet_header_t); i++)
{
buffer[(writeIndex + i) % storageSize] = head[i];
}
writeIndex = (writeIndex + sizeof(packet_header_t)) % storageSize;
for (unsigned int i = 0; i < header.payloadSize; i++)
{
buffer[(writeIndex + i) % storageSize] = payload[i];
}
writeIndex = (writeIndex + header.payloadSize) % storageSize;
usedSize += packetSize;
}
return true;
}
packet_header_t PacketBuffer::getHeader()
{
packet_header_t header = {};
uint8_t* dest = reinterpret_cast<uint8_t*>(&header);
memset(dest, 0x00, sizeof(packet_header_t));
if (valid)
{
Lock<FastMutex> l(mutex);
for (unsigned int i = 0; i < sizeof(packet_header_t); i++)
dest[i] = buffer[(readIndex + i) % storageSize];
}
return header;
}
void PacketBuffer::getData(uint8_t* data)
{
if (!valid)
return;
/* Packet size is stored in header, so first get the payloadSize.
* The data is stored sizeof(packet_header_t) bytes next the read pointer,
* since a packet is stored as header followed by payload, so we have to
* add sizeof(packet_header_t) to the read pointer to reach the first data
* byte
*/
packet_header_t frontHead = getHeader();
{
Lock<FastMutex> l(mutex);
int start = readIndex + sizeof(packet_header_t);
for (unsigned int i = 0; i < frontHead.payloadSize; i++)
{
data[i] = buffer[(start + i) % storageSize];
}
}
}
void PacketBuffer::popFront()
{
if ((!valid) || empty()) // this means that list is empty
return;
/* Popping a packet out of list simply means move the readIndex forward
* of the size of the packet at list's head.
* The size of a packet is made of two parts: a fixed one which is
* constituded by the size of IP address, port and packet length fields
* and a variable one that is the size of the payload. The latter is stored
* into the len field of the packet.
* What we do here is gather the fixed and variable sizes and sum them
* together to obtain the readIndex's needed increment
*/
packet_header_t head = getHeader();
size_t packetSize = sizeof(packet_header_t) + head.payloadSize;
{
Lock<FastMutex> l(mutex);
readIndex = (readIndex + packetSize) % storageSize;
usedSize -= packetSize;
}
}
bool PacketBuffer::empty()
{
Lock<FastMutex> l(mutex);
return usedSize == 0;
}
/* Copyright (c) 2016-2017 Skyward Experimental Rocketry
* Author: Silvano Seva
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "UdpManager.h"
using namespace std;
using namespace miosix;
void __attribute__((naked)) EXTI1_IRQHandler()
{
saveContext();
asm volatile("bl _Z13EXTIrqHandlerv");
restoreContext();
}
void __attribute__((used)) EXTIrqHandler()
{
EXTI->PR |= EXTI_PR_PR1;
Singleton<UdpManager>::getInstance().phyIrqHandler();
}
void _evt_mgmt_thread(void* args)
{
Singleton<UdpManager>::getInstance().evtQueue.run();
}
UdpManager::UdpManager()
{
eth::int1::mode(Mode::INPUT);
// Configure STM32 to generate an interrupt on
// falling edge of chip's INT line
{
FastInterruptDisableLock dLock;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
RCC_SYNC();
}
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI1_PC;
EXTI->IMR |= EXTI_IMR_MR1;
EXTI->FTSR |= EXTI_FTSR_TR1;
NVIC_SetPriority(EXTI1_IRQn, 10);
NVIC_ClearPendingIRQ(EXTI1_IRQn);
NVIC_EnableIRQ(EXTI1_IRQn);
phy.setModeReg(0x00);
phy.setSocketInterruptMask(0xFF);
txBuffer = new PacketBuffer(TX_BUF_SIZE);
rxBuffer = new PacketBuffer(RX_BUF_SIZE);
wdt->setDuration(TX_TIMEOUT);
wdt->setCallback(bind(&UdpManager::wdtIrqHandler, this));
if (!txBuffer->isValid() || !rxBuffer->isValid())
{
// TODO log!
}
else
{
Thread::create(_evt_mgmt_thread, 1024);
}
}
UdpManager::~UdpManager()
{
delete txBuffer;
delete rxBuffer;
}
void UdpManager::setTxPort(uint16_t port)
{
// Open transmitting socket
phy.setSocketModeReg(PHY_TX_SOCK_NUM, SOCKn_MR_UDP);
phy.setSocketSourcePort(PHY_TX_SOCK_NUM, port);
// Enable timeout & send ok interrupts
phy.setSocketInterruptMaskReg(PHY_TX_SOCK_NUM, 0x18);
phy.setSocketCommandReg(PHY_TX_SOCK_NUM, SOCKn_CR_OPEN);
}
void UdpManager::setRxPort(uint16_t port)
{
// Open receiving socket
phy.setSocketModeReg(PHY_RX_SOCK_NUM, SOCKn_MR_UDP);
phy.setSocketSourcePort(PHY_RX_SOCK_NUM, port);
// Enable recv interrupt only
phy.setSocketInterruptMaskReg(PHY_RX_SOCK_NUM, 0x04);
phy.setSocketCommandReg(PHY_RX_SOCK_NUM, SOCKn_CR_OPEN);
phy.setSocketCommandReg(PHY_RX_SOCK_NUM, SOCKn_CR_RECV);
}
/** Legacy code, uncomment if we want tx @ port and rx @ port+1 **/
// void UdpManager::setPort(uint16_t port) {
//
// //Open transmitting socket
// phy.setSocketModeReg(PHY_TX_SOCK_NUM,SOCKn_MR_UDP);
// phy.setSocketSourcePort(PHY_TX_SOCK_NUM,port);
// // Enable timeout & send ok interrupts
// phy.setSocketInterruptMaskReg(PHY_TX_SOCK_NUM,0x18);
// phy.setSocketCommandReg(PHY_TX_SOCK_NUM,SOCKn_CR_OPEN);
//
// //Open receiving socket
// phy.setSocketModeReg(PHY_RX_SOCK_NUM,SOCKn_MR_UDP);
// phy.setSocketSourcePort(PHY_RX_SOCK_NUM,port+1);
// // Enable recv interrupt only
// phy.setSocketInterruptMaskReg(PHY_RX_SOCK_NUM,0x04);
// phy.setSocketCommandReg(PHY_RX_SOCK_NUM,SOCKn_CR_OPEN);
// phy.setSocketCommandReg(PHY_RX_SOCK_NUM,SOCKn_CR_RECV);
// }
bool UdpManager::newReceivedPackets() { return !rxBuffer->empty(); }
void UdpManager::sendPacketTo(const uint8_t* ip, const uint16_t port,
const void* data, size_t len)
{
packet_header_t header;
header.ipAddress = *(reinterpret_cast<const uint32_t*>(ip));
header.port = port;
header.payloadSize = len;
bool wasEmpty = txBuffer->empty();
bool ok = txBuffer->push(header, reinterpret_cast<const uint8_t*>(data));
if (!ok)
{
// TODO: better failure logging
puts("UDP->sendPacketTo: failed to enqueue the new packet\n");
}
else if (wasEmpty)
{
bool pok =
evtQueue.postNonBlocking(bind(&UdpManager::tx_handler, this));
if (!pok)
{
// TODO: better failure logging
puts(
"UDP->sendPacketTo: job queue full."
"Failed to post tx_handler.\n");
}
}
}
size_t UdpManager::recvPacketSize()
{
if (rxBuffer->empty())
return 0;
packet_header_t hdr = rxBuffer->getHeader();
return hdr.payloadSize;
}
void UdpManager::readPacket(uint8_t* ip, uint16_t& port, void* data)
{
packet_header_t header = rxBuffer->getHeader();
// IP address is 4 bytes long
memcpy(ip, reinterpret_cast<uint8_t*>(&(header.ipAddress)), 4);
port = header.port;
// The copy of the exact number of bytes is guaranteed by getData. We only
// have to be sure that the receiving buffer has the right capacity,
// which is given by UdpManager::recvPacketSize()
rxBuffer->getData(reinterpret_cast<uint8_t*>(data));
rxBuffer->popFront();
}
/** Interrupt and event handlers **/
void UdpManager::phyIrqHandler()
{
bool hppw = false;
uint8_t sockInt = phy.readSocketInterruptReg();
// TX socket interrupts management
if (sockInt & (0x01 << PHY_TX_SOCK_NUM))
{
// Stopping watchdog inside an IRQ is safe to do
wdt->stop();
uint8_t txFlags = phy.getSocketInterruptReg(PHY_TX_SOCK_NUM);
phy.clearSocketInterruptReg(PHY_TX_SOCK_NUM);
// Send OK interrupt flag set
if (txFlags & 0x10)
evtQueue.IRQpost(bind(&UdpManager::tx_end_handler, this), hppw);
// Timeout flag set, problems with ARP
if (txFlags & 0x08)
evtQueue.IRQpost(bind(&UdpManager::timeout_handler, this), hppw);
}
// RX socket interrupts management
if (sockInt & (0x01 << PHY_RX_SOCK_NUM))
{
uint8_t rxFlags = phy.getSocketInterruptReg(PHY_RX_SOCK_NUM);
phy.clearSocketInterruptReg(PHY_RX_SOCK_NUM);
if (rxFlags & 0x04)
evtQueue.IRQpost(bind(&UdpManager::rx_handler, this), hppw);
}
if (hppw)
Scheduler::IRQfindNextThread();
}
void UdpManager::wdtIrqHandler()
{
bool hppw = false;
evtQueue.IRQpost(bind(&UdpManager::timeout_handler, this), hppw);
if (hppw)
Scheduler::IRQfindNextThread();
}
void UdpManager::tx_handler()
{
if (txBuffer->empty())
return;
packet_header_t header = txBuffer->getHeader();
uint8_t* addr = reinterpret_cast<uint8_t*>(&header.ipAddress);
uint8_t payload[header.payloadSize];
txBuffer->getData(payload);
txBuffer->popFront();
phy.setSocketDestIp(PHY_TX_SOCK_NUM, addr);
phy.setSocketDestPort(PHY_TX_SOCK_NUM, header.port);
phy.writeData(PHY_TX_SOCK_NUM, payload, header.payloadSize);
phy.setSocketCommandReg(PHY_TX_SOCK_NUM, SOCKn_CR_SEND);
wdt->clear();
wdt->start();
}
void UdpManager::tx_end_handler()
{
if (txBuffer->empty())
return;
bool ok = evtQueue.postNonBlocking(bind(&UdpManager::tx_handler, this));
if (!ok)
{
// TODO: better failure logging
puts("UDP->tx_end_handler:job queue full, failed to post tx_handler");
}
}
void UdpManager::timeout_handler()
{
if (wdt->expired())
puts("Tx timeout due to watchdog expiration");
else
puts("Tx timeout due to phy error");
bool ok = evtQueue.postNonBlocking(bind(&UdpManager::tx_end_handler, this));
if (!ok)
puts(
"UDP->timeout_handler: job queue full, "
"failed to post tx_end_handler");
}
void UdpManager::rx_handler()
{
// get new packet len, in bytes
uint16_t len = phy.getReceivedSize(PHY_RX_SOCK_NUM);
uint8_t buffer[len];
// read all the packet, that is made of so30urceIp + sourcePort +
// payload len + payload. Since the header length is of 8 bytes,
// the payload length is len - 8 bytes! :-)
phy.readData(PHY_RX_SOCK_NUM, buffer, len);
// Set back to listening mode
phy.setSocketCommandReg(PHY_RX_SOCK_NUM, SOCKn_CR_RECV);
packet_header_t header;
memcpy(reinterpret_cast<uint8_t*>(&(header.ipAddress)), buffer, 4);
header.port = (buffer[4] << 8) | buffer[5];
header.payloadSize = len - 8;
bool pushOk = rxBuffer->push(header, &buffer[8]);
if (!pushOk)
puts(
"rx_handler error: rxBuffer is full,"
"cannot enqueue a new packet!");
}
/* Copyright (c) 2016-2017 Skyward Experimental Rocketry
* Author: Silvano Seva
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <Common.h>
#include <Singleton.h>
#include <W5200/w5200.h>
#include <e20/e20.h>
#include "PacketBuffer.h"
#include "WatchdogTimer.h"
class UdpManager : Singleton<UdpManager>
{
friend class Singleton<UdpManager>;
public:
/**
* Open a transmitting UDP socket which source port is @param port
*/
void setTxPort(uint16_t port);
/**
* Open a receiving UDP socket that will listen on @param port, listening
* starts as soon as this function is called
*/
void setRxPort(uint16_t port);
/**
* Send an UDP packet.
* @param ip: destination IP address
* @param port: destination port
* @param data: pointer to payload data
* @param len: payload lenght in bytes
*/
void sendPacketTo(const uint8_t* ip, const uint16_t port, const void* data,
size_t len);
/**
* @return true if there are new packets in the rx buffer
*/
bool newReceivedPackets();
/**
* @return payload size of the packet stored at the head of the internal
* buffer, in other words the packet that will be read if readPacket() is
* called.
*/
size_t recvPacketSize();
/**
* Read the packet placed at rx buffer's head popping it out of the queue.
* @param ip: source ip address
* @param port: source port
* @param data: pointer to a buffer in which store the payload data. It must
* have a size greater than or equal to that returned by recvPacketSize()
*/
void readPacket(uint8_t* ip, uint16_t& port, void* data);
/**
* IRQ handler for interrupts coming from the phy interface chip
* WARNING: DON'T call this!!
*/
void phyIrqHandler();
/**
* IRQ handler for interrupts coming from the tx watchdog timer
* WARNING: DON'T call this!!
*/
void wdtIrqHandler();
private:
// TX timeout time, in ms
static constexpr unsigned int TX_TIMEOUT = 500; // 500ms timeout
// Size of the event queue, used for event handling
static constexpr unsigned int EVT_QUEUE_SIZE = 20;
// Size of buffer used to store packets still to be sent, IN BYTES
static constexpr unsigned int TX_BUF_SIZE = 100000;
// Size of buffer used to store packets received, IN BYTES
static constexpr unsigned int RX_BUF_SIZE = 100000;
// TX and RX socket number, used by the phy interface
static constexpr uint8_t PHY_TX_SOCK_NUM = 0;
static constexpr uint8_t PHY_RX_SOCK_NUM = 1;
miosix::FixedEventQueue<EVT_QUEUE_SIZE> evtQueue;
PacketBuffer* txBuffer;
PacketBuffer* rxBuffer;
W5200& phy = W5200::instance();
WatchdogTimer* wdt = Singleton<WatchdogTimer>::getInstance();
// Function used by the event management thread
friend void _evt_mgmt_thread(void* args);
void tx_handler(); //< Tx event handler function
void tx_end_handler(); //< Tx end event handler function
void rx_handler(); //< New packet Rx handler function
void timeout_handler(); //< Tx timeout handler function
UdpManager();
UdpManager(const UdpManager& other);
UdpManager& operator=(const UdpManager& other);
~UdpManager();
};
/* Copyright (c) 2015-2016 Skyward Experimental Rocketry
* Author: Silvano Seva
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "spi_impl.h"
using namespace miosix;
void Spi_init()
{
eth::sck::mode(Mode::ALTERNATE);
eth::sck::alternateFunction(5);
eth::miso::mode(Mode::ALTERNATE);
eth::miso::alternateFunction(5);
eth::mosi::mode(Mode::ALTERNATE);
eth::mosi::alternateFunction(5);
eth::cs::mode(Mode::OUTPUT);
RCC->APB2ENR |= RCC_APB2ENR_SPI5EN;
RCC_SYNC();
// APB bus frequency is 90MHz, so leaving the BR[2:0] bits
// in CR1 makes the SPI clock frequency to be 45MHz
SPI5->CR1 = SPI_CR1_SSM // CS handled in software
| SPI_CR1_SSI // Internal CS high
| SPI_CR1_SPE // SPI enabled
| SPI_CR1_MSTR; // Master mode
}
unsigned char Spi_sendRecv(unsigned char data)
{
SPI5->DR = data;
while ((SPI5->SR & SPI_SR_RXNE) == 0)
; // Wait
return SPI5->DR;
}
void Spi_CS_high() { eth::cs::high(); }
void Spi_CS_low() { eth::cs::low(); }
This diff is collapsed.
This diff is collapsed.
/* Copyright (c) 2016-2017 Skyward Experimental Rocketry
* Author: Silvano Seva
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include <cstdint>
#include <cstdio>
// UDP packet header descriptor
typedef struct __attribute__((packed))
{
uint32_t ipAddress;
uint16_t port;
size_t payloadSize;
} packet_header_t;
This diff is collapsed.
This diff is collapsed.
/* Copyright (c) 2017 Skyward Experimental Rocketry
* Author: Silvano Seva
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "Common.h"
namespace modbus
{
static constexpr uint8_t EXC_ILLEGAL_FUN = 0x01; ///< Illegal function
static constexpr uint8_t EXC_ILLEGAL_ADDR = 0x02; ///< Illegal data address
static constexpr uint8_t EXC_ILLEGAL_VAL = 0x03; ///< Illegal data value
static constexpr uint8_t EXC_SLAVE_FAILURE = 0x04; ///< Slave internal failure
static constexpr uint8_t ACKNOWLEDGE = 0x05; ///< Acknowledge
static constexpr uint8_t SLAVE_BUSY = 0x06; ///< Slave busy
static constexpr uint8_t EXC_MEM_PARITY = 0x08; ///< Memory parity error
} // namespace modbus
This diff is collapsed.
This diff is collapsed.