Skip to content

Commit

Permalink
Improve luos_phy.h public interface and adapt robus and Serial
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-rabault committed Jul 25, 2023
1 parent d316b66 commit 95ea3d8
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 55 deletions.
3 changes: 2 additions & 1 deletion engine/IO/inc/_luos_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ void Phy_ResetAll(void);
bool Phy_Busy(void);
void Phy_Loop(void);
luos_phy_t *Phy_Get(uint8_t id, JOB_CB job_cb, RUN_TOPO run_topo, RESET_PHY reset_phy);
error_return_t Phy_FindNextNode(void); // Use it to find the next node as a master.
error_return_t Phy_FindNextNode(void); // Use it to find the next node as a master.
phy_job_t *Phy_GetNextJob(luos_phy_t *phy_ptr, phy_job_t *job); // Use it to get the next job to send.

#endif /* _PRIVATE_LUOS_PHY_H_ */
20 changes: 11 additions & 9 deletions engine/IO/inc/luos_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,27 @@ void Phy_SetIrqStateFunciton(IRQ_STATE irq_state); // Use it to reference your p
void Phy_SetIrqState(bool state); // Use it to globally enable/disable all the phy irq.

// Phy creation
luos_phy_t *Phy_Create(JOB_CB phy_cb, RUN_TOPO run_topo, RESET_PHY reset_phy); // Use it to reference your phy to Luos.
luos_phy_t *Phy_Create(JOB_CB job_cb, RUN_TOPO run_topo, RESET_PHY reset_phy); // Use it to reference your phy to Luos.

// Topology management
void Phy_FindNextNodeJob(void); // Use it to find the next node that need to be detected accross phys.
void Phy_Topologysource(luos_phy_t *phy_ptr, uint8_t port_id); // The phy will call this function when a new node is detected on a specific port.
void Phy_TopologyNext(void); // Use it to find the next node that need to be detected accross phys.
void Phy_TopologySource(luos_phy_t *phy_ptr, uint8_t port_id); // The phy will call this function when a new node is detected on a specific port.
void Phy_TopologyDone(luos_phy_t *phy_ptr); // The phy will call this function when all its port detection are done.

// Rx management
void Phy_ComputeHeader(luos_phy_t *phy_ptr); // After receiving the first 7 bytes (the header) call this function to compute how you should manage the incoming message.
void Phy_ValidMsg(luos_phy_t *phy_ptr); // After receiving as much valid bytes as phy_ptr.rx_size, call this function to validate the message.
void Phy_ResetMsg(luos_phy_t *phy_ptr); // Call this function to reset the rx process.

// Tx management
time_luos_t Phy_ComputeTimestamp(phy_job_t *job);
uint16_t Phy_GetNodeId(void);
time_luos_t Phy_ComputeMsgTimestamp(phy_job_t *job); // Use it to compute the timestamp of the message to send.
time_luos_t Phy_GetTimestamp(void); // Use it to get the current timestamp.
uint16_t Phy_GetNodeId(void); // Use it to get your current node id. (This can be used to compute priority or controled latency avoiding infinite collision condition)

// Job management
void Phy_DeadTargetSpotted(luos_phy_t *phy_ptr, phy_job_t *job); // If some messages failed to be sent, call this function to consider the target as dead
phy_job_t *Phy_GetJob(luos_phy_t *phy_ptr); // Use it to get the first job to send.
phy_job_t *Phy_GetNextJob(luos_phy_t *phy_ptr, phy_job_t *job); // Use it to get the next job to send.
void Phy_RmJob(luos_phy_t *phy_ptr, phy_job_t *job); // Use it to remove a job from your phy job list when it's done.
void Phy_FailedJob(luos_phy_t *phy_ptr, phy_job_t *job); // If some messages failed to be sent, call this function to consider the target as dead
phy_job_t *Phy_GetJob(luos_phy_t *phy_ptr); // Use it to get the first job to send.
void Phy_RmJob(luos_phy_t *phy_ptr, phy_job_t *job); // Use it to remove a job from your phy job list when it's done.
uint16_t Phy_GetJobNumber(luos_phy_t *phy_ptr); // Use it to get the number of job to send.

#endif /* _LUOS_PHY_H_ */
5 changes: 3 additions & 2 deletions engine/IO/inc/struct_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "struct_luos.h"
#include "time_luos.h"

/*******************************************************************************
* Definitions
Expand Down Expand Up @@ -46,8 +47,8 @@ typedef uint8_t phy_target_t;
typedef struct luos_phy_t
{
// *************** RX information ***************
volatile int64_t rx_timestamp; // Timestamp of the last received message. We will use it to compute the date based on received latency.
uint8_t *rx_buffer_base; // Pointer to the base of the buffer where we will store the begining of received data.
volatile time_luos_t rx_timestamp; // Timestamp of the last received message. We will use it to compute the date based on received latency.
uint8_t *rx_buffer_base; // Pointer to the base of the buffer where we will store the begining of received data.
union
{
volatile uint8_t *rx_data; // Pointer to write received bytes.
Expand Down
2 changes: 1 addition & 1 deletion engine/IO/src/luos_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ error_return_t LuosIO_ConsumeMsg(const msg_t *input)
Luos_SendMsg(service, &output_msg);
// This message can't be send directly to avoid dispatch re-entrance issue.
// To be able to send this message then run the detection of the other nodes we need to make it later on the LuosIO_Loop, so we put a flag for it.
Phy_FindNextNodeJob();
Phy_TopologyNext();
// This message have been consumed
return SUCCEED;
break;
Expand Down
55 changes: 47 additions & 8 deletions engine/IO/src/luos_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ void Phy_Loop(void)

/******************************************************************************
* @brief Instanciate a physical layer
* @param phy_cb callback to call when we want to transmit a message
* @param job_cb callback to call when we want to transmit a message
* @param run_topo callback to call when we want to run the topology detection
* @param reset_phy callback to call when we want to reset the phy
* @return None
******************************************************************************/
luos_phy_t *Phy_Create(JOB_CB job_cb, RUN_TOPO run_topo, RESET_PHY reset_phy)
Expand Down Expand Up @@ -259,7 +261,7 @@ void Phy_SetIrqState(bool state)
* @brief save a flag allowing to run a new discovering outside of IRQ (because this function is very long and can't be run in IRQ)
* @return None
******************************************************************************/
_CRITICAL void Phy_FindNextNodeJob(void)
_CRITICAL void Phy_TopologyNext(void)
{
phy_ctx.find_next_node_job = true;
}
Expand Down Expand Up @@ -341,7 +343,7 @@ error_return_t Phy_FindNextNode(void)
* @param port_id id of the port detected in the phy
* @return None
******************************************************************************/
void Phy_Topologysource(luos_phy_t *phy_ptr, uint8_t port_id)
void Phy_TopologySource(luos_phy_t *phy_ptr, uint8_t port_id)
{
LUOS_ASSERT((phy_ptr != NULL)
&& (port_id < 0xFF));
Expand Down Expand Up @@ -374,7 +376,9 @@ port_t *Phy_GetTopologysource(void)
/******************************************************************************
* @brief return the local physical layer (only used by LuosIO, this function is private)
* @param id of the phy we want
* @param phy_cb callback to call when we want to transmit a message
* @param job_cb callback to call when we want to transmit a message
* @param run_topo callback to call when we want to run a topology detection
* @param reset_phy callback to call when we want to reset the phy
* @return None
******************************************************************************/
luos_phy_t *Phy_Get(uint8_t id, JOB_CB job_cb, RUN_TOPO run_topo, RESET_PHY reset_phy)
Expand Down Expand Up @@ -466,7 +470,7 @@ _CRITICAL void Phy_ValidMsg(luos_phy_t *phy_ptr)
uint16_t my_job = phy_ctx.io_job_nb++;
Phy_SetIrqState(true);
// Now copy the data in the job
phy_ctx.io_job[my_job].timestamp = phy_ptr->rx_timestamp;
phy_ctx.io_job[my_job].timestamp = (uint64_t)TimeOD_TimeTo_ns(phy_ptr->rx_timestamp);
phy_ctx.io_job[my_job].alloc_msg = (msg_t *)phy_ptr->rx_data;
phy_ctx.io_job[my_job].phy_filter = phy_ptr->rx_phy_filter;
phy_ctx.io_job[my_job].size = phy_ptr->rx_size;
Expand All @@ -477,17 +481,41 @@ _CRITICAL void Phy_ValidMsg(luos_phy_t *phy_ptr)
}
}

/******************************************************************************
* @brief Consider the message as failed and reset the phy
* @param phy_ptr Pointer to the phy concerned by the allocation
* @return None
******************************************************************************/
_CRITICAL void Phy_ResetMsg(luos_phy_t *phy_ptr)
{
phy_ptr->received_data = 0;
phy_ptr->rx_size = 0;
phy_ptr->rx_keep = true;
phy_ptr->rx_alloc_job = false;
phy_ptr->rx_data = phy_ptr->rx_buffer_base;
}

/******************************************************************************
* @brief Compute the timestamp to send with the message
* @param job Pointer to the job concerned by this message
* @return None
******************************************************************************/
time_luos_t Phy_ComputeTimestamp(phy_job_t *job)
time_luos_t Phy_ComputeMsgTimestamp(phy_job_t *job)
{
LUOS_ASSERT((job != NULL) && (job->msg_pt != NULL) && (job->timestamp == true));
return Timestamp_ConvertToLatency(job->msg_pt);
}

/******************************************************************************
* @brief Get the current timestamp
* @param None
* @return Timestamp value
******************************************************************************/
_CRITICAL time_luos_t Phy_GetTimestamp(void)
{
return TimeOD_TimeFrom_ns((double)LuosHAL_GetTimestamp());
}

/******************************************************************************
* @brief return the node id
* @return Node ID value
Expand Down Expand Up @@ -625,7 +653,7 @@ static void Phy_Dispatch(void)
* @param job pointer to the job that failed.
* @return None
******************************************************************************/
_CRITICAL void Phy_DeadTargetSpotted(luos_phy_t *phy_ptr, phy_job_t *job)
_CRITICAL void Phy_FailedJob(luos_phy_t *phy_ptr, phy_job_t *job)
{
// A phy failed to send a message, we need to be sure that our node don't try to contact this target again.
LUOS_ASSERT((job != NULL)
Expand Down Expand Up @@ -734,7 +762,7 @@ static phy_job_t *Phy_AddJob(luos_phy_t *phy_ptr, phy_job_t *phy_job)
* @param phy_ptr Phy to get the job from
* @return Job pointer
******************************************************************************/
_CRITICAL inline phy_job_t *Phy_GetJob(luos_phy_t *phy_ptr)
inline phy_job_t *Phy_GetJob(luos_phy_t *phy_ptr)
{
LUOS_ASSERT(phy_ptr != NULL);
if (phy_ptr->job_nb == 0)
Expand Down Expand Up @@ -841,6 +869,17 @@ _CRITICAL void Phy_RmJob(luos_phy_t *phy_ptr, phy_job_t *job)
}
}

/******************************************************************************
* @brief Get the number of job in the phy queue
* @param phy_ptr Phy to get the job number from
* @return None
******************************************************************************/
inline uint16_t Phy_GetJobNumber(luos_phy_t *phy_ptr)
{
LUOS_ASSERT(phy_ptr != NULL);
return phy_ptr->job_nb;
}

/******************************************************************************
* @brief define is there is something waiting to be sent or not
* @return Succeed if nothing is waiting to be sent
Expand Down
6 changes: 3 additions & 3 deletions network/robus_network/src/port_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ _CRITICAL void PortMng_PtpHandler(uint8_t PortNbr)
PortMng_Reset();
}
// Ask Luos_phy to find another node
Phy_FindNextNodeJob();
Phy_TopologyNext();
}
else if (Port_ExpectedState == POKE)
{
Expand All @@ -102,7 +102,7 @@ _CRITICAL void PortMng_PtpHandler(uint8_t PortNbr)
ctx.port.activ = PortNbr;
// This port become the topology source of this node
// Notify luos_phy about it
Phy_Topologysource(Robus_GetPhy(), PortNbr);
Phy_TopologySource(Robus_GetPhy(), PortNbr);
}
}
/******************************************************************************
Expand Down Expand Up @@ -143,7 +143,7 @@ uint8_t PortMng_PokePort(uint8_t PortNbr)

/******************************************************************************
* @brief being poked so poke next node to
* @param None
* @param portId pointer to the port id
* @return true if a port have been poke else false
******************************************************************************/
error_return_t PortMng_PokeNextPort(uint8_t *portId)
Expand Down
12 changes: 4 additions & 8 deletions network/robus_network/src/reception.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,11 @@ uint16_t crc_val = 0; // CRC value
void Recep_Init(luos_phy_t *phy_robus)
{
LUOS_ASSERT(phy_robus != NULL);
LUOS_ASSERT(phy_robus->rx_alloc_job == false);
// Initialize the reception state machine
ctx.rx.status.unmap = 0;
ctx.rx.callback = Recep_GetHeader;
ctx.rx.status.identifier = 0xF;
phy_robus->rx_timestamp = 0;
phy_robus->rx_timestamp = TimeOD_TimeFrom_s(0.0);
phy_robus->rx_buffer_base = data_rx;
phy_robus->rx_data = data_rx;
phy_robus->rx_keep = true;
Expand All @@ -104,7 +103,7 @@ _CRITICAL void Recep_GetHeader(luos_phy_t *phy_robus, volatile uint8_t *data)
// When we catch the first byte we timestamp the msg
// We remove the time of the first byte to get the exact reception date.
// 1 byte is 10 bits and we convert it to nanoseconds
phy_robus->rx_timestamp = LuosHAL_GetTimestamp() - ((uint32_t)10 * (uint32_t)1000000000 / (uint32_t)DEFAULTBAUDRATE);
phy_robus->rx_timestamp = TimeOD_TimeFrom_ns(TimeOD_TimeTo_ns(Phy_GetTimestamp()) - ((uint32_t)10 * (uint32_t)1000000000 / (uint32_t)DEFAULTBAUDRATE));

// Declare Robus as busy
ctx.tx.lock = true;
Expand Down Expand Up @@ -281,11 +280,8 @@ _CRITICAL void Recep_Timeout(void)
******************************************************************************/
_CRITICAL void Recep_Reset(void)
{
luos_phy_t *phy_robus = Robus_GetPhy();
phy_robus->received_data = 0;
phy_robus->rx_size = 0;
phy_robus->rx_keep = true;
phy_robus->rx_alloc_job = false;
luos_phy_t *phy_robus = Robus_GetPhy();
Phy_ResetMsg(phy_robus);
crc_val = 0xFFFF;
ctx.rx.status.rx_framing_error = false;
ctx.rx.status.rx_error = false;
Expand Down
3 changes: 2 additions & 1 deletion network/robus_network/src/robus.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ void Robus_Reset(luos_phy_t *phy_ptr)

/******************************************************************************
* @brief Find the next neighbour on this phy
* @param None
* @param phy_ptr
* @param portId pointer to the portId of the next node
* @return error_return_t
******************************************************************************/
error_return_t Robus_RunTopology(luos_phy_t *phy_ptr, uint8_t *portId)
Expand Down
6 changes: 3 additions & 3 deletions network/robus_network/src/transmission.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ _CRITICAL void Transmit_Process()
if (nbrRetry >= NBR_RETRY)
{
// We failed to transmit this message. We can't allow it, there is an issue on this target.
Phy_DeadTargetSpotted(robus_phy, job);
Phy_FailedJob(robus_phy, job);
nbrRetry = 0;
ctx.tx.collision = false;
// Try to get a new job
Expand Down Expand Up @@ -187,7 +187,7 @@ _CRITICAL void Transmit_Process()
{

// Convert date to a sendable timestamp and put it on the encapsulation
jobEncaps->timestamp = Phy_ComputeTimestamp(job);
jobEncaps->timestamp = Phy_ComputeMsgTimestamp(job);

jobEncaps->timestamped_crc = ll_crc_compute(jobEncaps->unmaped, sizeof(time_luos_t), crc_val);
jobEncaps->size = sizeof(time_luos_t) + CRC_SIZE;
Expand Down Expand Up @@ -243,7 +243,7 @@ _CRITICAL void Transmit_End(void)
luos_phy_t *robus_phy = Robus_GetPhy();
phy_job_t *job = Phy_GetJob(robus_phy);
// We may had a reset during this transmission, so we need to check if we still have something to transmit
if (robus_phy->job_nb > 0)
if (Phy_GetJobNumber(robus_phy) > 0)
{
job->phy_data = 0;
Phy_RmJob(robus_phy, job);
Expand Down
8 changes: 5 additions & 3 deletions network/serial_network/src/serial_network.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ void Serial_Init(void)
Serial_Reset(phy_serial);
SerialHAL_Init(RX_data, SERIAL_RX_BUFFER_SIZE);

phy_serial->rx_timestamp = 0;
phy_serial->rx_timestamp = TimeOD_TimeFrom_s(0.0);
;
phy_serial->rx_buffer_base = RX_data;
phy_serial->rx_data = RX_data; // In our case we don't need to use this pointer because we use DMA to receive complete messages in one time.
phy_serial->rx_keep = true;
Expand Down Expand Up @@ -223,7 +224,7 @@ void Serial_Loop(void)
// We receive this ping from a master node
// This port become the topology source of this node
// Notify luos_phy about it
Phy_Topologysource(phy_serial, SerialHAL_GetPort());
Phy_TopologySource(phy_serial, SerialHAL_GetPort());
// The next ping we send will be a deping
next_ping_is_deping = true;
}
Expand Down Expand Up @@ -302,7 +303,7 @@ _CRITICAL void Serial_TransmissionEnd(void)
sending = false;
// We transmitted this message, we can remove it then send another one
// We may had a reset during this transmission, so we need to check if we still have something to transmit
if (phy_serial->job_nb > 0)
if (Phy_GetJobNumber(phy_serial) > 0)
{
phy_job_t *job = Phy_GetJob(phy_serial);
job->phy_data = 0;
Expand Down Expand Up @@ -362,6 +363,7 @@ _CRITICAL void Serial_ReceptionAdd(uint8_t *data, uint32_t size)
memcpy(RX_data, data + copy_size, size - copy_size);
}
rx_size += size;
LUOS_ASSERT(rx_size < sizeof(RX_data));
if ((wait_reception == true) && (size >= sizeof(SerialHeader_t) + 1))
{
// We received the answer of a topology ping, just indicate that we receive it
Expand Down
Loading

0 comments on commit 95ea3d8

Please sign in to comment.