restore UAVCAN bootloader support

- essentially reverting #7878 minus the obsolete board support
This commit is contained in:
Daniel Agar
2020-04-19 16:10:09 -04:00
committed by GitHub
parent 7c533e5a53
commit a3ad710623
30 changed files with 6658 additions and 3 deletions
@@ -0,0 +1,434 @@
/****************************************************************************
*
* Copyright (c) 2015 PX4 Development Team. All rights reserved.
* Author: Ben Dyer <ben_dyer@mac.com>
* Pavel Kirienko <pavel.kirienko@zubax.com>
* David Sidrane <david_s5@nscdg.com>
*
* 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
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS 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.
*
****************************************************************************/
#include <nuttx/config.h>
// Turn off Probes in this module
#undef CONFIG_BOARD_USE_PROBES
#include <boot_config.h>
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <nuttx/arch.h>
#include <arch/irq.h>
#include <arch/board/board.h>
#include "px4_macros.h"
#include "timer.h"
#include "nvic.h"
typedef enum {
OneShot = modeOneShot,
Repeating = modeRepeating,
Timeout = modeTimeout,
modeMsk = 0x3,
running = modeStarted,
inuse = 0x80,
} bl_timer_ctl_t;
typedef struct {
bl_timer_cb_t usr;
time_ms_t count;
time_ms_t reload;
bl_timer_ctl_t ctl;
} bl_timer_t;
static time_ms_t sys_tic;
static bl_timer_t timers[OPT_BL_NUMBER_TIMERS];
/* Use to initialize */
const bl_timer_cb_t null_cb = { 0, 0 };
/* We use the linker --wrap ability to wrap the NuttX stm32 call out to
* the sceduler's sched_process_timer and service it here. Thus replacing
* the NuttX scheduler with are timer driven scheduling.
*/
void __wrap_sched_process_timer(void);
/****************************************************************************
* Name: timer_tic
*
* Description:
* Returns the system tic counter that counts in units of
* (CONFIG_USEC_PER_TICK/1000). By default 10 Ms.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
time_ms_t timer_tic(void)
{
return sys_tic;
}
/****************************************************************************
* Name: sched_process_timer
*
* Description:
* Called by Nuttx on the ISR of the SysTic. This function run the list of
* timers. It deducts that amount of the time of a system tick from the
* any timers that are in use and running.
*
* Depending on the mode of the timer, the appropriate actions is taken on
* expiration.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
__EXPORT void __wrap_sched_process_timer(void)
{
//PROBE(1, true);
//PROBE(1, false);
/* Increment the per-tick system counter */
sys_tic++;
/* todo:May need a X tick here is threads run long */
time_ms_t ms_elapsed = (CONFIG_USEC_PER_TICK / 1000);
/* Walk the time list from High to low and */
bl_timer_id t;
for (t = arraySize(timers) - 1; (int8_t) t >= 0; t--) {
/* Timer in use and running */
if ((timers[t].ctl & (inuse | running)) == (inuse | running)) {
/* Is it NOT already expired nor about to expire ?*/
if (timers[t].count != 0) {
/* Is it off in future */
if (timers[t].count > ms_elapsed) {
/* Just remove the amount attributed to the tick */
timers[t].count -= ms_elapsed;
continue;
}
/* it has expired now or less than a tick ago */
/* Mark it expired */
timers[t].count = 0;
/* Now perform action based on mode */
switch (timers[t].ctl & ~(inuse | running)) {
case OneShot: {
bl_timer_cb_t user = timers[t].usr;
memset(&timers[t], 0, sizeof(timers[t]));
if (user.cb) {
user.cb(t, user.context);
}
}
break;
case Repeating:
timers[t].count = timers[t].reload;
/* FALLTHROUGH */
/* to callback */
case Timeout:
if (timers[t].usr.cb) {
timers[t].usr.cb(t, timers[t].usr.context);
}
break;
default:
break;
}
}
}
}
}
/****************************************************************************
* Name: timer_allocate
*
* Description:
* Is used to allocate a timer. Allocation does not involve memory
* allocation as the data for the timer are compile time generated.
* See OPT_BL_NUMBER_TIMERS
*
* There is an inherent priority to the timers in that the first timer
* allocated is the first timer run per tick.
*
* There are 3 modes of operation for the timers. All modes support an
* optional call back on expiration.
*
* modeOneShot - Specifies a one-shot timer. After notification timer
* is resource is freed.
* modeRepeating - Specifies a repeating timer that will reload and
* call an optional.
* modeTimeout - Specifies a persistent start / stop timer.
*
* modeStarted - Or'ed in to start the timer when allocated
*
*
* Input Parameters:
* mode - One of bl_timer_modes_t with the Optional modeStarted
* msfromnow - The reload and initial value for the timer in Ms.
* fc - A pointer or NULL (0). If it is non null it can be any
* of the following:
*
* a) A bl_timer_cb_t populated on the users stack or
* in the data segment. The values are copied into the
* internal data structure of the timer and therefore do
* not have to persist after the call to timer_allocate
*
* b) The address of null_cb. This is identical to passing
* null for the value of fc.
*
* Returned Value:
* On success a value from 0 - OPT_BL_NUMBER_TIMERS-1 that is
* the bl_timer_id for subsequent timer operations
* -1 on failure. This indicates there are no free timers.
*
****************************************************************************/
bl_timer_id timer_allocate(bl_timer_modes_t mode, time_ms_t msfromnow, bl_timer_cb_t *fc)
{
bl_timer_id t;
irqstate_t s = enter_critical_section();
for (t = arraySize(timers) - 1; (int8_t)t >= 0; t--) {
if ((timers[t].ctl & inuse) == 0) {
timers[t].reload = msfromnow;
timers[t].count = msfromnow;
timers[t].usr = fc ? *fc : null_cb;
timers[t].ctl = (mode & (modeMsk | running)) | (inuse);
break;
}
}
leave_critical_section(s);
return t;
}
/****************************************************************************
* Name: timer_free
*
* Description:
* Is used to free a timer. Freeing a timer does not involve memory
* deallocation as the data for the timer are compile time generated.
* See OPT_BL_NUMBER_TIMERS
*
* Input Parameters:
* id - Returned from timer_allocate;
*
* Returned Value:
* None.
*
****************************************************************************/
void timer_free(bl_timer_id id)
{
DEBUGASSERT(id >= 0 && id < arraySize(timers));
irqstate_t s = enter_critical_section();
memset(&timers[id], 0, sizeof(timers[id]));
leave_critical_section(s);
}
/****************************************************************************
* Name: timer_start
*
* Description:
* Is used to Start a timer. The reload value is copied to the counter.
* And the running bit it set. There is no problem in Starting a running
* timer. But it will restart the timeout.
*
* Input Parameters:
* id - Returned from timer_allocate;
*
* Returned Value:
* None.
*
****************************************************************************/
void timer_start(bl_timer_id id)
{
DEBUGASSERT(id >= 0 && id < arraySize(timers) && (timers[id].ctl & inuse));
irqstate_t s = enter_critical_section();
timers[id].count = timers[id].reload;
timers[id].ctl |= running;
leave_critical_section(s);
}
/****************************************************************************
* Name: timer_stop
*
* Description:
* Is used to stop a timer. It is Ok to stop a stopped timer.
*
* Input Parameters:
* id - Returned from timer_allocate;
*
* Returned Value:
* None.
*
****************************************************************************/
void timer_stop(bl_timer_id id)
{
DEBUGASSERT(id >= 0 && id < arraySize(timers) && (timers[id].ctl & inuse));
irqstate_t s = enter_critical_section();
timers[id].ctl &= ~running;
leave_critical_section(s);
}
/****************************************************************************
* Name: timer_expired
*
* Description:
* Test if a timer that was configured as a modeTimeout timer is expired.
* To be expired the time has to be running and have a count of 0.
*
* Input Parameters:
* id - Returned from timer_allocate;
*
* Returned Value:
* Non Zero if the timer is expired otherwise zero.
*
****************************************************************************/
int timer_expired(bl_timer_id id)
{
DEBUGASSERT(id >= 0 && id < arraySize(timers) && (timers[id].ctl & inuse));
irqstate_t s = enter_critical_section();
int rv = ((timers[id].ctl & running) && timers[id].count == 0);
leave_critical_section(s);
return rv;
}
/****************************************************************************
* Name: timer_restart
*
* Description:
* Is used to re start a timer with a new reload count. The reload value
* is copied to the counter and the running bit it set. There is no
* problem in restarting a running timer.
*
* Input Parameters:
* id - Returned from timer_allocate;
* ms - Is a time_ms_t and the new reload value to use.
*
* Returned Value:
* None.
*
****************************************************************************/
void timer_restart(bl_timer_id id, time_ms_t ms)
{
DEBUGASSERT(id >= 0 && id < arraySize(timers) && (timers[id].ctl & inuse));
irqstate_t s = enter_critical_section();
timers[id].count = timers[id].reload = ms;
timers[id].ctl |= running;
leave_critical_section(s);
}
/****************************************************************************
* Name: timer_ref
*
* Description:
* Returns an time_ref_t that is a reference (ponter) to the internal counter
* of the timer selected by id. It should only be used with calls to
* timer_ref_expired.
*
* Input Parameters:
* id - Returned from timer_allocate;
*
* Returned Value:
* An internal reference that should be treated as opaque by the caller and
* should only be used with calls to timer_ref_expired.
* There is no reference counting on the reference and therefore does not
* require any operation to free it.
*
*************************************************************************/
time_ref_t timer_ref(bl_timer_id id)
{
DEBUGASSERT(id >= 0 && id < arraySize(timers) && (timers[id].ctl & inuse));
return (time_ref_t) &timers[id].count;
}
/****************************************************************************
* Name: timer_init
*
* Description:
* Called early in os_start to initialize the data associated with
* the timers
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
__EXPORT void timer_init(void)
{
/* For system timing probing see bord.h and
* CONFIG_BOARD_USE_PROBES
*/
//PROBE_INIT(7);
//PROBE(1, true);
//PROBE(2, true);
//PROBE(3, true);
//PROBE(1, false);
//PROBE(2, false);
//PROBE(3, false);
/* This is the lowlevel IO if needed to instrument timing
* with the smallest impact
* *((uint32_t *)0x40011010) = 0x100; // PROBE(3,true);
* *((uint32_t *)0x40011014) = 0x100; // PROBE(3,false);
*/
/* Initialize timer data */
sys_tic = 0;
memset(timers, 0, sizeof(timers));
}