NetBurner 3.3.8a
PDF Version
Release 2.x to 3.x Porting Guide

Device Configuration

Previously device configuration was accomplished with IPSetup, a windows based program. In 3.x there are a number of ways to configure the device that are independent of the host computer type. The primary method is through the device's own configuration web server. In this way the device can be configured by a web browser on any platform. There is also a serial interface configuration method.

  • Can be configured by any web browser, and applications can be programmed into the device. Note: Autoupdate and IPSetup are no longer used to download applications or configure the device. However, you can still use IPSetup to discover a device's IP address.
  • Devices can be found by typing discover.netburner.com in the web browser URL field.
  • The underlying configuration mechanism is handled through a JavaScript Object Notation (JSON) object. This will be described in more detail later, but the important point is that it provides a simple interface that can be used by non-embedded developers (e.g. web developers) to interact and configure the device. The implementation is also designed to enable you to add any application specific information to be stored and accessed in the same manor, such as calibration values, set points, etc.
  • You are able to create your own configuration web interface that will appear in place of the default interface. In this way you can organize and present data in the appropriate way for your customers, as well as add your own custom logo, images and descriptions. Examples are provided.

Configuration Procedure

  • Connect your NetBurner device to a network with Internet access.
  • Open a web browser on your host computer and go to discover.netburner.com. You will see a list of devices on your network.
  • The "Device" link will take you to the device's web page. The "ConfigPage" link will take you to the device's configuration web page as shown below:

A sample JSON object is shown below:

{
"Config":{
"AppData":{},
"Sys":{
"Application":"Simple HTML Example",
"Boot":{
"Abort":"A",
"BootBaud":115200,
"BootDelay":2,
"BootQuiet":false,
"BootUart":0,
"Password":"",
"SerialConfig":{
"Choices":"DuringBoot, AlwaysEnabled, PauseAfterBoot, Disabled", "Value":"DuringBoot"
},
"User":""
},
"NetIf":{
"Ethernet0":{
"DeviceName":"",
"DhcpDiscoverSec":1,
"DiscoveryObfuscate":true,
"DiscoveryReportInterval":900,
"DiscoveryReportUrl":"discover.netburner.com/DevicePost",
"IPv4":{
"ActiveAddr":"10.1.1.73",
"ActiveDNS1":"10.1.1.1",
"ActiveDNS2":"0.0.0.0",
"ActiveGate":"10.1.1.1",
"ActiveMask":"255.255.252.0",
"AutoIPAddr":"169.254.131.245",
"AutoIPEn":true,
"Mode":{
"Choices":"DHCP,DHCP w Fallback,Static,Disabled", "Value":"DHCP"
},
"StaticAddr":"0.0.0.0",
"StaticDNS1":"0.0.0.0",
"StaticDNS2":"0.0.0.0",
"StaticGate":"0.0.0.0",
"StaticMask":"0.0.0.0"
},
"IPv6":{
"ActiveAddr":["2602:306:b8e9:c83f::14c0","2602:306:b8e9:c83f:203:f4ff:fe0b:83f5","fe80::203:f4ff:fe0b:83f5"],
"ActiveDNS":["2602:306:b8e9:c83f:208:a2ff:fe0c:b081","2602:306:b8e9:c83f:208:a2ff:fe0c:b081"],
"ActiveRoute":["fe80::1:1"],
"Mode":{
"Choices":"DHCP,DHCP w Fallback,Static,Disabled", "Value":"DHCP"
},
"StaticAddr":"::",
"StaticDNS1":"::",
"StaticDNS2":"::"
},
"MAC":"00:03:F4:0B:83:F5"
}
},
"Platform":"MODM7AE70"
},
"Version":8,
"Reboot":false
}
}

If you were writing a web interface and need only the data under Ethernet in the tree, it can be accessed by: http://10.1.1.71:20034/UI.html?CONFIG/SYS/NETIF/Ethernet

To obtain just the IP address: http://10.1.1.71:20034/UI.html?CONFIG/SYS/NETIF/Ethernet/IPv4/ActiveAddr

Recommended Examples

The following examples are recommended to begin evaluating the platform. They are located in the \nburn\examples directory.

  • ShowInterfaces
  • \Configuration\Web\BasicWebConfig

Configuration Security

One of the features of NetBurner 3.0 is that each device is configured though its own configuration web interface. Data sent and received through the network interface has three options for security:

  • Open: No security, plain text
  • Obfuscated: Encrypted, but without TLS and a secure certificate and private key
  • Secure: Encrypted with TLS and a certificate and private key

Each NetBurner device generates a default certificate and private key, which is stored in its internal flash memory, which can be used to secure the connection as a self-signed certificate. You can also use the device’s private key to create your own externally self-signed certificate, or have a certificate issued by a recognized third party. The externally signed certificate can then be installed by overwriting the device's default key.

Cautions When Using the Jumper Recover Procedure on a Device

Each device has a location to insert a shorting jumper to reset the module in the event of a catastrophic software problem, such as downloading an application image that corrupts flash memory or crashes. This recovery procedure will erase all of flash memory and download a recovery image. A new private key and certificate will then be generated. In such a case, any external self-signed or third party certificates will no longer be valid since the private key will have changed. A new certificate will have to be created from the new private key.



Device Application Updates

Note
The AutoUpdate utility is no longer used for download application to your device.

You will notice there is an Update Application on the web page. Application are now uploaded using the web interface. Alternatively, there is a windows executable that can be run from the command line in \nburn\pcbin\nbupdate.exe. Application images are now .bin files, they are no longer .s19 files. If building in NBEclipse the .bin file will be located in your workspace project's release folder. The format using nbupdate.exe is as follows: nbupdate <application .bin file> <device IP>



Eclipse and Development Tools Updates

Summary of new and improved features:

  • Eclipse has been updated to the Oxygen version. It also takes advantage of multiple processor cores on the host computer to greatly speed up compile times. Note: if using the command line to build you can use make -j to use multiple cores.
  • GCC has been updated to version 8.1.
  • Each project now has its own NetBurner library. Now any system changes you make will be specific to the project, and each project can have its own modifications.
  • The makefile implementation is now identical for NBEclipse and command line builds.



SSL/TLS

Improvements include:

  • Moving from NetBurnerSSL to wolfSSL
  • Support for a much broader range of ciphers
  • Support for DER encoded certificates
  • Support for server-side peer verification
  • Support for onboard certificate generation
  • Substantial improvements to SSL stability
  • Support for client side certificate authority lists
  • A cleaner interface for using certificate authority lists, as well as the ability to dynamically alter them
    during runtime
  • Faster key generation for onboard certificate generation
  • Lays the groundwork for future improvements
    • TLS v1.3
    • FIPS 140 Ready
    • DTLS



Notes on Porting From Previous Revisions

  • Big endian vs. little endian. The ColdFire processors have a bin endian architecture, while ARM processors are little endian. If you have code that manipulates 16-bit or 32-bit numbers that relay on a big endian format you will need to ensure it works for both types.
  • The typical startup sequence of function calls: IntializeStack(), GetDhcpIfNecessary, EnableAutoUpdate(), etc have been replaced with a single call: init() which is declared in the header file init.h. You will need to remove header files such as:
    #include <startnet.h>
    #include <autoupdate.h>
    #include <dhcpclient.h>
    #include <NetworkDebug.h>
    NetBurner IPv4 DHCP Client Header File.
  • The real-time operating system has been modified to increase performance and capabilities. The header file ucos.h is now nbrtos.h. Any RTOS function calls that had UCOS in related names have been modified to reflect this.
  • UCOS_ENTER_CRITICAL has been replaced with NBRTOS_ENTER_CRITICAL.
  • The StartHTTP() function is now StartHttp() and StartHttps().
  • Callbacks have been added to replace the MyDoGet() and MyDoPost() functions. See HTML Processing for examples on usage.
  • A new function has been added to wait for an active network connection, meaning the device has link. A typical startup sequence will be:
    init();
    WaitForActiveNetwork(TICKS_PER_SECOND * 10);
    StartHttp(); // or StartHttps();
    void StartHttp(uint16_t port, bool RunConfigMirror)
    Start the HTTP web server. Further documentation in the Initialization section Initialization - Syste...
    void init()
    System initialization. Normally called at the beginning of all applications.
    Definition: init.cpp:27
    bool WaitForActiveNetwork(uint32_t ticks_to_wait=120 *TICKS_PER_SECOND, int interface=-1)
    Wait for an active network connection on at least one interface.
    Definition: dhcpc.cpp:1554
  • Types such as WORD, DWORD, etc have been replaced with uint16_t, int16_t, uint32_t, int32_t, etc.
  • Registering a name with a DHCP server is no longer done by assigning a string to extern const char pDHCPOfferName. It is now set by assigning a name to the configuration tree JSON object element: CONFIG:SYS:NETIF:Ethernet:DeviceName.
  • Runtime calls to the network interface such as EthernetIP() have been removed. Please refer to the ShowInterfaces example for methods to obtain runtime interface data.



Porting I2C From MCF52xx Based Products to MODM7AE70

Applicable Platforms:

  • MOD5234
  • MOD5270
  • MOD5272
  • MOD5282
  • PK70EX
  • SB70
  • SB70LC
  • SB72

MCF52xx platforms have a singe I2C peripheral, therefore the I2C driver API knew which signal pins to use and the set of functions to send/receive data only had to consider a single peripheral. ARM based platforms have many I2C peripherals, so a different type of driver/API is required. For example, with just a single I2C peripheral, an I2CSend() function is all that is needed. If there are many I2C peripherals, the driver must be able to send on any of them. This applies to all I2C functions: read, write, status, error detection, etc.

The most robust and scalable implementation is to use I2C peripheral C++ objects. You do not need to be a C++ programmer to use these objects in your application, other than to understand the format to call a member function of the object instead of a global C function call. For example, if in C you had a global function named GetI2CStatus(), it would now be a member function of a specific I2C object/peripheral and the call would be MyI2CObject.GetI2CStatus(). This method enables your application to handle multiple I2C peripherals, and the status function knows which peripheral to use because it operates on the object. Note that since the status function is called as a member function of the object, it is common to take that into consideration in the member function name, so it would likely be MyI2CObject.GetStatus().

In this way you can easily handle multiple I2C peripherals: MyI2CObject1, MyI2CObject2, MyI2CObject3, etc. Your application code does not need to manage and continuously check for which peripheral is being used, such as having a C style array of I2C peripherals.

The I2C driver for MCF52xx devices in the NNDK 2.x tools has the interface listed below. Note that there is a bit of C++ even in the old driver in terms of the function prototypes. You are likely calling some of these functions without any parameters, or with less than all the parameters listed. In C++ default parameters are specified in the function prototype with the '=' sign. So you can call I2CInit() with no parameters in your application, and the default parameters in the function prototype will be used.

void I2CInit( BYTE slave_Addr = 0x08, BYTE freqdiv = 0x3C )
BYTE I2CSend( BYTE val, DWORD ticks_to_wait = I2C_RX_TX_TIMEOUT )
BYTE I2CSendBuf(BYTE addr, PBYTE buf, int num, bool stop = true)
BYTE I2CRead( PBYTE val, DWORD ticks_to_wait = I2C_RX_TX_TIMEOUT )
BYTE I2CReadBuf( BYTE addr, PBYTE buf, int num, bool stop = true )
BYTE I2CStart( BYTE addr, bool Read_Not_Write, DWORD ticks_to_wait = I2C_RX_TX_TIMEOUT )
BYTE I2CStop( DWORD ticks_to_wait = I2C_RX_TX_TIMEOUT )
BYTE I2CRestart( BYTE addr, bool Read_Not_Write, DWORD ticks_to_wait = I2C_RX_TX_TIMEOUT )
void I2CResetPeripheral()
bool I2CRXAvail()
DWORD I2CTXAvail()
BYTE I2CGetByte()

The I2C implementation in the 3.x tools for ARM platform uses the I2CDevice Class. For example, on the MODM7AE70, an I2C object to select an I2C peripheral to interface with an EEPROM can be declared as (code taken from the I2C Pic Kit example):

#define I2C_MODULE_NUM 0 // use I2C0/TW0
#define I2C_EEPROM_ADDRESS (0xA0 >> 1) // Microchip 24LC0B EEPROM, 2Kbit (256 x 8)
I2CDevice EepromDevice(i2c[I2C_MODULE_NUM], I2C_EEPROM_ADDRESS);

The declaration of the I2CDevice creates an I2C object for I2C peripheral module 0 at the specified EEPROM I2C address. Creating the object also handles the initialization, so the equivalent of I2CInit() is not needed. Once we have created the object, all we need to do is call the member functions to control it in the format: EepromDevice.<member function>. For example, to send/write a single byte value of 0x60 to address 0x01 of the EEPROM: EepromDevice.writeReg8(0x01, 0x60);. Note that in ARM terms, the I2C addresses are referred to as registers. writeReg8() refers to 8-bits.

You will also note that the return values use the C++ operator "::". Whereas the 2.x driver returned an unsigned 8-bit value (BYTE), the 3.x driver returns a typed value of Result_t. Using typed values will result in more robust application code since the compiler can detect when a return value is used incorrectly. the "I2C::" result types are (be sure to view the latest information in the 3.x NetBurner API manual):

I2C_RES_ACK Acknowledged
I2C_RES_NACK Not acknowledged
I2C_RES_ARB_LST Arbitration listening
I2C_RES_BUSY Bus is busy
I2C_RES_ARG Bad argument

The corresponding functions to the MCF52xx I2CDevice driver are below. This is the recommended driver.

// Constructor to create object, also initializes the I2C peripheral. The pInterface
// parameter will be i2c[0], i2c[1] or i2c[2], representing the 3 I2C peripherals.
// The optional 3rd parameter is normally left as a default. It can be used to set the
// number of register address byte to send, from 0 to 3.
// Example: I2Cdevice EepromDevice(i2c[0], address);
I2CDevice(I2C & pInterface, uint8_t deviceAddress, uint8_t numAddressBytes = 1)
Result_t writeReg8(uint32_t reg, uint8_t dat)
Result_t writeRegN(uint32_t reg, uint8_t *buf, uint32_t blen)
Result_t readReg8(uint32_t reg, uint8_t &dat)
Result_t readRegN(uint32_t reg, uint8_t *buf, uint32_t blen)
Start, Stop and Restart are taken care of in the writeRegN and readRegN functions.
In situations in which a restart was used for sending more than 1 byte as an address,
the numAddressBytes parameter in the I2CDevive constructor can be used.
void resetBus()
void setup(uint32_t busSpeed) // change bus speed
I2C Device Class (recommended)
Definition: i2c.h:438
I2C Peripheral Class.
Definition: i2c.h:212

If you wish to have more manual control over the I2C transactions, you can create an I2C object instead of an I2CDevice object:

// Create an I2C peripheral object. The module parameter for the MODM7AE70 can be 0, 1 or 2.
I2C(int module)
Result_t writeReg8(uint8_t devAddr, uint32_t reg, uint8_t data)
Result_t writeRegN(uint8_t devAddr, uint32_t reg, uint8_t *buf, uint32_t blen)
Result_t readReg8(uint8_t devAddr, uint32_t reg, uint8_t &data)
Result_t readRegN(uint8_t devAddr, uint32_t reg, uint8_t *buf, uint32_t blen)
void setup(uint32_t busSpeed)
Result_t DoTransaction(I2CTxn_t *pTransaction, bool bRepeatedStart = false);
void resetBus()

In NNDK 3.x there is also a third option. ARM refers to the I2C as a two-wire interface, or a wire interface in general. A WireIntf class is available for even more manual control. It was written for those familiar with Arduino drivers, but can be used for more detailed control in general. Please refer to the NNDK 3.x documentation for details.