Difference between revisions of "How to create a custom ESPRO BSP"

From SEGGER Wiki
Jump to: navigation, search
Line 65: Line 65:
 
#Now build the project and start the debug session.
 
#Now build the project and start the debug session.
 
If everything works fine, two console outputs will be printed successively.
 
If everything works fine, two console outputs will be printed successively.
 
==How to add emNet to the custom BSP==
 
 
This tutorial will be explain how to add emNet to your bare metal espro custom BSP.
 
To make this tutorial easier, a few terms need to be defined first:
 
 
===Requirements===
 
*Make sure, your Clock is initialized so that your periphery can be used correctly.
 
 
===Tutorial===
 
 
*SolutionDir = The SolutionDir means the folder that contains the emProject file.
 
*ESPRODir = The ESPRO package folder, found in Embedded Studio under File->Open Studio Folder->Packages Folder.
 
 
#Open Embedded Studio
 
#Now activate the embOS and SEGGER library in the project options:
 
#*<code>Project Settings->ES PRO Cortex-M->emNet-></code>Add emNet = Yes.
 
#Open the SolutionDir and create a Folder called <code>IP</code> in it.
 
#Open the IP folder an create two more folders called <code>Setup</code> and <code>Generic</code> int it.
 
#Open the ESPRODir and navigate into <code>IP->Generic</code>
 
#Copy the following files into <code>SolutionDir->IP->Generic</code>
 
#*CM_IP_cksum.S
 
#*FTPC_Conf.h
 
#*IP_COAP_Conf.h
 
#*IP_Conf.h
 
#*IP_ConfigIO.c
 
#*IP_FIND.c
 
#*IP_FIND.h
 
#*IP_FTP_SERVER_Conf.h
 
#*IP_MQTT_CLIENT_Conf.h
 
#*IP_OS_embOS.c
 
#*README_emNet.html
 
#*SMTPC_Conf.h
 
#*WEBS_Conf.h
 
#*WiFi_Callbacks.c
 
#Navigate back to <code>SolutionDir->IP->Setup</code>
 
#In this folder a BSP_IP.c and a IP Config file is required, you can try to create them by your own, or you can contact us to make them for you in exchange with money.
 
#*Here you can find a example for the BSP_IP.c and for the IP Config, this example is for a STM32F7xx Board:
 
#Now Drag and Drop the IP Folder from your SolutionDir into the project window of Embedded studio.
 
#Activate in both folders Recurse into subdirectories via <code>Right click on the folder->Code->Folder->Dynamic Folder Recurse->Recurse into subdirectories</code>.
 
#Close the options window and synchronize both folder with disk via <code>Right click->Synchronize with disk</code>.
 
#To test emNet create a new c source file with following content:
 
<source lang=C>
 
/*********************************************************************
 
* (c) SEGGER Microcontroller GmbH *
 
* The Embedded Experts *
 
**********************************************************************
 
* *
 
* (c) 2007 - 2022 SEGGER Microcontroller GmbH *
 
* *
 
* www.segger.com Support: www.segger.com/ticket *
 
* *
 
**********************************************************************
 
* *
 
* emNet * TCP/IP stack for embedded applications *
 
* *
 
* *
 
* Please note: *
 
* *
 
* Knowledge of this file may under no circumstances *
 
* be used to write a similar product for in-house use. *
 
* *
 
* Thank you for your fairness ! *
 
* *
 
**********************************************************************
 
* *
 
* emNet version: V3.42.6 *
 
* *
 
**********************************************************************
 
-------------------------- END-OF-HEADER -----------------------------
 
 
File : IP_Ping.c
 
Purpose : Sample program for embOS & emNet
 
Demonstrates use of the IP stack to PING a host and get
 
notified about incoming ICMP (PING) packets.
 
Notes : For compatibility with interfaces that need to connect in
 
any way this sample calls connect and disconnect routines
 
that might not be needed in all cases.
 
 
This sample can be used for Ethernet and dial-up interfaces
 
and is configured to use the last registered interface as
 
its main interface.
 
*/
 
 
#include "RTOS.h"
 
#include "BSP.h"
 
#include "IP.h"
 
 
/*********************************************************************
 
*
 
* Configuration
 
*
 
**********************************************************************
 
*/
 
 
#define USE_RX_TASK 0 // 0: Packets are read in ISR, 1: Packets are read in a task of its own.
 
 
//
 
// PING sample.
 
//
 
#define HOST_TO_PING IP_BYTES2ADDR(192, 168, 5, 1) // IP addr. of host that will be periodically PINGed by this sample.
 
 
//
 
// Task priorities.
 
//
 
enum {
 
TASK_PRIO_IP_TASK = 150 // Priority should be higher than all IP application tasks.
 
#if USE_RX_TASK
 
,TASK_PRIO_IP_RX_TASK // Must be the highest priority of all IP related tasks.
 
#endif
 
};
 
 
/*********************************************************************
 
*
 
* Static const
 
*
 
**********************************************************************
 
*/
 
 
static const char *_ICMPContent = "This is a PING";
 
 
/*********************************************************************
 
*
 
* Static data
 
*
 
**********************************************************************
 
*/
 
 
static IP_HOOK_ON_STATE_CHANGE _StateChangeHook;
 
static int _IFaceId;
 
 
//
 
// Task stacks and Task-Control-Blocks.
 
//
 
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.
 
 
#if USE_RX_TASK
 
static OS_STACKPTR int _IPRxStack[TASK_STACK_SIZE_IP_RX_TASK/sizeof(int)]; // Stack of the IP_RxTask.
 
static OS_TASK _IPRxTCB; // Task-Control-Block of the IP_RxTask.
 
#endif
 
 
/*********************************************************************
 
*
 
* Prototypes
 
*
 
**********************************************************************
 
*/
 
#ifdef __cplusplus
 
extern "C" { /* Make sure we have C-declarations in C++ programs */
 
#endif
 
void MainTask(void);
 
#ifdef __cplusplus
 
}
 
#endif
 
 
/*********************************************************************
 
*
 
* Local functions
 
*
 
**********************************************************************
 
*/
 
 
/*********************************************************************
 
*
 
* _OnStateChange()
 
*
 
* Function description
 
* Callback that will be notified once the state of an interface
 
* changes.
 
*
 
* Parameters
 
* IFaceId : Zero-based interface index.
 
* AdminState: Is this interface enabled ?
 
* HWState : Is this interface physically ready ?
 
*/
 
static void _OnStateChange(unsigned IFaceId, U8 AdminState, U8 HWState) {
 
//
 
// Check if this is a disconnect from the peer or a link down.
 
// In this case call IP_Disconnect() to get into a known state.
 
//
 
if (((AdminState == IP_ADMIN_STATE_DOWN) && (HWState == 1)) || // Typical for dial-up connection e.g. PPP when closed from peer. Link up but app. closed.
 
((AdminState == IP_ADMIN_STATE_UP) && (HWState == 0))) { // Typical for any Ethernet connection e.g. PPPoE. App. opened but link down.
 
IP_Disconnect(IFaceId); // Disconnect the interface to a clean state.
 
}
 
}
 
 
/*********************************************************************
 
*
 
* _OnRxICMP()
 
*
 
* Function description
 
* Callback that will be notified once an ICMP packet has been
 
* received. The packet is evaluated and the type of the message
 
* will be output.
 
*
 
* Parameters
 
* pPacket: Pointer to packet received. pData points to the IP header.
 
*
 
* Return value
 
* 0 : Packet will be processed by the stack.
 
* Other: Packet will be freed by the stack.
 
*/
 
static int _OnRxICMP(IP_PACKET* pPacket) {
 
const U8* pData;
 
 
pData = IP_GetIPPacketInfo(pPacket);
 
if(*pData == IP_ICMP_TYPE_ECHO_REQUEST) {
 
IP_Logf_Application("ICMP echo request received!");
 
}
 
if(*pData == IP_ICMP_TYPE_ECHO_REPLY) {
 
IP_Logf_Application("ICMP echo reply received!");
 
}
 
return 0;
 
}
 
 
/*********************************************************************
 
*
 
* Global functions
 
*
 
**********************************************************************
 
*/
 
 
/*********************************************************************
 
*
 
* MainTask()
 
*
 
* Function description
 
* Main task executed by the RTOS to create further resources and
 
* running the main application.
 
*/
 
void MainTask(void) {
 
U16 SeqenceNumber;
 
char ac[16];
 
 
SeqenceNumber = 0;
 
 
IP_Init();
 
IP_AddLogFilter(IP_MTYPE_APPLICATION);
 
_IFaceId = IP_INFO_GetNumInterfaces() - 1; // Get the last registered interface ID as this is most likely the interface we want to use in this sample.
 
OS_SetPriority(OS_GetTaskID(), TASK_PRIO_IP_TASK); // For now, this task has highest prio except IP management tasks.
 
OS_CREATETASK(&_IPTCB , "IP_Task" , IP_Task , TASK_PRIO_IP_TASK , _IPStack); // Start the IP_Task.
 
#if USE_RX_TASK
 
OS_CREATETASK(&_IPRxTCB, "IP_RxTask", IP_RxTask, TASK_PRIO_IP_RX_TASK, _IPRxStack); // Start the IP_RxTask, optional.
 
#endif
 
IP_ICMP_SetRxHook(_OnRxICMP); // Register hook to be notified of incoming ICMP packets.
 
IP_AddStateChangeHook(&_StateChangeHook, _OnStateChange); // Register hook to be notified on disconnects.
 
IP_Connect(_IFaceId); // Connect the interface if necessary.
 
OS_SetPriority(OS_GetTaskID(), 255); // Now this task has highest prio for real-time application. This is only allowed when this task does not use blocking IP API after this point.
 
while (IP_IFaceIsReadyEx(_IFaceId) == 0) {
 
OS_Delay(50);
 
}
 
IP_PrintIPAddr(ac, HOST_TO_PING, sizeof(ac));
 
while (1) {
 
//BSP_ToggleLED(1);
 
OS_Delay(200);
 
IP_Logf_Application("Sending PING to IP addr. %s .", ac);
 
IP_SendPingEx(_IFaceId, htonl(HOST_TO_PING), (char*)_ICMPContent, strlen(_ICMPContent), SeqenceNumber++);
 
}
 
}
 
 
/****** End Of File *************************************************/
 
</source>
 
#Now build the project and start the debug session.
 
#If everything works fine, you should see a console output like in the picture below:
 

Revision as of 13:24, 19 August 2022

This article contains a guide that explains how to create a custom ESPRO Board Support Package based on a CPU Support Package. In this example we will create an embOS project, later other SEGGER software can be added as well.


Setup

The following tutorial will be based on the following Hardware and Software combinations:

Tutorial

This tutorial will be explain how to create a custom embOS board support package. To make this tutorial easier, a few terms need to be defined first:


  • SolutionDir = The SolutionDir means the folder that contains the emProject file.
  • ESPRODir = The ESPRO package folder, found in Embedded Studio under File->Open Studio Folder->Packages Folder.


  1. Start Embedded Studio
  2. Install CPU support Package for your device family via Tools->Package Manager.
  3. Create new project via File->New Project->Create the project in a new solution.
  4. Select the "A C/C++ executable for..." from the corresponding package. Press Next, select your target device and keep pressing Next until your project is finished.
  5. Now activate the embOS and SEGGER library in the project options:
    • Project Settings->ES PRO Cortex-M->embOS->Add embOS = Yes.
    • Project Settings->ES PRO Cortex-M->SEGGER->Add SEGGER library = Yes.
  6. After activating the libraries open the SolutionDir.
  7. Create two folders called OS and SEGGER, after that open the OS folder.
  8. Create two more folders in it named Setup and Generic.
    ESPRO BareMetal OS Setup Generic.PNG
  9. Go back to the SolutionDir and open the SEGGER folder.
  10. Create a folder named Generic in it.
    ESPRO BareMetal SEGGER Generic.PNG
  11. Now open the ESPRODir and navigate to SEGGER->Generic.
  12. Copy the following files into SolutionDir->SEGGER->Generic:
    • SEGGER_RTT.c
    • SEGGER_SYSVIEW.c
    • SEGGER_SYSVIEW_embOS.c
    • SEGGER_RTT_ASM_ARMv7M.S
  13. Also copy SEGGER_SYSVIEW_CONF.h from ESPRODir->SEGGER->Inc to SoluionDir->SEGGER->Generic.
    ESPRO BareMetal SEGGER Generic Source.PNG
  14. Unzip the downloaded SystemView, Target Sources to any location.
  15. Open the unzipped files and navigate to Sample->embOS->Config->Cortex-M.
  16. Copy SEGGER_SYSVIEW_Config_embOS.c into SolutionDir->SEGGER->Generic
  17. Now navigate to SolutionDir->OS->Generic and copy the following files from ESPRODir->OS->Generic:
    • JLINKMEM_Process.c
    • OS_Error.c
    • OS_ThreadSafe.c
      ESPRO BareMetal OS Generic Source.PNG
  18. After that create a RTOS Init file in SolutionDir->OS->Setup, how to create a RTOS init file can be found here: https://www.segger.com/doc/UM01076_embOS_Ultra.html#Board_Support_Packages
    ESPRO BareMetal OS Setup Source.PNG
  19. Go back to Embedded Studio and open the project settings.
  20. Switch to the common build configuration and navigate to Code->Preprocessor->User Include Directories
  21. After that add the following User Include Directories:
    • $(ProjectDir)/
    • $(ProjectDir)/CMSIS_5/CMSIS/Core/Include
    • $(ProjectDir)/STM32F7xx/Device/Include
    • $(ProjectDir)/SEGGER/Generic
      ESPRO BareMetal includes.PNG
  22. Drag and Drop the SEGGER and OS Folder from your SolutionDir into the project window of Embedded studio.
  23. Activate in both folders Recurse into subdirectories via Right click on the folder->Code->Folder->Dynamic Folder Recurse->Recurse into subdirectories.
  24. Close the options window and synchronize both folder with disk via Right click->Synchronize with disk.
  25. Drag an Drop both files of the downloaded files on top of the article into your SolutionDir.
  26. Drag and Drop both files of the downloaded files on top of the article into your virtual source folder in Embedded Studio.
    • The SolutionDir should now look as follows
      ESPRO BareMetal folders.PNG
    • The ES project explorer should now look as follows:
      ESPRO BareMetal project explorer.PNG
  27. Now build the project and start the debug session.

If everything works fine, two console outputs will be printed successively.