Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
DIOT Monitoring Module
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
6
Issues
6
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
Snippets
Snippets
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
DIOT Monitoring Module
Commits
fde87b75
Commit
fde87b75
authored
Oct 22, 2019
by
Christos Gentsos
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Doc: start documenting the firmware
parent
35ccc3b9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
161 additions
and
11 deletions
+161
-11
flash_utils.h
common/include/flash_utils.h
+6
-1
i2c_slave.h
common/include/i2c_slave.h
+10
-0
i2c_slave.c
common/src/i2c_slave.c
+11
-5
Makefile
doc/Makefile
+2
-1
conf.py
doc/source/conf.py
+1
-1
firmware.rst
doc/source/firmware.rst
+117
-3
pid.h
main_fw/include/pid.h
+7
-0
main.c
main_fw/src/main.c
+2
-0
pid.c
main_fw/src/pid.c
+5
-0
No files found.
common/include/flash_utils.h
View file @
fde87b75
...
...
@@ -3,9 +3,14 @@
#define FLASH_ROW_SIZE 256
/*! This struct defines 256 bytes of user data, stored in non-volatile
* memory, including a special 4-byte word which is used to turn on
* remote programming.
*/
typedef
struct
{
//! check if we want to enable the remote programming functionality
uint32_t
copy_fw
;
//! provide some (optional) user data storage
uint8_t
user_data
[
252
];
}
user_flash_t
;
...
...
common/include/i2c_slave.h
View file @
fde87b75
...
...
@@ -26,18 +26,28 @@ enum QUERY_RET_VALS {
QUERY_FMT_NAN
=
0x1c
};
typedef
const
struct
{
//! CMD code
const
uint8_t
addr
;
//! transaction length for this command
int8_t
*
const
data_len
;
//! pointer to data
uint8_t
*
const
data_pnt
;
//! invoked when accessing the command, before any data transfer
const
fp_t
a_callback
;
//! invoked after writing data
const
fp_t
w_callback
;
//! invoked after reading data
const
fp_t
r_callback
;
//! data for the query command
const
uint8_t
query_byte
;
//! always disable PEC for this command if non-zero
const
uint8_t
wr_pec_disabled
;
}
cmd_t
;
typedef
const
struct
{
//! holds number of commands implemented
const
uint8_t
n_cmds
;
//! where the command structure list is stored
cmd_t
*
const
cmds
;
}
cmd_space_t
;
...
...
common/src/i2c_slave.c
View file @
fde87b75
...
...
@@ -43,8 +43,11 @@ int16_t in_addr_space(cmd_space_t *addr_space, uint8_t addr)
return
-
1
;
}
/*! \defgroup I2C_int_handlers Command space integrating interrupt handlers
* @{
*/
/* we get here every time we get a byte from the master */
/*
!
we get here every time we get a byte from the master */
static
void
__xMR
I2C_slave_rx_complete_int
(
const
struct
i2c_s_async_descriptor
*
const
descr
)
{
if
(
last_byte_read_got_nack
)
{
...
...
@@ -197,8 +200,8 @@ static void __xMR I2C_slave_rx_complete_int(const struct i2c_s_async_descriptor
}
}
/* we get here when a master read transaction expects another byte (we
* haven't terminated it using CMD=2 */
/*
!
we get here when a master read transaction expects another byte (we
*
haven't terminated it using CMD=2 */
static
void
__xMR
I2C_slave_tx_pending_int
(
const
struct
i2c_s_async_descriptor
*
const
descr
)
{
if
(
last_byte_read_got_nack
)
{
...
...
@@ -265,20 +268,23 @@ static void __xMR I2C_slave_tx_pending_int(const struct i2c_s_async_descriptor *
}
/* we get here when a byte has been sent to the master */
/*
!
we get here when a byte has been sent to the master */
static
void
__xMR
I2C_slave_tx_complete_int
(
const
struct
i2c_s_async_descriptor
*
const
descr
)
{
last_byte_read_got_nack
=
hri_sercomi2cs_get_STATUS_RXNACK_bit
(
descr
->
device
.
hw
);
}
/* we get here when something bad has happened */
/*
!
we get here when something bad has happened */
static
void
__xMR
I2C_slave_error_int
(
const
struct
i2c_s_async_descriptor
*
const
descr
)
{
set_cmd
(
descr
,
2
);
}
/*! @} */
/*! this configures the I2C interrupt handlers with the PMBus and
extended command structures */
void
setup_I2C_slave
(
cmd_space_t
*
impl_cmds
,
cmd_space_t
*
impl_ext_cmds
)
{
cmds
=
impl_cmds
;
...
...
doc/Makefile
View file @
fde87b75
...
...
@@ -12,7 +12,7 @@ BUILDDIR = build
help
:
@
$(SPHINXBUILD)
-M
help
"
$(SOURCEDIR)
"
"
$(BUILDDIR)
"
$(SPHINXOPTS)
$(O)
.PHONY
:
help Makefile
.PHONY
:
help
doxygen
Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
...
...
@@ -32,6 +32,7 @@ doxygen:
ifeq
($(TARGET),clean)
@rm
-rf
build/doxygen-xml-common
build/doxygen-xml-main
build/doxygen-xml-testmaster
else
mkdir
-p
build
doxygen
doxygen-config-common
doxygen
doxygen-config-main
doxygen
doxygen-config-testmaster
...
...
doc/source/conf.py
View file @
fde87b75
...
...
@@ -87,4 +87,4 @@ import subprocess, os
read_the_docs_build
=
os
.
environ
.
get
(
'READTHEDOCS'
,
None
)
==
'True'
if
read_the_docs_build
:
subprocess
.
call
(
'make doxygen'
,
shell
=
True
)
subprocess
.
call
(
'
cd .. ;
make doxygen'
,
shell
=
True
)
doc/source/firmware.rst
View file @
fde87b75
...
...
@@ -4,24 +4,138 @@ Firmware
The project's fitmware is split in three parts: the bootloader, the
main firmware and the test firmware.
PMBus command infrastructure
----------------------------
A common command handling infrastructure has been put in place, such
that both the main firmware and the bootloader can easily implement
different subsets of PMBus and extended commands. The basic construct
of this implementation is the :code:`cmd_t` structure:
.. doxygenstruct:: cmd_t
:project: common
:members:
An array of these structs makes up a command space:
.. doxygenstruct:: cmd_space_t
:project: common
:members:
From the user's point of view, these structures are defined and used
just once, in the function
.. doxygenfunction:: setup_I2C_slave
:project: common
:outline:
This function will configure the inturrupt handlers, below, with the
command spaces defined in the specific user implementation (main
firmware or bootloader). From that point on, the only interaction will
be through the user-defined callbacks.
.. doxygengroup:: I2C_int_handlers
:project: common
:outline:
:content-only:
Bootloader
----------
The bootloader checks a certain word in the flash storage and,
depending on the value, either hands control to the main FW, or enters
remote programming mode.
The bootloader, after bringing up the device, will check for the
special word :code:`0xBEC0ABCD` in the flash storage (see struct
below) and, depending on the value, will either hand control to the
main FW, or enter remote programming mode.
.. doxygenstruct:: user_flash_t
:project: common
:members:
Main firmware
-------------
PMBus and extended commands
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The PMBus and extended command spaces are:
.. doxygenvariable:: cmds
.. doxygenvariable:: ext_cmds
Fan control PID
~~~~~~~~~~~~~~~
When the fans connected provide a tachometer output, fan speed control
can be enabled. This is implemented using PID controllers, with each
fan having its own instance. The main data structure of the PID
implementation is
.. doxygenstruct:: pid_cntrl_t
:members:
This is used by the main software to set the PID setpoint, and by the
PID controller to hold integration data. The main function that has to
be called every timestep is described below:
.. doxygenfunction:: pid_compute
Test firmware
-------------
To help with development, a test firmware has been written for a
`Feather M0 Basic <https://www.adafruit.com/product/2772>`_ minimal
development board.
Mitigation measures
-------------------
The MoniMod will be used in radiation environments. Although its
function is not critical and it can be remotely reset upon loss of
communication, some measures have been taken to minimize interruptions
and data corruption, improving QoS.
TMR using COAST
~~~~~~~~~~~~~~~
The `COAST <https://github.com/byuccl/coast>`_ LLVM passes are used to
automatically implement TMR to important variables.
NOPs and trampolines
~~~~~~~~~~~~~~~~~~~~
The Program Counter is also sensitive to SEUs; in fact, execution can
sometimes jump to an invalid address. To help mitigate failures owed
to this mechanism, any region of unused memory space has been filled
with :code:`NOP` instructions, and a small trampoline function as an
epilogue that will reset the stack pointer and jump to the device
initialization code. Furthermore, the instruction that comprises the
main loop has been placed at a "strategic" location, aligned by
:code:`0x8000`: that way, a bit-flip in any of the lower bits will
send execution to the upper memory region, filled with the NOPs and
concluding at the trampoline.
Watchdog
~~~~~~~~
Short description of the watchdog peripheral and the use we make of
it.
Toolchains
----------
Can be built with GCC and Clang / LLVM compilers; TMR only works with
Clang.
main_fw/include/pid.h
View file @
fde87b75
...
...
@@ -7,17 +7,24 @@
// #define DEBUG_PID
typedef
struct
{
//! controller setpoint
float
setpoint
;
//! the input of the last timestep
float
last_input
;
//! storage for integration
float
output_sum
;
#ifdef DEBUG_PID
float
p_factor
;
float
i_factor
;
float
d_factor
;
#endif
//! timestep counter
uint16_t
id_cnt
;
}
pid_cntrl_t
;
/*! use this function with a PID structure and an input to calculate
* the output for each timestep.
*/
float
pid_compute
(
pid_cntrl_t
*
pid_inst
,
float
input
);
#endif
main_fw/src/main.c
View file @
fde87b75
...
...
@@ -14,7 +14,9 @@ __DEFAULT_NO_xMR
#define PWM_CC 1.041
/* #define PWM_CC 1.0 */
//! PMBus commmands structure
extern
cmd_space_t
cmds
;
//! Our custom commmands structure
extern
cmd_space_t
ext_cmds
;
uint16_t
temps_lin
[
3
];
...
...
main_fw/src/pid.c
View file @
fde87b75
...
...
@@ -19,6 +19,11 @@ const float pid_outMax = 500;
const
float
pid_ifMax
=
50
;
/*! Compute the PID output for the next timestep
* \param pid_inst struct that holds the PID controller's configuration
* \param input the current input to the PID controller
* \return the PID controller output
*/
float
__xMR
pid_compute
(
pid_cntrl_t
*
pid_inst
,
float
input
)
{
/*Compute all the working error variables*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment