Network Module Manual - Code Rev 20210821 1541
Network Module Manual - Code Rev 20210821 1541
Introduction
Did you buy one (or more) of these Network Modules and then find disappointment in
the software on the board?
- All of the modules have the same MAC address. That's a problem if you want
more than one on your network. And the supplier does not give you a way to
change the MAC.
- If you change the IP Address the device returns to its default IP Address when it
power cycles. That makes it pretty much useless even if you only put one on your
network - unless you're OK with it always having IP Address 192.168.1.4.
I decided to write my own firmware for the device to provide a web server interface that
let's you change the IP Address, Gateway (Default Router) Address, Netmask, Port
number (a REAL port number), and MAC Address. I also added the ability for the device
to remember all these settings through a power cycle. Any Output settings you make are
also optionally saved through a power cycle (Outputs typically being Relay controls).
1
NOTE 1: The software provided in this project only works with the “Web_Relays_Con
V2.0 HW-584” which is based on the STM8S-005 or STM8S-105 processor and
ENC28J60 ethernet controller. I haven't tried it with any other version of the hardware. I
think the V.1 FC-160 is based on a Nuvoton processor and this code and the tools are
incompatible.
NOTE 2: I am not in any way associated with the manufacturer of this device. I only
wrote code to run on it for my own hobby purposes, and I am making it available for
other hobbyists.
NOTE 3: If you’re looking to buy these modules the best source I’ve found is eBay. Best
search term is “ENC28J60 Network Module”. I’ve also seen them on Amazon,
Banggood, and AliExpress. In some cases they show photos of both the V.1 and V2.0
versions, but don’t provide a way of specifying which one you want. You may need to
communicate with the seller to be sure you’ll get the V2.0 device.
Thank You!
Many thanks to Carlos Ladeira for his help with user interface ideas, many hours of
testing, and his patience during development of the MQTT version of this code. And
many thanks to Jevdeni Kiski for his guidance and code contributions in developing the
Home Assistant interface, new Configuration interface, and JavaScript. We’ve ended up
with a much better project as a result.
Document License
Copyright (C) 2020 Michael Nielson.
Permission is granted to copy, distribute and/or modify this document under the terms of
the GNU Free Documentation License, Version 1.3 or any later version published by the
Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no
Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free
Documentation License".
2
Table of Contents
Introduction..........................................................................................................................1
Thank You!..........................................................................................................................2
Document License...............................................................................................................2
Table of Contents.................................................................................................................3
Change Log..........................................................................................................................5
MQTT Firmware vs Browser Only Firmware...................................................................12
Upgradeable Firmware......................................................................................................13
Screen Shots and Usage - MQTT Build............................................................................17
Screen Shots and Usage - Browser Only Build.................................................................19
Screen Shots and Usage - All Builds.................................................................................22
Notes on Feature Settings..................................................................................................23
Notes on Individual IO Settings – MQTT build................................................................25
Notes on Individual IO Settings – Browser Only build.....................................................27
Notes on the MAC Address...............................................................................................29
Notes on REST Commands...............................................................................................31
Notes on MQTT.................................................................................................................33
Notes on Network Statistics – Browser Only....................................................................41
Notes on Link Error Statistics............................................................................................42
Functional Limitations.......................................................................................................46
Programming the Module..................................................................................................48
Alternative Way to Force Defaults or Downgrade Firmware...........................................59
Alternative Way to Set Initial IP Address.........................................................................62
Display Values vs Pin Logic Levels..................................................................................65
Network Module Schematic..............................................................................................67
Pinouts...............................................................................................................................69
Notes on Interfacing to Relay Modules.............................................................................70
Notes on Inputs..................................................................................................................78
Hardware Design to Maintain Relay States Through a Power Loss or Reboot.................79
Adding DS18B20 Temperature Sensors............................................................................85
Developers: Setting Up a Development Environment.......................................................87
Developers: Location of EEPROM Variables...................................................................89
Developers: Notes on Debug Bytes...................................................................................91
Developers: Notes on Configuration Debug and pin_control Bytes.................................95
Developers: Notes on Proto-Sockets.................................................................................97
Developers: #pragma, Sections, Segments and the .lkf File..............................................99
Developers: STM8 Address Map....................................................................................107
Developers: Flash Memory Map.....................................................................................108
Developers: I2C EEPROM Memory Map.......................................................................110
Developers: Strings File Generation................................................................................112
Developers: Using the UART..........................................................................................113
Developers: Analysis of MQTT sendbuf sizing..............................................................116
Developers: Storing Variables in Flash via the Application...........................................120
Developers: Flash and EEPROM Wear Notes................................................................125
3
Code Credits....................................................................................................................127
Documentation License Note..........................................................................................130
4
Change Log
June 20, 2020 – Initial Release
August 6, 2020 – Added a note to make sure people know they don’t need to set up a
development environment unless they need to change the code.
5
- Rearranged some sections in the document.
- Added EEPROM bit field definitions.
- Added tables showing relationship of browser and MQTT fields to pin logic
levels.
December 2, 2020
Code changes:
o Fixed issue regarding browsers on multiple IP addresses.
o Fixed issue regarding browser interference on page changes.
Document changes:
o Added section to describe functional limitations (like number of browser
sessions, browser interference).
o Added section on an alternative method for entering the initial IP Address.
December 4, 2020
Code changes:
o Code change made to reduce or eliminate relay state changes during
reboot.
Document changes:
o Added section on alternative hardware design methods for maintaining
relays states during power loss.
6
December 21, 2020
MAJOR CHANGE: Changed all MQTT commands to match the Home Assistant
standard.
Code changes:
o Fixed timing issue in MQTT command processing
o Changed all MQTT commands to match the Home Assistant standard.
o Simplified the appearance of the browser interface to make code space
available for continued MQTT development.
Document changes:
o Updated MQTT command list
7
o Changed Screen Shots
o Replaced Config Settings section with Feature Settings section
o Added section on Individual IO Settings
o Updated REST commands
o Eliminated section “Notes on Compiling Different Configurations”
o Updated section “Location of EEPROM Variables”
o Added section “Alternative Way to Force Defaults”
o Updated section “Programming the Module” to reflect use of a single
release for all configurations.
8
o Re-enabled the former MQTT Error Statistics page renamed as Link Error
Statistics
Document changes:
o Documented support for UART debug output messages on IO 11
o Documented Link Error Statistics
o Added description of Debug bytes for developers
o Changed some section titles to clarify which ones are for Developers, and
reorganized the document to collocate Developer sections.
o Moved the Change Log after the Table of Contents
o Updated information on where to find .stp and .sx files on GitHub
9
o Fixed Issue #56: Temperature Sensor accuracy improvement
o Fixed Issue #57: Temperature sensor order in GUI and Home Assistant.
Fixed by changing Temperature Sensor ID’s from “1, 2, 3, 4, 5” to a 12
character ID per sensor that is based on the sensor serial number
o Fixed Issue #58: Home Assistant; Auto Discovery; MQTT; Should a
temperature sensor be deleted in HA if it fails during runtime?
o Fixed Issue #62: Browser Only; Timers don’t work with Invert setting.
Included in fix is a correction for “Timer values not saved correctly” and
“Timer value being set to 256 in error”.
o Fixed Issue #63: REST commands preventing IO Control page from
making pin state changes.
o Fixed Issue #66: MQTT doesn’t report temperature sensors unless at least
1 IO is enabled.
Document changes:
o Updated description of Temperature Sensor ID’s and run time add/delete
functionality.
o Added additional explanations on how Temperature Sensor ID’s are sorted
for display.
10
o Addressed Issue #83: /98 /99 command does not return the correct size for
the page in the HTML header.
Document changes:
o Added new section on using “Upgradeable” firmware
o Added REST command notes
o Added Developers section: Notes on Proto-Sockets
o Added Developers section: #pragma, Sections, Segments and the .lkf File.
Includes information on Editing the .lkf file, Flash Update and Copy-
RAM-to-Flash Code, _fctcpy, #pragma Sections, and Content of the .lkf
File
o Added Developers section: STM8 Address Map
o Added Developers section: Flash Memory Map
o Added Developers section: I2C EEPROM Memory Map, Includes
information on I2C EEPROM Regions for Upgradeable Builds and
Addressing the I2C EEPROM Regions
o Added Developers section: Strings File Generation
11
MQTT Firmware vs Browser Only Firmware
Two firmware types are available for the Network Module: “MQTT” and “Browser
Only”.
The intent of having the two firmware builds is to address two different communities of
users.
The MQTT firmware is directed at users that have the network infrastructure to support a
MQTT Broker and device management tools like Home Assistant, NodeRed, and similar
tools. Those added network tools provide a very diverse set of device management
capabilities including user friendly interfaces and timing control. The MQTT firmware
CAN also be used by someone that only wants a Browser GUI.
The Browser Only firmware is directed at users that want simpler, self-contained
functionality without the need for an MQTT broker and other “always on” network tools.
The Browser Only firmware eliminates the MQTT code and provides a GUI that includes
a few extra user interface features like “IO Naming” and “IO Timers”. Of course
“Browser Only” significantly limits automation relative to what you can do with MQTT
and the device management tools associated with MQTT.
Feature Comparison:
Feature Browser
MQTT
MQTT Browser Only
Upgradeable
Build Only Build Upgradeable
Build
Build
MQTT Support X X
Home Assistant Support X X
Full/Half Duplex X X X X
Link Error Statistics X X X X
DS18B20 Temp Sensor X X X X
IO Naming X X
IO Timers X X
Link Error Statistics X X X X
Network Statistics X X
I2C Support X X
Upgradeable Over
X X
Ethernet
12
Upgradeable Firmware
REQUIRES ADDITIONAL HARDWARE
“Regular” firmware can only be installed on the Network Module using an ST-Link V2
and the SWIM interface (see section “Programming the Module”). Then, for upgrades
you must attach the ST-Link V2 again and reprogram the device. However, by adding an
external EEPROM you can take advantage of “Upgradeable” firmware that enables you
to update the firmware on the Network Module via Ethernet. You still must program the
Network Module at least one time via the SWIM interface, but thereafter you can do all
code upgrades via Ethernet. Both the MQTT and Browser Only versions of the firmware
are available in Upgradeable form.
Advantages:
- No need to physically access the Network Module to update the firmware.
Reprogramming is fairly fast, taking only about 1 minute.
- You can switch between MQTT and Browser Only versions as needed.
- More Flash space is made available for future features.
- An I2C interface is implemented to support the feature, enabling addition of other
I2C devices.
Disadvantages:
- IO pins 14 and 15 are required for use as an I2C interface
- You must add an external 1MBit (128Kbyte) I2C EEPROM.
Search eBay or other sites with the term “Serial I2C Interface EEPROM”. These are
typically sold WITH a 32KByte (256Kbit) EEPROM already on them – but we need a
13
larger capacity EEPROM. So, you can get the “board only” without an EEPROM for as
little as $1 USD.
The 24xx1025 is a 128Kbyte (1Mbit) device. It is plug compatible with the board shown
above.
The 24xx1025 can be hard to find in DIP form. Single devices are typically around $7
USD. If multiples are bought the price is much lower per device. I bought 10 for $1.25
each. Search on all three types (AA, LC, FC) as sometimes one of the alternatives is
cheaper.
Comment: One user bought the TSSOP/MSOP SMT/SMD style of package, soldered it
to a machined DIP socket, then plugged that into the socket on the board. I don’t
recommend this approach due to its fragility, but it will work in a pinch if you are good
with kluging.
The “VCC” pin on the EEPROM board must be attached to 3.3V on the Network
Module. 3.3V is accessible on the SWIM connector, or you can add a wire.
The “SCL” pin on the EEPROM board must be attached to IO 14 on the Network
Module.
The “SDA” pin on the EEPROM board must be attached to IO 15 on the Network
Module.
14
The “GND” pin on the EEPROM board must be attached to GND on the Network
Module.
IMPORTANT: The A2 jumper on the EEPROM board needs to be moved to the outer
position (tied to 3.3V) . The WP, A0, and A1 jumpers remain as shown in the photo
above (all tied to GND).
Due to the small amount of code space on the Network Module the “upgradeable
firmware process” works as follows:
a) A “Code Uploader” is copied from the added “Off-Board EEPROM” into the
STM8 Flash, replacing the program that was in the Flash.
b) The Code Uploader is then used to install and start new firmware.
I left out some details in the above for simplification. So let me expand on the process.
The first question you may ask is “How did the Code Uploader get into the Off-Board
EEPROM”? Well, whenever the Code Uploader runs the first thing it does is copy itself
to a special region in the Off-Board EEPROM. So, the first time this process is ever used
the user must use the SWIM interface to install the Code Uploader in the Network
Module Flash, and then boot the Network Module. The Code Uploader copies itself to the
EEPROM, and it is then available for future use.
Another detail: The “upgradeable” versions of the MQTT and Browser Only firmware
needed more space for runtime code, so the “strings” used to define the IOControl and
Configuration pages are also stored in the Off-Board EEPROM. The Code Uploader is
used to copy those strings to the Off-Board EEPROM.
So, knowing all this, here is the procedure the FIRST time you install the upgradeable
firmware:
a) Use the SWIM interface to install the Code Uploader in the Network Module.
b) Boot the Network Module to start the Code Uploader and access the Network
Module with your Browser
c) Use the Code Uploader GUI to select the “Strings” file and upload it.
d) Use the Code Uploader GUI to select the upgradeable verson of the MQTT or
Browser Only runtime code and install it.
You are up and running.
Future upgrades:
After initial install as described above here’s how you upgrade firmware in the future:
a) A release will always contain these files:
- Code Uploader (example name: NetworkModule-CodeUploader.sx)
- Strings file (example name: NetworkModule-Strings.sx)
15
- Runtime files: (example names: NetworkModule-MQTT-UPG.sx and
NetworkModule-Browser-UPG.sx)
When using “upgradeable” code it is important to ONLY load the MQTT and
Browser Only >>upgradeable<< versions or you will break the upgrade loop and
have to go back to the “first time” steps.
b) Since you are upgrading you already have a “runtime” version installed. Enter the
URL command /72. This will install the Code Uploader from the Off-Board
EEPROM.
c) Use the Code Uploader to install the new Code Uploader. Why do this? Often
there won’t be any change to the Code Uploader, but just to keep the process
“familiar” I will always release all files at the same time.
d) Use the Code Uploader to install the new Strings file. Again this file usually
doesn’t change, but installing it every time prevents procedural mistakes.
e) Use the Code Uploader to install the new Runtime file of your choice.
Note: If you are certain you already installed the new Code Uploader and String files
you can use the Code Uploader (via the /72 URL command) to install the MQTT and
Browser versions as needed. This lets you move back and forth between the code
types for development work.
That’s pretty much it. The Code Upload process includes some pop-up screens to help
you with progress and timing of the steps. But if you are new to the Network Module it
may be best to just use the non-upgradeable code and the ST-Link V2 / SWIM interface
programming process until you get familiar.
16
Screen Shots and Usage - MQTT Build
17
Screen Shots and Usage
MQTT Build
18
Screen Shots and Usage - Browser Only
Build
19
Screen Shots and Usage
Browser Only Build
20
Screen Shots and Usage
Browser Only Build
To access the Network Statistics Page enter the http command “http://IP:Port/68”.
21
Screen Shots and Usage - All Builds
22
Notes on Feature Settings
The Features checkboxes on the Configuration page let you modify operation of the code
as follows:
MQTT build:
The Full Duplex checkbox determines the Half / Full Duplex Ethernet
communication method. The default setting is Half Duplex because that is the
most reliable setting for the ENC28J60 Ethernet chip. Since all the Ethernet
transactions that will occur with the module are small and infrequent there is no
real performance advantage to using Full Duplex.
During test it was found that Cisco business level switches exhibited Half Duplex
timing that the ENC28J60 cannot handle, the symptom being a device disconnect
(and automatic recovery) every few hours. This isn’t the fault of the Cisco switch,
rather it appears to be the fault of errata in the ENC28J60. During test it was
determined that we could get around this issue when connected to the Cisco
switch by enabling Full Duplex mode in the ENC28J60. While there was concern
that this would not work (due to chip spec notes and online discussion over the
years), it seemed to run error free. There may be other switches which show the
same issue. Again, the reason Full Duplex works may be the very low messaging
rate used with the Network Module which eliminates the need for flow control.
Note 1: The spec for the chip indicates that Full/Half Duplex auto-
negotiation DOES NOT work. However, experimentation showed that
both Full and Half Duplex worked with some unmanaged switches, but
not with others. Problems were always running Half Duplex only with the
Cisco 1G managed switch. No problem was seen running Half Duplex
with a Cisco 10/100 managed switch.
23
Note 2: If you choose to use the Full Duplex setting note that the spec says
the Switch port the device is connected to MUST be manually configured
for Full Duplex operation … even though our testing did not always show
that to be the case. Of course we had a limited number of switches and this
might be an issue on some other switch.
Note3: Feel free to experiment with this setting at your own risk to see
what works best in your network configuration. I recommend you use Half
Duplex and only try Full Duplex if you have issues.
HA Auto:
The Home Assistant Auto Discovery setting enables the Network Module to send
MQTT Auto Discovery Publish messages to your Home Assistant server.
Checking this setting will automatically enable MQTT (and the MQTT checkbox
will automatically be set). Do not enable this setting unless you are operating in
an MQTT environment with Home Assistant.
MQTT:
Checking this box will enable the MQTT interface. HA Auto DOES NOT need to
be enabled with MQTT. This will allow you to operate with MQTT servers
without using Home Assistant, OR it will enable you to use Home Assistant
without Auto Discovery.
DS18B20:
Checking this box will cause IO 16 (Pin 16) to be disabled for use as an Input /
Output pin and will enable operation of the DS18B20 Temperature Sensor
interface on IO 16 (Pin 16). You can attach up to 5 DS18B20 temperature sensors
to pin 16, and the temperatures sensed by those devices will be displayed on the
IOControl page. See the section “Adding DS18B20 Temperature Sensors”.
24
Notes on Individual IO Settings – MQTT build
The Individual IO Settings drop down and check boxes on the Configuration page lets
you modify functionality of each IO as follows:
Each IO has a “Type” drop down box that lets you configure each IO as follows:
25
VERY IMPORTANT: Be sure you understand your hardware design. You must
avoid setting an IO as an Output if the associated pin is tied to VCC or Ground, as
that is likely to damage the output driver on the processor. If your hardware
design can provide high levels of input current on a pin make sure that pin is
defined as an Input.
Invert Settings:
Effect on Inputs:
If not checked, a low voltage on the Input pin will display as OFF in the
IOControl page and will be reported as OFF to MQTT clients.
If checked, a low voltage in the Input pin will display as ON in the IOControl
page and will be reported as ON to MQTT clients.
Effect on Outputs:
If not checked, an OFF indication in the IOControl page or MQTT Client will
result in a low voltage on the Output pin.
If checked, an OFF indication in the IOControl page or MQTT Client will result
in a high voltage on the Output pin.
Since some devices connected to Output pins may be in an ON state with a low
voltage, and others may be in an OFF state with a low voltage you will need to
figure out what the Invert setting should be for your specific design. It is really a
simple matter of connecting your peripheral device, setting ON or OFF in the
Browser, then checking the Invert box as needed so that an ON state in the
Browser matches an ON condition in your peripheral.
Each IO has a “Boot State” dropdown box. The effect of each setting is as
follows:
26
Notes on Individual IO Settings – Browser
Only build
The Individual IO Settings drop down and check boxes on the Configuration page lets
you modify functionality of each IO as follows:
Name Settings:
Enter a name for the IO pin. This name will appear on the IOControl page for the
pin. Use any alphanumeric character plus -*_ and . (no spaces).
Timer Settings:
Two fields are provided:
27
“Value” field:
0 disables the Timer.
1 to 16383 can be entered for the of “ticks” to operate the Timer. For
example, 1 second or 1 minute or 1 hour.
“Units” field:
Select the time unit to use: 0.1 second, seconds, minutes, or hours.
If you enter “0” in the Value field the Timer will not affect the Output pin.
The Timer assumes that the “Boot State” is the idle state of the output, ie,
the “normal” state the output is in. If you then change the output to its
non-idle state the Timer will start and will return the output to the idle
state when the Timer expires. Example:
Output #1 is named “Porch Light”. The Boot State is “off”. So,
normally this output is “off”. I have the Timer value and units set
to 15 seconds. If I change the output to “on” the Timer will turn
the output off after 15 seconds.
“Boot State” must be “on” or “off”. “retain” will disable the Timer.
If a Reboot or power cycle occurs while a Timer is running the Output will
be set to its “Boot State”.
NOTE: “Name” and “IO Timer” features are not available in the MQTT build due to lack
of Flash space. Typically this type of feature isn’t needed in MQTT environments as
MQTT management tools provide similar functionality.
28
Notes on the MAC Address
When new the Network Modules all have the same MAC address. This obviously doesn’t
work when you try to put more than one on a network.
A MAC address is only used within your network. Your router(s) and switch(es) use the
MAC address as the means of uniquely addressing all the hardware in your network. The
MAC address does not appear outside your network so it only needs to be unique to
YOUR network, not to the entire world. This being the case, you only need to make sure
that any MAC address you put in the Network Module does not conflict with any other
hardware in your local network.
The default MAC address value in the code provided is just a random value with the
exception that it has the two least significant bits of the most significant octet arranged to
make it a “Unicast” and “Locally Administered Address (LAA)” as illustrated here. You
MUST make sure you use a LAA and Unicast address.
All other bits and octets in the MAC address (including those in the most significant
octet) can be anything you want as long as you set the two bits above as shown.
Despite this being a LAA MAC address there is still some very remote possibility the
MAC you pick will conflict with some other hardware you have on your network. You
can search on Google to find methods of finding all MAC addresses on your network –
the method you choose will depend on your level of expertise. Generally this is not
required, and if you suspect a conflict you may just find it easier to try a different MAC
address on the Network Module. Maybe make the middle fours octets something you
fancy.
29
If you are installing multiple devices on your network I suggest that you just change the
values in the least significant octet and leave the others as-is. I advise you add a label to
your Network Module with the MAC you programmed into it.
30
Notes on REST Commands
A REST (Representational State Transfer) type of interface has been implemented to
enable access to Input/Output states and other functions without the use of the browser.
This is to enable development of external programs to operate the Network Module
without use of the full GUI. A complete list of the REST commands is provided here.
55 = All Outputs ON
56 = All Outputs OFF
31
Note1: Output control commands (00 to 31) only work for IO defined as an Output. If the
IO referenced in the command is an Input no action is taken.
Note 3: Releases prior to August 2021 would repaint the GUI with the “current webpage”
when /00 to /31, /55, or /56 commands were executed. This was found to interfere with
operation of other Browsers logged into the Network Module. Beginning with August
2021 releases these commands will return a “blank” webpage to eliminate this
interference.
32
Notes on MQTT
This is not a tutorial on MQTT as there are a lot of great resources online to bring you up
to speed if you are just getting started with this protocol. Here I am only including notes
on the tools and methods used in test of the MQTT functionality on the Network Module.
Configuration Settings:
At this date the MQTT Broker Server must be specified in the form of an IP
Address (as opposed to a URL). In future versions I may be able to allow use of a
URL for the Broker Server.
The MQTT Port is self explanatory. The MQTT default value of 1883
automatically appears, but you can enter any port number you have assigned to
MQTT on your Broker Server.
Security:
The MQTT Username and MQTT Password are optional and only required if
you’ve set up your Broker to require them.
If security is really important due to the need to access MQTT on the device from
the internet I suggest setting up access to your internal MQTT Broker Server in a
secure way, then letting the Broker Server pass all messages on your internal
network. You don’t have to do it this way, but this is a suggestion for improving
security rather than just exposing the device to the internet.
33
Tools and test methods:
You aren’t restricted to the above. Any tools and interfaces that are MQTT compliant
should work just as well. But if you are just getting started I can recommend the
above as a good place to start.
The MQTT Status indicators show connection progress with the MQTT Server
and Broker:
Box 1 - Indicates that the MQTT Connection process has started.
Box 2 - Indicates a successful ARP reply from the Server.
Box 3 - Indicates a successful TCP connection with the Server.
Box 4 - Indicates the MQTT Broker has responded (Connect phase)
Box 5 - Indicates initial communication with the Broker has completed
successfully (initial subscribe and publish messages completed).
Once all 5 boxes are green the Network Module is connected to the Broker and
normal MQTT communications can proceed.
A reminder regarding the Output Boot State setting for the Outputs on the
Configuration page: If you select ‘Retain’ the Output states are written to the
EEPROM every time an Output changes state. If you anticipate a lot of Output
state changes you may wear out the EEPROM with too many changes to the
Output states.
34
Client Publish and Subscribe messaging:
The Network Module Publishes the following when an IO state change occurs:
NetworkModule/<devicename>/input/xx Payload: "ON" or "OFF"
NetworkModule/<devicename>/output/xx Payload: "ON" or "OFF"
Where “xx” is the IO number of the Input or Output
The Network Module Publishes the following every 30 seconds if DS18B20 mode is
enabled and Temperature Sensors are attached to the Network Module::
NetworkModule/<devicename>/temp/xxxxxxxxxxxx Payload: Temperature
in degrees Celsius in the format " 000.0" or “-000.0”
Where “xxxxxxxxxxxx” is the Temperature Sensor ID in 12 hex encoded
characters.
35
The Network Module Publishes the following in response to receiving a state-req
Publish message:
NetworkModule/<devicename>/state Payload: see below
The payload consists of two bytes with the bits organized as follows:
First byte:
Bit 7 = IO 16 state (1 = ON, 0 = OFF)
Bit 6 = IO 15 state
Bit 5 = IO 14 state
Bit 4 = IO 13 state
Bit 3 = IO 12 state
Bit 2 = IO 11 state
Bit 1 = IO 10 state
Bit 0 = IO 9 state
Second byte:
Bit 7 = IO 8 state
Bit 6 = IO 7 state
Bit 5 = IO 6 state
Bit 4 = IO 5 state
Bit 3 = IO 4 state
Bit 2 = IO 3 state
Bit 1 = IO 2 state
Bit 0 = IO 1 state
Note that Disabled IO will still have either an ON or OFF state – dependent on the
last state seen for that IO. The user application is responsible for knowing which
IO are Enabled and Disabled when using the above response.
The Network Module Subscribes to the following topics when it connects to the Broker:
NetworkModule/<devicename>/output/+/set
This Subscribe enables the Network Module to receive output Publish
commands from Clients. The + as used above causes the broker to send
the module the "set" commands, but won't reflect the modules own IO
state messages back to the module (reduces traffic).
NetworkModule/<devicename>/state-req
This Subscribe enables the Network Module to receive the state-req
Publish command from Clients
When the Network Module connects to the Broker it will establish a "last will" message
of "offline" with the will topic “NetworkModule/<devicename>/availability”
When the Network Module connects to the Broker it will Publish to the following topics:
NetworkModule/<devicename>/availability Payload: online
NetworkModule/<devicename>/input/xx Payload: "ON" or "OFF"
NetworkModule/<devicename>/output/xx Payload: "ON" or "OFF"
Where “xx” is the IO number for the Input or Output.
36
No Publish occurs for a Disabled IO.
If the HA Auto checkbox is set to enable the Network Module Publishes the following
messages at boot time:
37
homeassistant/sensor/<macaddress>/yyyy/config Payload: see below
This only occurs if DS18B20 mode is Enabled.
In the above topics <macaddress> is the MAC address of the Network Module. The “xx”
is the IO number. The “yyyy” is the Temperature Sensor ID. Outputs are defined as
“switch” topics, Inputs are defined as “binary_sensor” topics, and Temperature Sensors
are defined as “sensor” topics.
Where a Home Assistant Auto Discovery Payload is not empty it takes this form for the
“switch” topics:
{
"uniq_id":"<macaddress>_output_01",
"name":"<devicename> output 01",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":"~/output/01",
"cmd_t":"~/output/01/set",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for an Output on IO 01.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
Where a Home Assistant Auto Discovery Payload is not empty it takes this form for the
“binary-sensor” topics:
{
"uniq_id":"<macaddress>_input_01",
"name":"<devicename> input 01",
38
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":"~/input/01",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for Input on IO 01.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
Where a Home Assistant Auto Discovery Payload is not empty it takes this form for the
“sensor” topics:
{
"uniq_id":"<macaddress>_temp_012356abcdef",
"name":"<devicename> temp 012356abcdef ",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":”~/temp/012356abcdef ",
"unit_of_meas":"\xc2\xb0\x43",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for Temperature Sensor ID “012356abcdef”. The ID is a 12
character hex encoded field representing the 6 digits (48 bits) of the Temperature Sensor
serial number.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
39
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
40
Notes on Network Statistics – Browser Only
Network Statistics are accessible only via the http command “http://IP:Port/68”. This
page is available in the Browser Only build (there is not enough memory in the MQTT
build to include it). To be honest I was reluctant to add this page as it has only been
minimally useful – but it is kind of cool so here it is. The information may be useful if
you are debugging your network or developing applications to interface to the Network
Module.
Note: Seeing large numbers of “Dropped packets at the IP layer” is not unusual. At least
not unusual in my network. I traced this to Smart Home devices that seem to attempt
some form of connection maintenance with everything on the network many times per
hour. And I have lots of Smart Home devices on my network … so … lots of connection
attempts. The Network Module drops these requests. The difference between “Dropped”
and “Received” is the number of packets actually destined for the Network Module.
41
Notes on Link Error Statistics
Link Error Statistics are accessible only via the http command “http://IP:Port/66”. The
statistics may be useful to you for determining if Full Duplex works better than Half
Duplex in your particular network configuration.
As noted in other parts of the manual the normal mode of operation is “Half Duplex”, and
you should not need to change that. However, during development it was noticed that the
Network Module works better with some Cisco 1 Gbit business class switches if the
Network Module and the Cisco switch are manually set to Full Duplex. So, this statistics
page can let you compare error statistics over several hours or days to help you decide
which configuration works better for you.
IMPORTANT: If you use “Full Duplex” the ENC28J60 specifications state that you must
manually set your switch to “Full Duplex”. This is because the ENC28J60 cannot auto-
negotiate Full/Half Duplex. If your switch does not allow you to manually set Full
Duplex you should probably just leave the Network Module at Half Duplex. Having said
that, experimentation seems to suggest that some switches will work just fine regardless
of the Full/Half duplex setting in the Network Module. So … do your own experiments
and use the “/66” command to observe results. But in general I suggest you just leave the
module at its default “Half Duplex” mode.
If you enter the “/66” command you’ll get a display similar to this:
42
43
Seconds counter: # of seconds since boot
Transmit counter: # of transmits from the ENC28J60
Stack error: Not a counter, “1” will indicate detection of a stack overflow. That’s bad …
drop me a note if you see that happen.
ENC28J60 revision: Chip revision. This should indicate “06”, which indicates chip B7.
TXERIF: count of TRXERIF errors (see ENC28J60 documentation)
RXERIF: count of RXERIF errors (see ENC28J60 documentation)
MQTT Response Timeout count: Count of response timeouts in the MQTT code
MQTT Not OK: Count of MQTT Not OK events in the MQTT code
MQTT Broker Disconnect count: Count of MQTT Broker disconnects as detected in the
MQTT code
The Link Error Statistics page is “semi-hidden” and enabled only by the “/66” command
because it can be very confusing to the typical user.
The content of the Link Error Stats page is likely to change as the code matures. It was
added to assist with testing of MQTT performance using a variety of switches. One
critical finding is that the statistics are not completely consistent, likely due to the number
of variables affecting the values. Still, they can be useful for relative measurements when
determining if you might have unusually high error rates on your network, and/or if you
might need to experiment with the Half / Full Duplex setting.
The RXERIF error indicates that the ENC28J60 experienced a receive buffer overflow
condition. This likely indicates extremely high network traffic. The impact is that packets
received at the Network Module may be dropped. It is not unusual to have a few of these
errors over a long period of time.
44
The TXERIF error indicates that a transmit abort has occurred. This error can occur as a
result of the following;
1) Excessive Ethernet packet collisions
2) Late collisions
3) Transmission was unable to occur because the medium was occupied for too long.
It is normal to see transmit or receive errors, just not "too many", which is somewhat
arbitrary. On a LAN with well behaving clients and good cabling you may only see one
error every few months. Communication over WiFi, WAN, or Internet will see much
higher error rates. And the error rate depends on how much traffic is occurring. Some
users may never see an error indication, which is great. Others may see lots of errors,
which may be 'normal' or may indicate a problem depending on their specific
environment.
These counters are included because they were useful during development to help
determine that Full Duplex worked much better than Half Duplex on the Cisco 1Gb
“business level” managed switches. With Half Duplex a TXERIF error was occurring
several times per day, accompanied by an MQTT disconnect (and automatic reconnect).
Once Full Duplex was enabled zero errors were seen for several weeks in the Cisco 1Gb
configuration.
On the other hand, TXERIF errors were seen when Full Duplex was used with some
unmanaged switches, and no errors when those same switches were used with Half
Duplex.
Your specific configuration and conditions may require some experimentation to get the
best result.
Note: The “Seconds since boot” counter is approximate. The Network Module does not
have a highly accurate clock, and there will be an accumulating deviation from real time,
particularly if the counter is run for a long period. But, it is close enough for this purpose.
45
Functional Limitations
The code space and RAM in the processor on the Network Module is extremely limited,
so there are many functional limitations that you would not expect on a device without
these constraints. Some of the limitations to be aware of:
MQTT SSL/TSL:
MQTT does not support SSL/TSL. There is insufficient code space to implement this
functionality.
Configuration Errors:
There are very few “warnings” in the code to keep the user from creating bad
configurations. The most concerning is that if you enable “Retain” for the power
cycle output states AND you subject the device to rapid output state changes you run
46
the risk of wearing out the EEPROM. Other situations likely only cause the device to
lose contact with browsers or MQTT brokers (like mis-configuring IP addresses or
Port numbers).
47
Programming the Module
Assuming you have the Web_Relays_Con V2.0 HW-584 and all you want to do is apply
this firmware the following describes the process.
IMPORTANT NOTE: In the steps below you’ll turn off the Read Out
Protection bit on the Network Module. This will ERASE the program
currently in the device. It will only work again after you successfully
reprogram it. DO THIS AT YOUR OWN RISK.
Note that as of January 2021 I’ve gone to one release of the firmware that covers the
functionality of the four previous parallel releases.
1) Prepare your Network Module: Install a 4 pin header on the board (see photo)
48
2) Buy the Programmer: Purchase a ST-Link V2 (see photo). If you are patient you can
get one from China in about a month for about $3.50. Or in less than a week from within
the US for about $6.00 (assuming you are in North America). Price estimates are as of
June 2020. Search on Google, Amazon, eBay, etc.
The ST-Link V2 modules come in several colors so pick the color you like.
49
3) Obtain and Install Free Software: All of my development work was on the Windows
10 OS. If you are using Linux you will have a little more homework to do on your own,
but I don’t think there is much difference. For Windows you’ll need to download and
install the following files:
en.stsw-link009.zip
You'll find the above at https://www.st.com/en/development-tools/stsw-
link009.html
en.stvp-stm8.zip
You'll find the above at https://www.st.com/en/development-tools/stvp-stm8.html
You'll need to create an account at st.com to get the above software. It's free but
they want an email address to contact you. When you try to download the
software you’ll be asked for your account credentials and given the option to
create an account. By providing my email address I've gotten some invitations to
online programming seminars but otherwise no spam. Not much hassle.
1) ST Visual Develop
2) ST Visual Programmer (STVP)
I only used STVP even when developing the code. And if you are only
reprogramming your devices STVP is the only tool you’ll need.
50
4) Copy the Program: Now that you’ve installed the necessary software you need to
copy the STVP Project file and the Binary file from GitHub that will be programmed into
the Network Module.
NOTE: Beginning with the February 20, 2021 release you should obtain source code
and executable files from the “Releases” part of the GitHub web page (along the
right margin of the page).
C:/Users/Mike/Documents/COSMIC/FSE_Compilers/CXSTM8/NetworkModule
If you locate your copy of the project files in a similar Documents file location this
should minimize the tinkering you have to do. And should you decide to modify the
program you’ll already have an appropriate directory set up.
The STVP programmer needs a “.stp” and “.sx” file pair to program the Network
Module. Now that we have one code set to cover all the previous functionality you’ll only
need to copy the following files into the Documents directory you created above:
You will find these files in the “Releases” section of the GitHub web page (along the
right margin of the page). The above are the only files you need to copy from the GitHub
project account if you only want to program your module and you are not jumping right
into code modifications.
IMPORTANT1: Since the path to your “Documents” directory will be different than
mine (if for no other reason than your user ID is different than “Mike), you may need to
edit the .stp file to match your directory path. Open the .stp file with NotePad or
NotePad++ and look for the following. Edit it to match the path to your .sz file.
IMPORTANT2: Later releases of the code have already modified the .stp file so that
you should not need to edit it. If you find the following in the .stp file you only need to
make sure that the .stp file and the .sx file are in the same directory:
51
I use NotePad++ and have it set to show the CR/LF at the end of the line. If you use
regular NotePad as your text editor you won’t see that.
Since your User name on your Windows machine is probably not "Mike" you'll need to
start STVP, click on "Project/Open", and browse for the .stp file that you copied to your
Documents/… directory. Once you open the project file STVP should automatically load
the .sx file from that same directory.
The project file contains various settings that enable the ST-Link V2 to communicate
with your target board. They should already be set for you, but just in case the following
is how I had them set:
Under “Edit/Preferences”:
(Continued)
52
Under “Configure/Configure ST Visual Programmer”
If the above looks OK you are ready to program the Network Module.
53
Setting up the Hardware to allow programming:
Apply power to your Network Module. You should be using a 5V power supply
connected to the power pins on the Network Module.
If you see “out of range” messages like the following this is NOT an error. It would have
been nice if the messages were more informative, but they are just telling you that the
indicated addresses are in non-programmable areas of the chip during program load. The
addresses shown are typically in EEPROM and RAM.
54
Once the program is successfully loaded in the programmer you will see a message like
this (although the checksum will likely be different than what you see here).
If this is the first time you are programming your Network Module you will need to clear
the Read Out Protection (ROP) bit. If you don’t clear the ROP any attempt to program
the Network Module will give you a “This device is protected” message. How to clear the
ROP bit:
(Continued)
55
Make sure “Read Out Protection OFF” is selected in this drop down.
Next click on “Program / Current Tab”. This will clear the ROP bit and allow you to
reprogram the device. IMPORTANT: CLEARING THE ROP BIT ERASES THE
CODE IN THE NETWORK MODULE. After you clear the ROP bit you MUST
reprogram the Network Module to make it useful again.
56
Programming the Device:
If you got an error message while attempting to program the Network Module:
a) Make sure the RST connection is in place.
b) Make sure the power supply connected to the Network Module is providing 5V.
c) Make sure you have good connections from the ST-Link V2 to the Network
Module.
d) You might have to unplug the ST-Link V2 from the USB port on your PC and
plug it back in again.
e) You might have to stop the STVP program, unplug and replug the ST-Link V2,
then restart the STVP program.
f) If you have 16 relays connected to your Network Module I suggest disconnecting
them while reprogramming. If you have a very robust power supply it may be
possible to leave them connected. The Network Module will be reset a couple of
times during programming, and this may cause the relays to simultaneously turn
on and off. Whether this interferes with programming depends on whether your
power supply can handle the surge caused by the relay coils.
Generally I haven’t had to do any of the above as I seldom saw an error. But on
occasion I saw an error message that the link was not working, and the above
tinkering got it working again.
(Continued)
57
If you see a message indicating programming success you are ready to attempt to connect
to the Network Module via the Ethernet connector.
a) Disconnect the RST wire between the ST-Link V2 and the Network Module. You
can also disconnect the other wires, or leave them connected for the time being.
b) Connect the Ethernet cable. I suggest you do this the first time without using your
network. Make a direct Ethernet cable connection from the Network Module to
your PC and attempt to access it at 192.168.1.4:8080. If the connection does not
work check your IPV4 Ethernet settings on the PC and set it to use IP address
192.168.1.100 (not DHCP). If you don’t know how to do this Google it. Here’s a
helpful link:
https://stevessmarthomeguide.com/setting-up-static-ip-address-windows-10/
While the device is directly connected to your PC you can use your browser to make
address setting changes on the Network Module that are appropriate to your network.
Then you can connect the device to your network, return your PC to its original Ethernet
settings, and attempt to access the device.
If you need to re-install or upgrade the Browser Only version remember that the IO
Names and IO Timer values are stored in Flash. For this reason you will want to make
sure you don’t overwrite those values, otherwise you will have to manually re-enter them.
You don’t have to worry about this the first time you install the Browser Only version.
But on subsequent installs do the following:
If you forget and use “Program / Current Tab” you’ll see an error message – but the
programming will complete and the IO Names and IO Timer values will return to
defaults.
58
Alternative Way to Force Defaults or
Downgrade Firmware
Normally all you have to do to return to “factory defaults” is press the Reset button on
the Network Module board for 10 seconds. However, during development there were a
couple of times where pressing the Reset button did not revive the Network Module to a
point that it would operate. Admittedly this was due to “in development” code errors and
may not be needed, but I’m providing it just in case.
This information is only useful if you are going to do your own development from this
code. I DO NOT RECOMMEND THIS METHOD UNLESS ALL ELSE HAS FAILED
TO REVIVE THE DEVICE.
1) When the Network Module is connected to the STLink (including the Reset wire) you
can access the EEPROM content with the “Data Memory” tab.
59
2a) After clicking on the Data Memory tab click on Read / Current tab to read the
EEPROM contents.
2b) You can change any value in the Data Memory one character at a time, then you can
write the result to the EEPROM with the Program / Current tab selection.
60
2c) To force the EEPROM to a state where firmware must start over again set the bytes
circled in blue to 0.
After committing to EEPROM reboot the device (power cycle or reconnect the reset
wire, wait 2 seconds, and disconnect the reset wire).
2) You can now disconnect the STLink and connect the Network Module to your
network. Once connected you should be able to use a browser to connect to the
Network Module via the factory default address 192.168.1.4:8080.
FIRMWARE DOWNGRADE
Once you’ve cleared the EEPROM content as shown above you should be able to load a
prior release of the firmware should you need to do so. If your intention is to downgrade
the firmware DO NOT reboot the device until you do so.
61
Alternative Way to Set Initial IP Address
A user commented that it was cumbersome to have to set up a laptop with a fixed IP
Address to program the Network Module with its first “network compatible address”.
Here’s an alternative that may be useful to you.
Let’s say your network already uses 192.168.1.4, so you can’t attach the device directly
to your network. Or perhaps your network uses some other variant of the
192.168.xxx.xxx address range, or even the 10.0.0.x address range. A way to work
around this without needing to set up a laptop or PC for the initial Ethernet connection to
the Network module as follows;
1) Assumption is that you successfully programmed the flash with the Network
Module code. Reboot the Network Module (usually just be releasing the reset
wire). Then reconnect the reset wire.
2) Using the STLink change the IP address in the EEPROM. Reboot the Network
Module.
3) Attach the Network Module to your network, access the Network Module with a
browser, and finish changing any settings via the Configuration menu.
62
2a) After clicking on the Data Memory tab click on Read / Current tab to read the
EEPROM contents.
2b) You can change any value in the Data Memory one character at a time, then you can
write the result to the EEPROM with the Program / Current tab selection.
2c) SO …. Which value do you want to change? You can change any of the values, but
typically you only need to change the IP Address of the module to get it to appear on
your network. Looking at the EEPROM map the below shows where the IP Address
is located.
63
“hostaddr1 to 4” is the Network Module IP Address. Note that it is in hex, and it is in
reverse order (MSB on the right, LSB on the left). In decimal format the address
shown is 192.168.1.186. Click on any character to change it, then be sure to use
Program / Current tab to commit the changes to EEPROM.
After committing to EEPROM reboot the device (power cycle or reconnect the reset
wire, wait 2 seconds, and disconnect the reset wire).
5) You can now disconnect the STLink and connect the Network Module to your
network. Once connected you should be able to use a browser to connect to the
Network Module and make any further changes you need in the Configuration page.
IMPORTANT NOTES:
a) You should not use the “direct access to the EEPROM” method for anything other
than the minimum needed to gain access via a browser. Usually you only need to
change the Network Module IP Address (hostaddr). It’s too easy to make a
mistake … so don’t forget about the reset button if you mess it up.
b) If you press the reset button on the Network Module it will return to the hard-
coded defaults, NOT to the changes you manually put in the EEPROM. You’ll
have to go through this process again to get back to a network compatible IP
address.
c) If you change the “Magic Number” it will cause a return to factory defaults on
reboot.
64
Display Values vs Pin Logic Levels
This information may be useful to you for understanding how the values displayed in the
browser or contained in the MQTT fields correspond to output and input pin voltage
levels.
65
66
Network Module Schematic
I traced out the parts of the Network Module that are pertinent to developing the new
software. I did not trace ALL connections as my intention was not to reverse engineer the
hardware design. My intention was only to fix the inadequate function of the software.
The schematic may be useful should you decide to improve on the software I’ve
provided. Some notes:
- There are a number of capacitors connecting power and ground. These are left out
of the schematic.
- Unused pins or pins that did not appear to be a necessary part of the functionality
were programmed to be inputs with pull-ups. These are shown as disconnected on
the schematic even if there was a component attached.
o There are some components connected to the Port B pins. I suspect the
original code used these to identify if the board was “8 port” or “16 port”.
- I didn’t trace out most of the pins on the ENC28J60, as I knew the design worked
and did not need to do any modifications. Some notes:
o The SPI interface on the ENC28J60 is not connected to the SPI interface
on the STM8S005. Ordinary port pins on the STM8S005 are used to “bit
bang” the SPI interface. Not very fast, but this is not an Ethernet
performance design so it works just fine.
o The –WOL pin does not appear to be connected.
o The CLKOUT pin is not connected.
- If you dig into the STM8S005 specification you’ll find that most pins that I show
simply as “port pins” can be defined for other uses. I didn’t include all that
information in the component drawing as it just creates confusion in this context.
The Network Module uses all the pins as “port pins”, so that is all I show.
- The STM8S005 operates on its internal 16MHz clock. It does not have an external
crystal or clock source.
67
68
Pinouts
Schematic representation of the connection header vs silkscreen on the board;
69
Notes on Interfacing to Relay Modules
There are two things to be cautious of when attaching relay modules to the Network
Module: Power Distribution and Type of Relay Module.
Power Distribution
The first thing to consider is supplying power to the relay modules. The basic design of
the Network Module is intended to provide +5V power to the relay modules via the pin
header that also provides the relay control signals. This works well for just a few relays
(up to 3 or 4). This connection method is illustrated here:
If you attach more relays you need to make sure that there is sufficient current supplied
by your +5V power supply attached to the Network Module AND you need to make sure
the method used to send power to the relay modules is adequate. This is particularly
important if you are transferring power via a ribbon cable.
If you don’t think you can provide adequate power to the relay modules via the Network
Module relay header you can consider a couple of options:
1) Connect +5V power only at the Relays, and let the power/signal header send +5V
back to the Network module.
70
2) Use separate +5V power supplies on the Network Module and Relay Modules. If
you do this you’ll need to disconnect the +5V power connection between the
headers.
71
Type of Relay Module
The second consideration is the type of relay modules you attach. The SM8S processor
on the Network Module operates at 3V and its outputs are connected directly to the relay
control header. So, you need to avoid inadvertently causing +5V feedback from the relay
modules to the 3V output pins of the processor that exceed the processor specifications
(check the spec, but the short version is: Max 3.3V and/or limit to 4mA per pin, AND
limit to 20mA across all pins). The reason this is a concern is because the SM8S output
pins have overvoltage protection diodes that can provide a current path if a voltage higher
than 3.3V appears on the pin when it is not in an active pull-down state. To visualize this
here is a drawing illustrating the output pin:
Focus on the Protection Diode. There is also a protection diode to ground, but it is not a
concern in this discussion so I left it out. If any of the relay modules can provide a current
path from a higher voltage through the chip pin (when the pin is not pulling down) then
there is the potential for damage. Knowing this let’s look at typical relay module designs.
72
a) Opto-isolated relay boards: If you use opto-isolated relay boards there should
not be a concern as long as the relay boards are designed to operate at a voltage
no higher than 5V. The typical design of these relay modules looks like this:
Note that in fact this relay module can provide a current path from +5V, through
the photo emitter diode of the opto-isolator, through the visible LED, through the
1K resistor, then to the SM8S output pin via the “IN1” connection. But this will
still work and here is why:
- The difference in voltage from the 5V supply to the SM8S output pin is 5V –
3V. But about 0.7V is dropped across the photo emitter diode. Then another
0.7V is dropped across the LED. And about 0.3V is dropped across the
protection diode in the SM8S. The result is that there is only 5 – 3 – 0.7 - 0.7 -
0.3 = 0.3V potential across the 1K resistor. This will result in about 300 uA of
current flowing through the path. This is not enough current to damage the
SM8S and not enough current to cause the relay module to operate. So while
not ideal it works.
- If your relay module does not have the LED in the trigger signal path as
shown in the drawing above it might still work, but you’ll have to test it to
verify. The difference is that the 0.7 volt drop across the LED is missing from
the equation so about 1mA will flow into the output pin of the SM8S. That
won’t hurt the SM8S, but it might cause the opto-isolator to operate in turn
preventing the relay from releasing or causing the relay to release
intermittently.
73
b) Non-isolated relay module, Active HIGH trigger signal: Some relay modules
do not have opto-isolators. If they are of a design that has an active high trigger
signal then the typical design has a 1K ohm resistor feeding the base of a NPN
transistor. This type of relay module should operate just fine when connected
directly to the Network Module, although you’ll find that the logic seems reversed
and you may have to set or clear the “Invert” function in the Relay Control page
of the GUI.
The reason this module works with the Network Module is because it has no path
from +5V back to the SM8S output pin..
74
c) Non-isolated relay module, Active LOW trigger signal: This is another relay
module design that does not have opto-isolators. This design typically has an
active low trigger signal, and the typical design has a 1K ohm resistor feeding the
base of a PNP transistor. A typical relay module design looks like this:
This design is problematic in that the PNP transistor is connected to 5V, and when
the Network Module control signal goes to a high state a reverse current flow
(also known as an injected current flow) will travel from +5V through the PNP
transistor, through the 1K resistor, and into the SM8S output pin. Analyzing this
path:
- If the relay module you have places the LED in series with the PNP
transistor the module may work better due to the voltage drop across
the LED. However, there may still be enough current to cause the PNP
transistor and the relay to operate intermittently. All you can do is give
it a try.
75
d) 16 Channel Opto-isolated relay boards: A user that bought 16 Channel opto-
isolated boards reported problems, and on investigation it was found that the input
circuit did not match what had been seen on 1, 2, 4, and 8 channel boards (even
from the same supplier!). On further investigation we found that all the 16
Channel boards we could find online match this unique implementation. The type
of board is shown here:
With some circuit tracing the circuit design on each channel appears to be as follows:
76
While the particular board this user had utilized 24V relays it appears that the
board also comes in 5V and 12V relay versions. But the important thing to note is
that the opto-isolator input circuit does not include an LED like the boards
discussed in (a) above. This is a major problem in that the opto-isolator will
remain activated regardless of the state of the output pin on the Network Module.
The diode replaces the voltage drop that the series LED provides on most other
relay module designs and prevents the current path through the STM8S pin
protection diode from keeping the PC817 in its active region (re-read (a) above
for more information).
I am not sure if all 16 channel relays boards are designed this way, but all the ones
found in a search on April 9 2021 appear to be as discussed here.
If you haven’t bought any relay boards yet consider buying two 8 Channel boards
instead of one 16 Channel board … or do the fix described above.
77
Notes on Inputs
If you configure the Network Module to include digital inputs you’ll need to be careful
about the voltage you put on the input pin. The pins are directly connected to the SM8S
processor. The processor operates at 3V, so you’ll need to limit the high level voltage
applied to the pin to 3V, or limit the current to no more than 1 mA.
Each input pin has a weak pull-up applied internal to the SM8S processor. The pull-up
has a typical resistance equivalent of 60Kohm, but can range from 30Kohm to 80Kohm.
Some recommendations:
1) If you are using 3V logic to drive the input pin you should be able to directly
connect it.
2) If your driver circuitry might place more than 3V on the input pin you can do one
of the following:
a) Use open collector devices or level translators to prevent putting more than
3V on the input pin.
b) Use relay contacts to ground the input pin, relying on the SM8S pull-up to
take the pin high. This might not be adequate if the wiring to the input pin is
long or is subject to electrical interference.
c) Put a 1Kohm resistor between the driver logic and the input pin, but be sure
the driver cannot exceed 5V. This isn’t ideal, but should limit any current
driven into the SM8S to an acceptable level and still achieve adequate logic
levels at the SM8S input.
78
Hardware Design to Maintain Relay States
Through a Power Loss or Reboot
A user wanted to know how to prevent relays from changing state during a power loss on
the Network Module. This question is very dependent on the whether the relays remain
powered up during the power loss on the Network Module, AND it is dependent on
whether the control input to the relay is active low or active high. So let’s explore why
things happen and what you can do about it.
First of all, be aware that when the Network Module loses power its outputs go to a low
level signal. I’m sure this makes sense to you: no power, no signal output. But there is the
additional consideration that the overvoltage protection on the device pins (effectively a
diode to VCC) will look like a pull-down when VCC on the STM8S processor goes to
zero. Also be aware that when the SM8S processor powers up it defaults all IO pins to a
“floating input” state. This is a function of the chip design, so it can’t be changed.
Regardless of what you define as ON or OFF, this discussion here is purely from the
perspective of the output signal levels on the Network Module and the input type of the
relay being driven.
Scenario 1:
a) Assume relays remain powered up while the Network Module is powered down.
b) Relays are active high inputs (a high level signal activates the relay).
Scenario 2:
a) Assume relays remain powered up while the Network Module is powered down.
b) Relays are active low inputs (a low level signal activates the relay).
79
during power loss, then the relay will return to an inactive state if Retain was
enabled in Configuration.
- When the Network Module loses power and then reboots any relay that is active
will remain in an active state if Retain was enabled in Configuration.
- Note: If the relays also lose power they will of course go inactive during power
loss.
So let’s say you don’t like the above scenarios and you want the relays to stay just the
way you set them through a power loss, regardless of whether they were active or not.
Well, this can only be done with hardware external to the Network Module. Here are
some suggested solutions:
Option A:
- Assume the relays remain powered up while only the Network Module loses
power.
- The relays can be either active low or active high inputs.
Since we know the Network Module outputs will go low during power loss we need to
build hardware that will maintain the state of the relay control input during the outage.
An example circuit is shown here for 16 Relays:
80
In the above circuit the Power Supervision device will detect when power is falling on
the Network Module and will cause the D-latch devices to capture the output states of the
Network Module. As long as power is maintained on the Relays and the D-latches the
relays will maintain their state.
Once power returns on the Network Module the Power Supervision device will continue
to keep the D-latch devices in a hold state until the STM8 processor is operating. If
additional time is needed a capacitor can be added to the MR- input.
The latching circuit described above is placed between the Network Module and the
Relay Module as shown here:
The downside to the above: The devices in the Latching Circuit may not all be available
in DIP form – some may be surface mount. This implies that you may have to design a
circuit board for this solution. That is not as onerous as you might think. There are cheap
manufacturing sources in China that will make up to 10 circuit boards for almost nothing
(less than $10 USD). But you must design the board and generate gerber files.
Option B:
- Use “Latching Relays”
This option almost sounds like nirvana until you look at the details.
First let me caution you about “bi-stable self latching” relays that you may find on eBay.
Those are meant to be provided with a pulse and they will switch and hold their state.
BUT, you can’t tell what state they are in remotely, so not very useful for remote
81
applications. It might be possible to tap into their circuitry and find a sense point that
could be fed back to one of the Network Module sense inputs. But remember these bi-
stable relays are not actual latching relays as they require that power be maintained to the
relay for it to retain it’s state (just like Option A above)..
So, what about REAL latching relays? They will maintain their state even if ALL power
is lost to the Network Module and the Relay Module. These relays are sometimes called
“Impulse” relays because they require a pulse on a Set pin to put them in one state, and a
pulse on a Reset pin to go to the other state. An example of this type of relay is the
G5RL-K1-E-DC5 for low current applications (Google it).
Since the Network module only has a single state output a circuit is required to convert
that signal to the pulses needed by the latching relays. And a driver is needed to supply
the necessary pulse current to the relays. AND the circuit still needs to detect power loss
to prevent inadvertent pulse generation when power is lost and restored.
82
The pulse circuit looks like this:
The above needs to be repeated for each relay (except the Power Supervision can be
common).
As in Option A a capacitor can be applied to the MR- input of the Power Supervision if a
longer delay time is needed for the STM8 to stabilize.
Suggested part number for the Schmitt NAND gate is the SN74HC7001 and for the
Inverter is the SN74LVC1G04.
After considering the Pulse Circuit, Power Supervision, and Current Drivers once again
the circuit is complicated enough to require a circuit board.
Option C:
83
You may want to consider using a UPS to prevent power loss. That will solve most of the
problems discussed here. If power loss is nearly non-existent, then the only concern is
brief relay chatter in event of a reboot, which should also be nearly non-existent once the
Network Module is set up.
IMPORTANT: I have not implemented any of the above power loss circuits, so
there may be errors in what I’ve described. If you plan to go this route analyze the
design carefully.
Summary:
In the end you need to consider carefully if fully retaining the relay states all the way
through a power loss is really necessary. You can use the Retain setting in the Network
Module to be sure the relays return to their pre-power loss state, but they may still
“chatter” once or twice during reboot or power loss and recovery.
84
Adding DS18B20 Temperature Sensors
Code was added to allow you to use IO 16 (pin 16) for DS18B20 Temperature Sensors.
You can attach up to 5 DS18B20 sensors to this pin.
In the Features section of the Configuration page you’ll see a checkbox for DS18B20.
If you check this box IO 16 will show as “Disabled”, and in fact the pin IS disabled for
use as an Input/Output pin. But you can now attach up to 5 DS18B20 temperature sensors
to the pin and have the temperature seen at these sensors displayed in the IOControl page.
If you also check MQTT the temperature is Published on MQTT. And, if you also check
HA Auto the temperature sensor will be Auto Discovered in Home Assistant.
85
Diagram for attaching multiple sensors:
On power up the temperature display may show a “filler” value of ------°C degrees for
each sensor. Likewise, if one of the 5 sensors is missing it will show the filler value. As
soon as communication with the sensor is established the value will be as reported by the
sensor. If the sensor fails or becomes disconnected after initial communication is
established the reported temperature will be -000.1°C until the firmware discovers that
the sensor is missing or unresponsive. Once the sensor is replaced or re-connected the
temperature reported will require 1 to 2 minutes for the DS18B20 to begin reporting
correct values. In the meantime the reported values may be indeterminate.
The sensors appear in the display in the order of the unique 48-bit Serial Number
contained within each DS18B20. All 48 bits are displayed as the Temperature sensor ID
(6 bytes shown as 12 hex encoded characters). But there is a little bit of a catch: The
serial numbers are read from the devices LSbit first, so the device discovery and sorting
algorithm is based on LSbit to MSbit, one bit at a time. However, the display of the
values is shown MSByte on the left to LSByte on the right. So, they might not appear to
be in some sort of ascending order, but in fact they are.
Since the serial numbers are sorted as described above they will always maintain their
order in the Browser display. Thus if a sensor fails and is replaced the new sensor might
be inserted in the list at any point (again, based on the LSbit to MSbit sorting). But a
given sensor’s ID will always remain the same.
Note that Home Assistant sorts the sensors in ascending order based on the MSByte to
LSByte order. So, Home Assistant will display the sensor ID’s in a different order than
the Browser.
86
Developers: Setting Up a Development
Environment
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code. You don’t need to do this if you are going to
use the binaries (.stp and .sx files) already provided.
If you want to change the code for your own use I assume you have some experience
with coding and the tools typically involved. I used the tools described in the previous
sections for actual programming of the device, and used the Cosmic tools for the
development environment. To duplicate this you'll want the following:
1) Download and install the Cosmic Compiler: Use the one that is specifically for
the STM8 devices. Start at this website
https://www.st.com/en/development-tools/cxstm8.html#product-details
Click on Product Details and follow the link to the "partner website". From there
you can download the compiler. The compiler is free. They will send you a 1-year
license, but I think you can renew over and over. Note that the license is specific
to the machine you install it on.
As an FYI, even though my PC is x64, the tools installed in this directory:
C:/Program Files (x86)/COSMIC/FSE_Compilers/
3) Copy the Program: With the above installed the next step is to copy the entire
project from GitHub into your Documents directory. On my Windows 10 machine
the project was located in the following directory:
C:/Users/Mike/Documents/COSMIC/FSE_Compilers/CXSTM8/NetworkModule
Of course you will likely have a different user ID.
Start the Cosmic tools by double clicking on the NetworkModule.prjsm8 file. You should
be on your way.
A note about my coding style: My coding is not particularly esoteric or convoluted. I try
to keep it simple to read and understand even if that is less efficient. And I put a lot of
comments in, particularly if I had to do things to make the code work that didn’t fully
87
make sense to me. Sometimes that stuff happens and my intention is to come back and
look at it again later. So, feel free to modify and “do it your way”. I’m not proud as long
as it works.
88
Developers: Location of EEPROM Variables
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
You can view the contents of the EEPROM with the STVP programmer by selecting the
“Data Memory” tab and using the “Read / Current Tab” function. The displayed
information has the following definitions.
Note that the data in some fields is “left to right”, a more human readable direction. For
instance the device_name field. Some fields are “right to left”, for instance the hostaddr
field.
89
The debug bytes are defined by the developer to provide non-volatile storage of any
information the developer needs to debug code function. Some routines are already
present in the source files to help with capture of debug information.
90
Developers: Notes on Debug Bytes
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
The code contains compile options for implementing various debug modes. This section
describes the debug modes and how debug information is captured in EEPROM.
When code is compiled with any DEBUG_SUPPORT option debug data is stored
in RAM locations named debug[].
The data in the debug[] RAM locations is copied to EEPROM when the function
update_debug_storage1() is called, or when a function requires specific debug[]
bytes to be stored in EEPROM. In some functions any change in a specific
debug[] byte will cause it to be stored in EEPROM.
Note that ANY time a debug[] byte is stored in EEPROM it is first compared to the byte
already stored in EEPROM, and the EEPROM write only occurs if the bytes do not
compare. This is to prevent excessive writes to EEPROM. Example code:
for (i = 0; i < NUM_DEBUG_BYTES; i++) {
if (stored_debug[i] != debug[i]) stored_debug[i] = debug[i];
}
IMPORTANT: This “compare before write to EEPROM” concept should be used any
time a write to EEPROM of any kind is to occur. This will help prevent excessive wear
on the EEPROM, particularly when a coding error is made that might cause a frequent
write to EEPROM.
ALSO IMPORTANT: The EEPROM must be unlocked prior to any write (see function
unlock_eeprom() ). After the write the EEPROM should be locked again (see function
lock_eeprom() ). This helps prevent coding errors from inadverently writing EEPROM.
91
When code is compiled with DEBUG_SUPPORT == 1
All debug[] bytes are available to the developer to be used as needed, and they are
copied to EEPROM when the function update_debug_storage1() is called.
!!!!! Leave DEBUG_SUPPORT 11 enabled for Production Code. While this seems
inconsistent with the normal use of “debug”, DEBUG_SUPPORT 11 enables the
“Link Error Stats” web page. The Link Error Stats web page can be very useful to
regular users that may need to diagnose whether Full Duplex is needed with their
network switch(es).
update_debug_storage()
This function will copy the debug[] bytes to EEPROM only if debug[0] == 0x01.
If the function finds that debug[0] contains 0x01 it will write 0x02 into debug[0].
This creates a “single snapshot” capability.
capture_uip_buf_transmit()
This function will capture a portion of the uip_buf when transmit data is present.
The function can be modified to perform the capture when various triggers are
present. There are some sample triggers in the code that are commented out.
capture_uip_buf_receive()
This function is similar to capture_uip_buf_transmit but contains triggers for
capturing a portion of the uip_buf when receive data is present. There are some
sample triggers in the code that are commented out.
capture_mqtt_sendbuf()
This function is similar to the other capture functions above except that it is
designed to capture a portion of the data in the MQTT sendbuf.
92
#define DEBUG_SUPPORT table
Bits
7 6 5 4 3 2 1 0 De Function
c
0 0 0 0 0 0 0 0 0 No debug
No UART
No Link Error Stats browser page
0 0 0 0 0 0 0 1 1 debug[] bytes enabled - visible only via STVP
No UART
No Link Error Stats browser page
0 0 0 0 0 1 1 1 7 debug[] bytes enabled - visible only via STVP
Last 10 bytes of debug[] allocated to specific debug data
UART enabled
No Link Error Stats browser page
0 0 0 0 1 0 1 1 11 debug[] bytes enabled – visible only via STVP
Last 10 bytes of debug[] allocated to specific debug data
No UART
Link Error Stats browser page enabled
Set DEBUG_SUPPORT 11 for Production Code
0 0 0 0 1 1 1 1 15 debug[] bytes enabled – visible only via STVP
Last 10 bytes of debug[] allocated specific debug data
UART enabled
Link Error Stats browser page enabled
“visible only via STVP” means that the STVP programmer software should be used to
display the “Data Memory” in order to view these bytes. See section “Location of
EEPROM Variables”.
93
The table below defines the debug[] bytes dependent on the DEBUG_SUPPORT setting.
Note that NUM_DEBUG_BYTES defined in main.h sets the total number of debug[]
bytes available. If you make code changes that use up more EEPROM you will have to
adjust NUM_DEBUG_BYTES in main.h,
94
Developers: Notes on Configuration Debug
and pin_control Bytes
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
The Configuration page contains a debug feature useful for development. If you go to the
Configuration page, add #d to the URL, then click Refresh a column of numbers will
appear to the right of the settings as illustrated here:
These values are the decimal equivalents of the content of the pin_control bytes in the
code. The pin_control bytes are defined as shown here:
95
96
Developers: Notes on Proto-Sockets
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Most developers that build web server code are familiar with Windows or Linux systems
which provide a “socket” interface. The “socket” basically maintains all pointers and
parameters associated with a given network connection.
In a “bare metal” application like the Network Module there is no operating system
providing the socket interface, so a bare-bones implementation is used and is typically
called a “proto-socket” interface. The interface maintains only the very basic and
essential pointers and parameters associated with network connections in order to
minimize memory associated with the connections.
I didn’t write the original code used for proto sockets in this application, but I did modify
it as needed. Here are some notes I took along the way in case they are useful to other
developers and for future debug efforts.
struct uip_conn is a single structure identifying all the paramters of a single connection,
and each uip_conn is connected by a union to a struct tHttpD, thus defining a "Proto-
Socket". A Proto-Socket is really just the set of parameters that define the variables,
pointers, and status of a given connection.
uip_conns[] is an array of the uip_conn structures, and the number of elements in the
uip_conns[] array is defined by UIP_CONNS in the uipopt.h file. The uip_conns[] array
of structures is statically allocated in the uip.c file with this statement:
struct uip_conn uip_conns[UIP_CONNS];
So, the structures are "pre-existing" and remain in RAM at all times. Note that anything
added to the structure will occupy memory on a per uip_conn basis, so if I add say 10
bytes to the structure is will be multiplied by the UIP_CONNS value. UIP_CONNS is
defined as 4 in this application, so adding 10 bytes to the structure would add 40 bytes of
memory consumption.
Where is the content of the structure initialized? In uip.c, where the only real
initialization is to set each connection to UIP_CLOSED as follows:
void uip_init(void)
{
for (c = 0; c < UIP_LISTENPORTS; ++c) uip_listenports[c] = 0;
for (c = 0; c < UIP_CONNS; ++c) uip_conns[c].tcpstateflags = UIP_CLOSED;
/* IPv4 initialization. */
}
97
A connection is set up when a packet arrives over ethernet with the appropriate MAC, IP,
and Port. If the Port matches one of the "listening ports" then the uip_process() code finds
its way to the "found_listen:" code, an unused connection is located in the connection
table, and the necessary connection parameters are initialized in one of the uip_conn
structures contained in the uip_conns[] array.
For each connection I maintain all necessary parameters in the uip_conn structures with
the exception of variables used in parsing POSTs. Of these variables the parse_tail[] array
is the largest. parse_tail[] is used when parsing POST data from a Browser. parse_tail[] is
very large and must be maintained across packet fragments in a POST. parse_tail[] is too
large have a separate one for each connection ... so it is a usage requirement that the user
must never POST from more than one Browser at a time. If they do the parse_tail[] will
be corrupted and results will be indeterminate.
The other variables used in POST parsing are the “Pending_” variables. These provide
temporary storage of user entered data POST parsing completes. There are many of these
and there is not enough memory for them to be maintained in the uip_conn structures, so
again it is a usage requirement that the user never POST from more than one Browser at a
time.
In similar fashion the Code Uploader must only be run from one Browser as it is a
"POST" mechanism.
98
Developers: #pragma, Sections, Segments
and the .lkf File
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
I’ve included this section mostly so I don’t forget how all this works.
There are several places where I’ve had to define additional “segments” where code is
segregated for specific purposes. Those areas are:
a) Stack Overflow detection
b) Flash Update code
c) Copy RAM to Flash code
In general the reason that these segments must be defined in this application is to 1)
enable the linker to provide warnings if segment sizes interfere with each other, 2)
specify the location of specific code so that Flash updates will work without overwriting
code that is being used, 3) enable special functionality to copy RAM content to Flash.
LinkFileAutomatic=NO
When you first install IdeaSTM8 the default is for the program to auto generate the .lkf
file each time a build is done. This is useful because it creates all the linker commands
you typically need. However, when you reach the point that you need to make your own
changes to the .lkf file (such as described below) edit access is disabled until the
LinkFileAutomatic line is modified to “NO”.
99
One way to locate RAM variables in a specific location is to simply use Absolute
Addressing. For example:
uint8_t stack_limit1 @0x05fe;
uint8_t stack_limit2 @0x05ff;
Those two declarations would place the variables at addresses 0x05fe and 0x05ff.
However, using that method does not let the compiler/linker validate whether its own
variable placements also utilize those two memory addresses. So, using the #pragma and
linker directives is the safer method to use.
The pragma code creates the two variables in a special section named ".iconst". In the
main.c file a pragma section is created that looks like this:
#pragma section @near [iconst]
uint8_t stack_limit1;
uint8_t stack_limit2;
#pragma section @near []
The linker needs to be told where to place this section in memory. The following
directive needs to be placed in the .lkf file. This directive will place the two stack limit
variables at 0x5fe and 0x5ff. In the .lkf file specify the location of the pragma section like
this:
+seg .iconst -b 0x5fe -n .iconst
Now the linker will be able to warn you if allocation of variables in RAM has enough
space.
In order for a) and b) to work the I2C driver must remain functional throughout the write
to Flash. This requires that the I2C driver be located in a part of Flash that will remain
untouched until the final parts of the Flash update.
Further, because the I2C driver itself might be updated there needs to be a means of over-
writing that driver with code running from some location other than Flash. In this
application that code (the copy_ram_to_flash() function) will run from RAM.
And one last requirement: To make the Flash writes occur as fast as possible they must
occur as 128 byte block writes. This is accomplished in the Flash update code by copying
100
four 128 byte blocks from I2C EEPROM to RAM, then calling the copy_ram_to_flash()
function to copy those blocks from RAM to Flash.
To keep the I2C driver segment separate from the rest of the Flash code it is located in
upper Flash as follows:
In the I2C.c file a #pragma flash_update code segment is defined containing the
I2C driver and functions which call the copy_ram_to_flash() code.
In the linker .lkf file the following directive is added to specify the location of the
pragma section:
+seg .flash_update -b 0xfc80
The copy_ram_to_flash() code also requires special handling as the STM8 hardware will
only allow copies from RAM to Flash if the code performing the copy is running in
RAM. Since RAM is very limited the copy_ram_to_flash code is designed to have a
minimal code space footprint. The steps to implement this part of the code are as follows:
In the linker .lkf file the following directives are added to specify the location of
the pragma section:
+seg .memcpy_update -a .data -n memcpy_update –ic
+seg .bss -a memcpy_update -n .bss
In the main.c file the following code causes the copy_ram_to_flash() function to
be relocated to RAM. Once relocated, the function can be called like any other
function.
_fctcpy ('m');
Given the above: To complete a copy of new firmware from I2C EEPROM to Flash the
process is as follows:
101
a) The _fctcpy ('m') function is called from main.c
b) The eeprom_copy_to_flash() function is called from main.c. This function will
copy all of the I2C EEPROM content to Flash except for the segment containing
the I2C driver and copy_ram_to_flash() code. As mentioned this is done by
copying 512 bytes to RAM then copying the 512 bytes to Flash and repeating as
needed.
c) The last step in the eeprom_copy_to_flash() code is to copy the I2C Driver and
copy_ram_to_flash() function to RAM. These functions fit within 512 bytes. Next
the code initiates a copy of those functions from RAM to Flash. Remember, at
this point the actual copy function is being run from the existing
copy_ram_to_flash() function in RAM, so it doesn’t matter that the functions are
being over-written in Flash. Once the copy completes, the code waits for a device
reset using the Window watchdog function. At boot the new firmware is run from
Flash.
102
_fctcpy
For reference the following is from the CXSTM8_UserGuide.pdf:
103
#pragma Sections
For reference the following describes how to create #pragma sections.
https://cosmic-software.com/faq/faq18.php
104
Content of the .lkf File
For reference the +seg part of the .lkf file for this project looks like this:
105
Paraphrased from the CXSTM8_Userguide.pdf
-b* set the physical start address of the segment to *. Option –e or -a cannot be specified
if -b has been specified.
-m* set the maximum size of the segment to * bytes. If not specified, there is no checking
on any segment size. If a segment is declared with the -a option as following a segment
which is marked with the -m option, then set the maximum available space for all the
possible consecutive segments. If a -m is specified on a -a segment, the actual maximum
size checked is equal to the given value minus the size of all the segments already
allocated from the first segment of the –a list. So the new maximum size is computed
from the start address of the list and not from the start address of that segment.
-n* set the output name of the segment to *. Segment output names have at most 15
characters; longer names are truncated. If no name is given with a -n option, the segment
inherits a default name equal to its assembler section name.
106
Developers: STM8 Address Map
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
107
Developers: Flash Memory Map
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
108
STM8 Flash Map for Upgradeable builds
Block Number Block Start Content Equivalent Address in
(128 Bytes per Address I2C EEPROM Region 0
Block)
000 0x8000 Reset and Interrupt 0x0000
Vectors
001 0x8080 Constants and Code 0x0080
…
248 0xfc00 Constants and Code 0x7c00
109
Developers: I2C EEPROM Memory Map
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Region 2: Strings
Used to store the “Strings”, ie, the IO Control and Configuration webpage
content.
110
Addressing the I2C EEPROM Regions
This gets a little confusing so some explanation is required.
The 24xx1025 is addressed as if it were a pair of 64KB devices. So even though it is used
as four 32KB regions, the addressing of the device requires some translation.
When Region 0 or Region 1 are addressed the “I2C Command Byte” used on the I2C bus
to perform a Read is 0xa1, and to perform a Write is 0xa0. Then Region 0 is addressed as
bytes 0x0000 to 0x7fff, and Region 1 is addressed as bytes 0x8000 to 0xffff.
When Region 2 or Region 3 are addressed the “I2C Command Byte” used on the I2C bus
to perform a Read is 0xa9, and to perform a Write is 0xa8. Then Region 2 is addressed as
bytes 0x0000 to 0x7fff, and Region 3 is addressed as bytes 0x8000 to 0xffff.
The following defines are used to help translate this into something more “readable” in
code:
111
Developers: Strings File Generation
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
When using Upgradeable Builds a “Strings File” must be generated and stored in the I2C
EEPROM. The “Strings File” contains the HTML and Javascript that defines the IO
Control and Configuration web pages. That HTML and Javascript resides in the httpd.c
file, but it must be extracted and placed in a separate .sx file for upload to the Network
Module.
I’ve written a program that runs in the Windows environment that parses the httpd.c file,
locates the webpage HTML of interest, and generates the required .sx file. Along with the
HTML text the .sx file also includes pointers to the start of the HTML in the .sx file and
the size of the HTML text. The resulting .sx file can be directly uploaded to the Network
Module using the Code Uploader.
112
Developers: Using the UART
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
The STM8S processor includes a UART. The code can be compiled with the UART
enabled so that you can add debug statements to the code. The compile option is available
in the uipopt.h file (see #define DEBUG_SUPPORT).
When the UART is enabled it will take over IO Pin 11 and use that as the UART transmit
pin. No UART receive pin is implemented. The Configuration page will show the pin 11
as an Output, and you will not be able to change that pin configuration when the UART
option is compiled. Likewise, the IOControl page will show the pin as an Output, and any
attempt to change the pin state will not be successful. But the pin will continue to
function as the UART output until the code is recompiled with the Debug UART option
turned off.
To connect the Network Module UART Tx pin (IO 11) to a terminal or your PC you’ll
need a TTL-RS232 or TTL-USB converter. There are several ways to to this, but I will
describe the method I used:
a) Use a TTL-USB converter to connect the Tx pin to the USB port on a laptop.
Here’s the device I used:
113
Keep in mind that the Network Module operates at 3V, so the adapter needs to be
set to 3V IO on the pin connection side of the interface.
b) My laptop was a Windows 10 OS, so I had to download the drivers for the TTL-
USB interface here:
https://ftdichip.com/drivers/
114
d) If everything is set up correctly you should see something like this in the PuTTY
display when the Network Module boots:
Note: Use the http command “http://IP:Port/70” to clear the “Reset Status Register"
counters (the counts for EMCF, SWIMF, ILLOPF, IWDGF, WWDGF). See the STM8S
documentation for definitions of the Reset Status Register content.
115
Developers: Analysis of MQTT sendbuf
sizing
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
During MQTT startup we do not queue any MQTT messages. They are sent one at a
time, and in the case of CONNECT or SUBSCRIBE messages the code will wait for an
ACK from the broker.
After startup there can be queuing of messages, but that queue will only grow to a
maximum of 2 messages. This occurs when a PINGREQ is issued, and that request
immediately precedes or immediately follows some other PUBLISH message. The reason
the queue is needed is because we need to watch for a PINGRESP (an ACK) to the
PINGREQ. Thus, the PINGREQ is retained in the queue until the PINGRESP is received.
PUBLISH does not wait for an ACK since we are operating as QOS0.
Why is all the above mentioned? Because we want the mqtt_sendbuf to be as small as
possible. The way the MQTT code works is that it places a message in the mqtt_sendbuf,
and that message is always accompanied by a queue management structure of about 11
bytes. So to determine the mimimum size required for mqtt_sendbuf we need to know
that maximum size MQTT message that will go in the buffer.
116
It turns out the largest message is the CONNECT message, which is sent during
MQTT startup. At that time no PINGREQ messages can be issued, so the CONNECT
message will occupy the mqtt_sendbuf by itself. An analysis of the size of the
CONNECT message:
CONNECT message
Payload:
The payload of the CONNECT Packet contains one or more length-prefixed fields,
whose presence is determined by the flags in the variable header. These fields, if present,
MUST appear in the order Client Identifier, Will Topic, Will Message, User Name,
Password [MQTT-3.1.3-1].
Client Identifier:
NetworkModuleaabbccddeeff
2 length bytes + 25 bytes data = 27
Will Topic:
NetworkModule/NetworkModule456789/availability
2 length bytes + 46 bytes data = 48
Will Message:
Offline
2 length bytes + 7 bytes data
UserName:
2 length bytes + 10 bytes data
Password:
2 length bytes + 10 bytes data
117
Queue management structure 11 bytes
The only messages that must be retained in the mqtt_sendbuf are the CONNECT,
SUBSCRIBE, and PINGREQ messages. Since the CONNECT and SUBSCRIBE
messages are only sent by the mqtt_startup state machine we can carefully manage that
state machine to make sure the ACK for each of those messages is received before
continuing the state machine. This means that the only message that will be retained in
the mqtt_sendbuf during normal operation is the PINGREQ message. That message is
two bytes long. So, we can minimize the size of the mqtt_sendbuf to the point that only
that 2 byte message and the longest of any other MQTT transmit message will fit.
The implication of the above is that the mqtt_sendbuf needs to be as large as one
PINGREQ message (2 bytes) plus the longest Publish message (59 bytes), or 61 bytes. I
118
think the structure added to the mqtt_sendbuf for each message in the queue is 11 bytes
(search on struct mqtt_queued_message).
This would make the requirement for the mqtt_sendbuf AFTER MQTT STARTUP = 61
+ 22 = 83.
Since we know the CONNECT message far exceeds this value it will set the size of
the mqtt_sendbuf.
119
Developers: Storing Variables in Flash via
the Application
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Flash Programming
Beginning in April 2021 the ability to have user entered names for each IO pin was
implemented. This required storing those names in Flash memory (not EEPROM).
Following are notes on how this is done.
The following excerpts from the RM0016 and PM0051 clearly indicate that performing
byte and word writes to Flash will stop application execution until the write completes. If
word or byte writes are implemented it is not necessary to have code execution in
RAM. However, block writes to Flash do require code execution in RAM.
It appears that when byte writes are performed they may cause as many as 4 erase/write
cycles on all 4 bytes around a memory location. This is because Flash is actually written
4 bytes at a time even if a single byte is being written. So if you write 4 bytes in a row,
you actually write all 4 bytes 4 times.
For this reason the Word method (4-bytes at a time) will cause less wear on memory. If 4
bytes are going to be written sequentially anyway then writing them as a 4-byte Word
will result in one erase/write cycle on that Word instead of 4 cycles. PM0051 section 4.3
describes how to do this. A logical presumption (because I can’t find it in manuals): The
first byte of a Word must be at an address ending in 0, 4, 8, or C.
Since writes always occur 4 bytes at a time, code should be written to write 4 byte values
as much as possible. So, consideration needs to be taken to accumulate writes in RAM
first, then write them as 4 byte values to Flash. The 4 byte values are on 4 byte
boundaries starting at address 0x0000. Example of a 4 byte write:
unlock_flash();
for (i=0; i<8; i+=2) {
// IO_TIMER values are 2 byte values. They are accumulated in RAM first, then
// the sixteen 2 byte values are written to Flash as eight 4 byte values. First
120
// the values in RAM are compared to what is already in Flash to make sure no
// unnecessary writes are performed.
// Compare 4 bytes at a time. If any miscompare write to Flash 4 bytes at a time.
if (IO_TIMER[i] != Pending_IO_TIMER[i] || IO_TIMER[i+1] !=
Pending_IO_TIMER[i+1]) {
FLASH_CR2 = 0x40;
FLASH_NCR2 = 0xBF;
memcpy(&IO_TIMER[i], &Pending_IO_TIMER[i], 4);
}
}
lock_flash();
There is no protection against code being written to the "reserved" area, so care needs to
be taken that code size doesn't grow too large and over-lap the “reserved” area.
The specification states that there is 32K of Flash (32768 bytes). But the first 128 bytes
(starting at 0x8000) is used for interrupt vectors. So if we use 320 bytes for user data the
maximum code size is 32768 - 128 - 320 = 32320.
The real problem with using Flash for user data is that it has very limited write life. So
frequent changes should be avoided. Caution the user to set IO names and IO timers only
a few times during the life of the device. NEVER use an automated mechanism that
might inadvertantly change the names or timer values a lot of times.
Note that single byte writes should be avoided. A single byte write actually results in a 4
byte write of the targeted byte plus the 3 other bytes in the 4 byte "word". So if you want
to write all 4 bytes in a word and you do that one byte at a time, you will actually write
every byte of the word 4 times. This creates a lot of wear on the Flash, so in this
application data that will be written to the Flash is first accumulated in RAM, then
written to Flash as a series of 4 byte "word" writes.
Note that program execution is suspended by hardware for the 6ms that a Flash write is
being performed. From the PM0047 manual:
"Byte programming is done by executing any write instruction (ld, mov...) to a
Flash memory address when the memory is unlocked. The write instruction
initiates the erase/programming cycle and any core access to the memory is
121
blocked until the cycle is over. This means that program execution from Flash is
stopped until the end of the erase/programming cycle. At the end of the
programming the EOP bit in the FLASH_IAPSR is set and program execution
restarts from the instruction following the write/erase instruction."
A write to Flash requires about 6ms regardless of whether it is a 1 byte or 4 byte write.
Just for reference if the entire 320 byte reserved area of Flash were written at one time it
would take about (320 / 4) * 6ms = 480ms. Since this only occurs when the user makes
changes it is not significant to operation of the device.
From CXSTM8_UsersGuide:
Referencing Absolute Addresses
References to absolute addresses have the general form @<address>, where
<address> is a valid memory location in your environment. For example, to
associate an I/O port at address 0x20 with the identifier name MISCR1, write a
definition of the form:
char MISCR1 @0x20;
where @0x20 indicates an absolute address specification and not a data initializer.
Since input/output on the STM8 architecture is memory mapped, performing I/O
in this way is equivalent to writing in any given location in memory. Such a
declaration does not reserve any space in memory. The compiler still creates a
label, using an equate definition, in order to reference the C object symbolically.
This symbol is made public to allow external usage from any other file.
Flash Unlock/Lock
Unlock: Write 56h then AEh in FLASH_PUKR (00 5062h)
Lock: Reset bit 1 (PUL) in FLASH_IAPSR (00 505Fh)
122
RM0016
RM0016
PM0051
PM0051
123
124
Developers: Flash and EEPROM Wear Notes
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
125
Here is the pertinent device specification for the STM8S005C6 from data sheet DS8638
Rev 5 dated September 2018.
126
Code Credits
This project borrows heavily from the work of Simon Kueppers “MicroWebServer”
project available on GitHub. Extract of Simon Kueppers’ code sharing statement:
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kueppers work in turn borrows heavily from the work of Adam Dunkels uIP
project, also available on GitHub and other locations. Extract of Adam Dunkels’ code
sharing statement:
/**
* \file
* The uIP TCP/IP stack code.
* \author Adam Dunkels <[email protected]>
*/
/*
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
127
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
With the addition of the MQTT Interface the following statement is applicable:
MIT License
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
128
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.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
And, finally, I want to credit Carlos Ladeira and Jevgeni Kiski for their very significant
contributions to code and test.
129
Documentation License Note
And now for the GNU Free Documentation License (follows on the next page). If you
read the short preamble the typical user will know all you really need to know.
130
GNU Free Documentation License
Version 1.3, 3 November 2008
Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
<https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other functional
and useful document "free" in the sense of freedom: to assure everyone the
effective freedom to copy and redistribute it, with or without modifying it, either
commercially or noncommercially. Secondarily, this License preserves for the
author and publisher a way to get credit for their work, while not being considered
responsible for modifications made by others.
This License is a kind of "copyleft", which means that derivative works of the
document must themselves be free in the same sense. It complements the GNU
General Public License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software,
because free software needs free documentation: a free program should come
with manuals providing the same freedoms that the software does. But this
License is not limited to software manuals; it can be used for any textual work,
regardless of subject matter or whether it is published as a printed book. We
recommend this License principally for works whose purpose is instruction or
reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium, that contains a
notice placed by the copyright holder saying it can be distributed under the terms
of this License. Such a notice grants a world-wide, royalty-free license, unlimited
in duration, to use that work under the conditions stated herein. The "Document",
below, refers to any such manual or work. Any member of the public is a
licensee, and is addressed as "you". You accept the license if you copy, modify
or distribute the work in a way requiring permission under copyright law.
A "Modified Version" of the Document means any work containing the Document
or a portion of it, either copied verbatim, or with modifications and/or translated
into another language.
A "Secondary Section" is a named appendix or a front-matter section of the
Document that deals exclusively with the relationship of the publishers or authors
of the Document to the Document's overall subject (or to related matters) and
contains nothing that could fall directly within that overall subject. (Thus, if the
Document is in part a textbook of mathematics, a Secondary Section may not
131
explain any mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal, commercial,
philosophical, ethical or political position regarding them.
The "Invariant Sections" are certain Secondary Sections whose titles are
designated, as being those of Invariant Sections, in the notice that says that the
Document is released under this License. If a section does not fit the above
definition of Secondary then it is not allowed to be designated as Invariant. The
Document may contain zero Invariant Sections. If the Document does not identify
any Invariant Sections then there are none.
The "Cover Texts" are certain short passages of text that are listed, as Front-
Cover Texts or Back-Cover Texts, in the notice that says that the Document is
released under this License. A Front-Cover Text may be at most 5 words, and a
Back-Cover Text may be at most 25 words.
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the general public,
that is suitable for revising the document straightforwardly with generic text
editors or (for images composed of pixels) generic paint programs or (for
drawings) some widely available drawing editor, and that is suitable for input to
text formatters or for automatic translation to a variety of formats suitable for
input to text formatters. A copy made in an otherwise Transparent file format
whose markup, or absence of markup, has been arranged to thwart or
discourage subsequent modification by readers is not Transparent. An image
format is not Transparent if used for any substantial amount of text. A copy that is
not "Transparent" is called "Opaque".
Examples of suitable formats for Transparent copies include plain ASCII without
markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly
available DTD, and standard-conforming simple HTML, PostScript or PDF
designed for human modification. Examples of transparent image formats include
PNG, XCF and JPG. Opaque formats include proprietary formats that can be
read and edited only by proprietary word processors, SGML or XML for which the
DTD and/or processing tools are not generally available, and the machine-
generated HTML, PostScript or PDF produced by some word processors for
output purposes only.
The "Title Page" means, for a printed book, the title page itself, plus such
following pages as are needed to hold, legibly, the material this License requires
to appear in the title page. For works in formats which do not have any title page
as such, "Title Page" means the text near the most prominent appearance of the
work's title, preceding the beginning of the body of the text.
The "publisher" means any person or entity that distributes copies of the
Document to the public.
A section "Entitled XYZ" means a named subunit of the Document whose title
either is precisely XYZ or contains XYZ in parentheses following text that
132
translates XYZ in another language. (Here XYZ stands for a specific section
name mentioned below, such as "Acknowledgements", "Dedications",
"Endorsements", or "History".) To "Preserve the Title" of such a section when you
modify the Document means that it remains a section "Entitled XYZ" according to
this definition.
The Document may include Warranty Disclaimers next to the notice which states
that this License applies to the Document. These Warranty Disclaimers are
considered to be included by reference in this License, but only as regards
disclaiming warranties: any other implication that these Warranty Disclaimers
may have is void and has no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either commercially
or noncommercially, provided that this License, the copyright notices, and the
license notice saying this License applies to the Document are reproduced in all
copies, and that you add no other conditions whatsoever to those of this License.
You may not use technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough number of
copies you must also follow the conditions in section 3.
You may also lend copies, under the same conditions stated above, and you may
publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly have printed
covers) of the Document, numbering more than 100, and the Document's license
notice requires Cover Texts, you must enclose the copies in covers that carry,
clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover,
and Back-Cover Texts on the back cover. Both covers must also clearly and
legibly identify you as the publisher of these copies. The front cover must present
the full title with all words of the title equally prominent and visible. You may add
other material on the covers in addition. Copying with changes limited to the
covers, as long as they preserve the title of the Document and satisfy these
conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit legibly, you should
put the first ones listed (as many as fit reasonably) on the actual cover, and
continue the rest onto adjacent pages.
If you publish or distribute Opaque copies of the Document numbering more than
100, you must either include a machine-readable Transparent copy along with
each Opaque copy, or state in or with each Opaque copy a computer-network
location from which the general network-using public has access to download
using public-standard network protocols a complete Transparent copy of the
Document, free of added material. If you use the latter option, you must take
133
reasonably prudent steps, when you begin distribution of Opaque copies in
quantity, to ensure that this Transparent copy will remain thus accessible at the
stated location until at least one year after the last time you distribute an Opaque
copy (directly or through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of the Document
well before redistributing any large number of copies, to give them a chance to
provide you with an updated version of the Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document under the
conditions of sections 2 and 3 above, provided that you release the Modified
Version under precisely this License, with the Modified Version filling the role of
the Document, thus licensing distribution and modification of the Modified
Version to whoever possesses a copy of it. In addition, you must do these things
in the Modified Version:
• A. Use in the Title Page (and on the covers, if any) a title distinct from that of
the Document, and from those of previous versions (which should, if there
were any, be listed in the History section of the Document). You may use the
same title as a previous version if the original publisher of that version gives
permission.
• B. List on the Title Page, as authors, one or more persons or entities
responsible for authorship of the modifications in the Modified Version,
together with at least five of the principal authors of the Document (all of its
principal authors, if it has fewer than five), unless they release you from this
requirement.
• C. State on the Title page the name of the publisher of the Modified Version,
as the publisher.
• D. Preserve all the copyright notices of the Document.
• E. Add an appropriate copyright notice for your modifications adjacent to the
other copyright notices.
• F. Include, immediately after the copyright notices, a license notice giving the
public permission to use the Modified Version under the terms of this License,
in the form shown in the Addendum below.
• G. Preserve in that license notice the full lists of Invariant Sections and
required Cover Texts given in the Document's license notice.
• H. Include an unaltered copy of this License.
• I. Preserve the section Entitled "History", Preserve its Title, and add to it an
item stating at least the title, year, new authors, and publisher of the Modified
Version as given on the Title Page. If there is no section Entitled "History" in
the Document, create one stating the title, year, authors, and publisher of the
Document as given on its Title Page, then add an item describing the
Modified Version as stated in the previous sentence.
• J. Preserve the network location, if any, given in the Document for public
access to a Transparent copy of the Document, and likewise the network
locations given in the Document for previous versions it was based on. These
134
may be placed in the "History" section. You may omit a network location for a
work that was published at least four years before the Document itself, or if
the original publisher of the version it refers to gives permission.
• K. For any section Entitled "Acknowledgements" or "Dedications", Preserve
the Title of the section, and preserve in the section all the substance and tone
of each of the contributor acknowledgements and/or dedications given
therein.
• L. Preserve all the Invariant Sections of the Document, unaltered in their text
and in their titles. Section numbers or the equivalent are not considered part
of the section titles.
• M. Delete any section Entitled "Endorsements". Such a section may not be
included in the Modified Version.
• N. Do not retitle any existing section to be Entitled "Endorsements" or to
conflict in title with any Invariant Section.
• O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or appendices that
qualify as Secondary Sections and contain no material copied from the
Document, you may at your option designate some or all of these sections as
invariant. To do this, add their titles to the list of Invariant Sections in the Modified
Version's license notice. These titles must be distinct from any other section
titles.
You may add a section Entitled "Endorsements", provided it contains nothing but
endorsements of your Modified Version by various parties—for example,
statements of peer review or that the text has been approved by an organization
as the authoritative definition of a standard.
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover
Texts in the Modified Version. Only one passage of Front-Cover Text and one of
Back-Cover Text may be added by (or through arrangements made by) any one
entity. If the Document already includes a cover text for the same cover,
previously added by you or by arrangement made by the same entity you are
acting on behalf of, you may not add another; but you may replace the old one,
on explicit permission from the previous publisher that added the old one.
The author(s) and publisher(s) of the Document do not by this License give
permission to use their names for publicity for or to assert or imply endorsement
of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified versions,
provided that you include in the combination all of the Invariant Sections of all of
the original documents, unmodified, and list them all as Invariant Sections of your
combined work in its license notice, and that you preserve all their Warranty
Disclaimers.
135
The combined work need only contain one copy of this License, and multiple
identical Invariant Sections may be replaced with a single copy. If there are
multiple Invariant Sections with the same name but different contents, make the
title of each such section unique by adding at the end of it, in parentheses, the
name of the original author or publisher of that section if known, or else a unique
number. Make the same adjustment to the section titles in the list of Invariant
Sections in the license notice of the combined work.
In the combination, you must combine any sections Entitled "History" in the
various original documents, forming one section Entitled "History"; likewise
combine any sections Entitled "Acknowledgements", and any sections Entitled
"Dedications". You must delete all sections Entitled "Endorsements".
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this License in
the various documents with a single copy that is included in the collection,
provided that you follow the rules of this License for verbatim copying of each of
the documents in all other respects.
You may extract a single document from such a collection, and distribute it
individually under this License, provided you insert a copy of this License into the
extracted document, and follow this License in all other respects regarding
verbatim copying of that document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other separate and
independent documents or works, in or on a volume of a storage or distribution
medium, is called an "aggregate" if the copyright resulting from the compilation is
not used to limit the legal rights of the compilation's users beyond what the
individual works permit. When the Document is included in an aggregate, this
License does not apply to the other works in the aggregate which are not
themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these copies of the
Document, then if the Document is less than one half of the entire aggregate, the
Document's Cover Texts may be placed on covers that bracket the Document
within the aggregate, or the electronic equivalent of covers if the Document is in
electronic form. Otherwise they must appear on printed covers that bracket the
whole aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may distribute
translations of the Document under the terms of section 4. Replacing Invariant
Sections with translations requires special permission from their copyright
holders, but you may include translations of some or all Invariant Sections in
addition to the original versions of these Invariant Sections. You may include a
136
translation of this License, and all the license notices in the Document, and any
Warranty Disclaimers, provided that you also include the original English version
of this License and the original versions of those notices and disclaimers. In case
of a disagreement between the translation and the original version of this License
or a notice or disclaimer, the original version will prevail.
If a section in the Document is Entitled "Acknowledgements", "Dedications", or
"History", the requirement (section 4) to Preserve its Title (section 1) will typically
require changing the actual title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document except as
expressly provided under this License. Any attempt otherwise to copy, modify,
sublicense, or distribute it is void, and will automatically terminate your rights
under this License.
However, if you cease all violation of this License, then your license from a
particular copyright holder is reinstated (a) provisionally, unless and until the
copyright holder explicitly and finally terminates your license, and (b)
permanently, if the copyright holder fails to notify you of the violation by some
reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated
permanently if the copyright holder notifies you of the violation by some
reasonable means, this is the first time you have received notice of violation of
this License (for any work) from that copyright holder, and you cure the violation
prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of
parties who have received copies or rights from you under this License. If your
rights have been terminated and not permanently reinstated, receipt of a copy of
some or all of the same material does not give you any rights to use it.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of the GNU
Free Documentation License from time to time. Such new versions will be similar
in spirit to the present version, but may differ in detail to address new problems
or concerns. See https://www.gnu.org/licenses/.
Each version of the License is given a distinguishing version number. If the
Document specifies that a particular numbered version of this License "or any
later version" applies to it, you have the option of following the terms and
conditions either of that specified version or of any later version that has been
published (not as a draft) by the Free Software Foundation. If the Document does
not specify a version number of this License, you may choose any version ever
published (not as a draft) by the Free Software Foundation. If the Document
specifies that a proxy can decide which future versions of this License can be
137
used, that proxy's public statement of acceptance of a version permanently
authorizes you to choose that version for the Document.
11. RELICENSING
"Massive Multiauthor Collaboration Site" (or "MMC Site") means any World Wide
Web server that publishes copyrightable works and also provides prominent
facilities for anybody to edit those works. A public wiki that anybody can edit is an
example of such a server. A "Massive Multiauthor Collaboration" (or "MMC")
contained in the site means any set of copyrightable works thus published on the
MMC site.
"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 license
published by Creative Commons Corporation, a not-for-profit corporation with a
principal place of business in San Francisco, California, as well as future copyleft
versions of that license published by that same organization.
"Incorporate" means to publish or republish a Document, in whole or in part, as
part of another Document.
An MMC is "eligible for relicensing" if it is licensed under this License, and if all
works that were first published under this License somewhere other than this
MMC, and subsequently incorporated in whole or in part into the MMC, (1) had
no cover texts or invariant sections, and (2) were thus incorporated prior to
November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site under
CC-BY-SA on the same site at any time before August 1, 2009, provided the
MMC is eligible for relicensing.
138