STM32H750XB_Hello/Middlewares/Third_Party/SystemView/Sample/COMM/SEGGER_SYSVIEW_COMM_IP_embO...

480 lines
16 KiB
C

/*********************************************************************
* SEGGER Microcontroller GmbH *
* The Embedded Experts *
**********************************************************************
* *
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
* *
* www.segger.com Support: support@segger.com *
* *
**********************************************************************
* *
* SEGGER SystemView * Real-time application analysis *
* *
**********************************************************************
* *
* All rights reserved. *
* *
* SEGGER strongly recommends to not make any changes *
* to or modify the source code of this software in order to stay *
* compatible with the SystemView and RTT protocol, and J-Link. *
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* condition is met: *
* *
* o Redistributions of source code must retain the above copyright *
* notice, this condition and the following disclaimer. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
* DAMAGE. *
* *
**********************************************************************
* *
* SystemView version: 3.30 *
* *
**********************************************************************
-------------------------- END-OF-HEADER -----------------------------
File : SEGGER_SYSVIEW_COMM_IP_embOS_emNet.c
Purpose : SystemView Communication for IP Recorder with embOS and emNet.
Revision: $Rev: 15024 $
Additional Information
emNet needs to be initialized by the application, ideally before calling SEGGER_SYSVIEW_X_StartComm.
Example code:
static OS_STACKPTR int _IPStack[TASK_STACK_SIZE_IP_TASK/sizeof(int)]; // Stack of the IP_Task.
static OS_TASK _IPTCB; // Task-Control-Block of the IP_Task.
void MainTask(void) {
//
// Initialize emNet
//
IP_Init();
OS_CREATETASK(&_IPTCB , "IP_Task" , IP_Task , TASK_PRIO_IP_TASK , _IPStack); // Start the IP_Task.
IP_Connect(IP_INFO_GetNumInterfaces() - 1); // Connect the interface if necessary.
//
// Start SystemView communication
//
SEGGER_SYSVIEW_X_StartComm();
...
}
*/
#include "SEGGER_SYSVIEW.h"
#include "SEGGER_SYSVIEW_Conf.h"
#include "SEGGER_RTT.h"
#include "RTOS.h"
#include "IP.h"
#include "IP_Int.h"
/*********************************************************************
*
* Defines, OS
*
**********************************************************************
*/
#define SYSVIEW_COMM_TASK_STACK_SIZE 1024
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
#ifndef SYSVIEW_COMM_TASK_PRIO
#define SYSVIEW_COMM_TASK_PRIO 1 // Priority of the communication task
#endif
#ifndef SYSVIEW_COMM_SEND_THRESHOLD
#define SYSVIEW_COMM_SEND_THRESHOLD 512 // Minimum number of bytes to read and send from the RTT Buffer.
#endif
#ifndef SYSVIEW_COMM_IDLE_DELAY
#define SYSVIEW_COMM_IDLE_DELAY 100 // Delay if no data had to be sent.
#endif
#ifndef SYSVIEW_COMM_POLL_INTERVAL
#define SYSVIEW_COMM_POLL_INTERVAL 2 // Interval to check for buffer level.
#endif
#ifndef SYSVIEW_COMM_SERVER_PORT
#define SYSVIEW_COMM_SERVER_PORT 19111
#endif
#define _NO_NOTIFY
/*********************************************************************
*
* Defines, fixed
*
**********************************************************************
*/
#define SYSVIEW_COMM_SERVER_HELLO_SIZE 4
#define SYSVIEW_COMM_TARGET_HELLO_SIZE 4
/*********************************************************************
*
* Static data, OS
*
**********************************************************************
*/
static OS_STACKPTR int _SysViewCommStack[SYSVIEW_COMM_TASK_STACK_SIZE/sizeof(int)];
static OS_TASK _SysViewCommTCB;
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
static int _ChannelID;
static const U8 _abHelloMsg[SYSVIEW_COMM_TARGET_HELLO_SIZE] = { 'S', 'V', (SEGGER_SYSVIEW_VERSION / 10000), (SEGGER_SYSVIEW_VERSION / 1000) % 10 }; // "Hello" message expected by SysView: [ 'S', 'V', <PROTOCOL_MAJOR>, <PROTOCOL_MINOR> ]
static char _acBuf[SYSVIEW_COMM_SEND_THRESHOLD * 2];
#ifndef _NO_NOTIFY
static unsigned _NumBytesRecorded;
#endif
/*********************************************************************
*
* Local functions, OS
*
**********************************************************************
*/
/*********************************************************************
*
* _Delay
*
* Function description
* Delay for some time.
*
*/
static void _Delay(int Ticks) {
OS_TASK_Delay(Ticks);
}
#ifdef _NO_NOTIFY
/*********************************************************************
*
* _WaitPolling
*
* Function description
* Poll SystemView Buffer to reach threshold fill level.
*
*/
static void _WaitPolling(int Timeout) {
int BytesInBuffer;
do {
BytesInBuffer = SEGGER_RTT_GetBytesInBuffer(_ChannelID);
if (BytesInBuffer >= SYSVIEW_COMM_SEND_THRESHOLD) {
break;
}
_Delay(SYSVIEW_COMM_POLL_INTERVAL);
Timeout -= SYSVIEW_COMM_POLL_INTERVAL;
} while (Timeout > 0);
}
#else
/*********************************************************************
*
* _WaitNotify
*
* Function description
* Wait to be notified or the timeout runs out.
*
*/
static void _WaitNotify(int Timeout) {
OS_TASKEVENT_GetTimed(1, Timeout);
}
/*********************************************************************
*
* _Notify
*
* Function description
* Notify the communication task.
*
*/
static void _Notify(void) {
//
// There might be SystemView Events before the communication task is created.
// Only notify task when it has been created
//
if (OS_TASK_IsTask(&_SysViewCommTCB)) {
OS_TASKEVENT_Set(&_SysViewCommTCB, 1);
}
}
#endif
/*********************************************************************
*
* Local functions, IP
*
**********************************************************************
*/
/*********************************************************************
*
* _WaitForIPInit
*
* Function description
* Wait for IP Stack to be initialized.
*
*/
static void _WaitForIPInit(void) {
while (IP_Global.InitCompleted == 0) {
_Delay(2);
}
}
/*********************************************************************
*
* _ListenAtTcpPort()
*
* Function description
* Creates a socket, binds it to a port and sets the socket into
* listening state.
*
* Parameter
* Port - Port which should be to wait for connections.
*
* Return value
* O.K. : Socket handle.
* Error: SOCKET_ERROR .
*/
static int _ListenAtTcpPort(U16 Port) {
int hSock;
int r;
struct sockaddr_in Addr;
//
// Create socket
//
hSock = socket(AF_INET, SOCK_STREAM, 0);
if (hSock != SOCKET_ERROR) {
//
// Bind it to the port
//
IP_MEMSET(&Addr, 0, sizeof(Addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(Port);
Addr.sin_addr.s_addr = INADDR_ANY;
r = bind(hSock, (struct sockaddr*)&Addr, sizeof(Addr));
//
// Start listening on the socket.
//
if (r != 0) {
hSock = SOCKET_ERROR;
} else {
r = listen(hSock, 1);
if (r != 0) {
hSock = SOCKET_ERROR;
}
}
}
return hSock;
}
/*********************************************************************
*
* _SocketIsReadable
*
* Function description
* Check if data can be read from the connected socket.
*
* Parameters
* hSocket Socket to check.
*
* Return value
* == 1 O.K., socket readable
* == 0 O.K., socket not readable
*/
static int _SocketIsReadable(int hSocket, int TimeoutMs) {
I32 tv = TimeoutMs;
IP_fd_set rfds;
IP_fd_set efds;
int v;
FD_ZERO(&rfds); // Zero init file descriptor list
FD_SET(hSocket, &rfds); // Add socket to file descriptor list to be monitored by select()
FD_ZERO(&efds);
FD_SET(hSocket, &efds);
v = select(&rfds, NULL, &efds, tv); // > 0: in case of success, == 0: Timeout, < 0: Error
return v;
}
/*********************************************************************
*
* Local functions, SystemView Communication
*
**********************************************************************
*/
/*********************************************************************
*
* _SysViewCommTask
*
* Function description
* Task that handles TCP/IP connection and communication
* with SystemView App.
*
*/
static void _SysViewCommTask(void) {
int hSockListen;
int hSockSV;
int v;
int r;
int NumBytes;
char acRecv[16];
//
_ChannelID = SEGGER_SYSVIEW_GetChannelID();
hSockSV = SOCKET_ERROR;
//
// Wait for IP Stack to be initialized.
//
_WaitForIPInit();
//
// Try until we get a valid listening socket.
//
while (1) {
hSockListen = _ListenAtTcpPort(SYSVIEW_COMM_SERVER_PORT);
if (hSockListen == SOCKET_ERROR) {
_Delay(100);
continue; // Error, try again.
}
break;
}
//
// Wait for a connection and process the communication.
//
do {
//
// Check for a new connection.
//
hSockSV = accept(hSockListen, NULL, NULL);
if (hSockSV == SOCKET_ERROR) {
continue; // Error, try again.
}
//
// Successful connection? => Start systemview session
// First, receive <Hello> message from SysView and send back own <Hello> message
//
r = recv(hSockSV, acRecv, SYSVIEW_COMM_SERVER_HELLO_SIZE, 0);
if (r != SYSVIEW_COMM_SERVER_HELLO_SIZE) { // Failed to receive Hello message from SystemView App
closesocket(hSockSV);
hSockSV = SOCKET_ERROR;
}
r = send(hSockSV, (const char*)_abHelloMsg, SYSVIEW_COMM_TARGET_HELLO_SIZE, 0);
if (r != SYSVIEW_COMM_TARGET_HELLO_SIZE) { // Failed to send Hello message to SystemView App
closesocket(hSockSV);
hSockSV = SOCKET_ERROR;
}
//
// After a succesful connection, poll RTT buffer for data
//
while (hSockSV != SOCKET_ERROR) {
#ifdef _NO_NOTIFY
_WaitPolling(SYSVIEW_COMM_IDLE_DELAY); // Wait until there is "enough" data in the buffer to be sent.
#else
_WaitNotify(SYSVIEW_COMM_IDLE_DELAY); // Wait for event to be signaled when there is "enough" data in the buffer to be sent.
_NumBytesRecorded = 0; // Reset counter when we are going to send current RTT Buffer
#endif
//
// Check for data to be received from SystemView App
//
r = _SocketIsReadable(hSockSV, 0);
if (r == 1) { // Data to read from SysView available?
r = recv(hSockSV, acRecv, 1, 0); // Receive <NumBytes> to read
if (r != 1) { // Failed to receive data? => Connection lost
break;
}
v = acRecv[0];
r = recv(hSockSV, acRecv, v, 0); // Receive all data
if (r != v) { // Failed to receive data? => Connection lost
break;
}
NumBytes = SEGGER_RTT_WriteDownBufferNoLock(_ChannelID, &acRecv[0], r); // Write data into corresponding RTT buffer for application to read and handle accordingly
}
//
// Read available RTT data into send bufer and send it.
//
NumBytes = SEGGER_RTT_ReadUpBufferNoLock(_ChannelID, &_acBuf[0], sizeof(_acBuf));
if (NumBytes > 0) {
//
// Send data to SystemView App
//
r = send(hSockSV, _acBuf, NumBytes, 0);
if (NumBytes != r) { // Failed to send data? => Connection lost
break;
}
}
}
//
// Processing done. close socket handle.
//
if (hSockSV != SOCKET_ERROR) {
closesocket(hSockSV);
hSockSV = SOCKET_ERROR;
}
} while (1);
}
/*********************************************************************
*
* Global functions
*
**********************************************************************
*/
/*********************************************************************
*
* SEGGER_SYSVIEW_X_StartComm()
*
* Function description
* Setup communication channel.
*/
void SEGGER_SYSVIEW_X_StartComm(void) {
//
// Initialize SystemView communication
//
OS_TASK_CREATE(&_SysViewCommTCB, "SysView Comm", SYSVIEW_COMM_TASK_PRIO, _SysViewCommTask, _SysViewCommStack);
}
#ifndef _NO_NOTIFY
/*********************************************************************
*
* SEGGER_SYSVIEW_X_OnEventRecorded()
*
* Function description
* Macro callback to be called when an event has been stored in the
* SystemView RTT Buffer.
*
* Parameters
* NumBytes: Number of bytes stored in the buffer.
*/
void SEGGER_SYSVIEW_X_OnEventRecorded(unsigned NumBytes) {
//
// Notify SystemView Communication Task when the send threshold is reached.
//
_NumBytesRecorded += NumBytes;
if (_NumBytesRecorded >= SYSVIEW_COMM_SEND_THRESHOLD) {
_NumBytesRecorded = 0;
_Notify();
}
}
#endif
/*************************** End of file ****************************/