mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-29 14:52:12 +01:00
OP-932 Adds a semaphore to PPM input to signal when a new frame has been received. This can be used to process a new frame with as low a latency as possible.
This commit is contained in:
parent
ac75af55c1
commit
7c10623615
@ -113,6 +113,38 @@ int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel)
|
||||
return rcvr_dev->driver->read(rcvr_dev->lower_id, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a semaphore that signals when a new sample is available.
|
||||
* @param[in] rcvr_id driver to read from
|
||||
* @param[in] channel channel to read
|
||||
* @returns The semaphore, or NULL if not supported.
|
||||
*/
|
||||
xSemaphoreHandle PIOS_RCVR_GetSemaphore(uint32_t rcvr_id, uint8_t channel)
|
||||
{
|
||||
// Publicly facing API uses channel 1 for first channel
|
||||
if (channel == 0) {
|
||||
return NULL;
|
||||
} else {
|
||||
channel--;
|
||||
}
|
||||
|
||||
if (rcvr_id == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pios_rcvr_dev *rcvr_dev = (struct pios_rcvr_dev *)rcvr_id;
|
||||
|
||||
if (!PIOS_RCVR_validate(rcvr_dev)) {
|
||||
/* Undefined RCVR port for this board (see pios_board.c) */
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
|
||||
if (rcvr_dev->driver->get_semaphore) {
|
||||
return rcvr_dev->driver->get_semaphore(rcvr_dev->lower_id, channel);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* PIOS_INCLUDE_RCVR */
|
||||
|
||||
/**
|
||||
|
@ -31,9 +31,6 @@
|
||||
#ifndef PIOS_PPM_PRIV_H
|
||||
#define PIOS_PPM_PRIV_H
|
||||
|
||||
#include <pios.h>
|
||||
#include <pios_stm32.h>
|
||||
|
||||
struct pios_ppm_cfg {
|
||||
TIM_ICInitTypeDef tim_ic_init;
|
||||
const struct pios_tim_channel *channels;
|
||||
|
@ -34,10 +34,12 @@
|
||||
struct pios_rcvr_driver {
|
||||
void (*init)(uint32_t id);
|
||||
int32_t (*read)(uint32_t id, uint8_t channel);
|
||||
xSemaphoreHandle (*get_semaphore)(uint32_t id, uint8_t channel);
|
||||
};
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel);
|
||||
extern xSemaphoreHandle PIOS_RCVR_GetSemaphore(uint32_t rcvr_id, uint8_t channel);
|
||||
|
||||
/*! Define error codes for PIOS_RCVR_Get */
|
||||
enum PIOS_RCVR_errors {
|
||||
|
@ -32,14 +32,19 @@
|
||||
|
||||
#ifdef PIOS_INCLUDE_PPM
|
||||
|
||||
#include "pios_ppm_priv.h"
|
||||
#include <pios_stm32.h>
|
||||
|
||||
#include "pios_ppm_priv.h"
|
||||
|
||||
/* Provide a RCVR driver */
|
||||
static int32_t PIOS_PPM_Get(uint32_t rcvr_id, uint8_t channel);
|
||||
static xSemaphoreHandle PIOS_PPM_Get_Semaphore(uint32_t rcvr_id, uint8_t channel);
|
||||
|
||||
const struct pios_rcvr_driver pios_ppm_rcvr_driver = {
|
||||
.read = PIOS_PPM_Get,
|
||||
.read = PIOS_PPM_Get,
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
.get_semaphore = PIOS_PPM_Get_Semaphore
|
||||
#endif
|
||||
};
|
||||
|
||||
#define PIOS_PPM_IN_MIN_NUM_CHANNELS 4
|
||||
@ -76,6 +81,10 @@ struct pios_ppm_dev {
|
||||
uint8_t supv_timer;
|
||||
bool Tracking;
|
||||
bool Fresh;
|
||||
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
xSemaphoreHandle new_sample_semaphores[PIOS_PPM_IN_MIN_NUM_CHANNELS];
|
||||
#endif /* PIOS_INCLUDE_FREERTOS */
|
||||
};
|
||||
|
||||
static bool PIOS_PPM_validate(struct pios_ppm_dev *ppm_dev)
|
||||
@ -93,6 +102,11 @@ static struct pios_ppm_dev *PIOS_PPM_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize the semaphores to 0.
|
||||
for (uint8_t i = 0; i < PIOS_PPM_IN_MIN_NUM_CHANNELS; ++i) {
|
||||
ppm_dev->new_sample_semaphores[i] = 0;
|
||||
}
|
||||
|
||||
ppm_dev->magic = PIOS_PPM_DEV_MAGIC;
|
||||
return ppm_dev;
|
||||
}
|
||||
@ -199,6 +213,28 @@ out_fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static xSemaphoreHandle PIOS_PPM_Get_Semaphore(uint32_t rcvr_id, uint8_t channel)
|
||||
{
|
||||
struct pios_ppm_dev *ppm_dev = (struct pios_ppm_dev *)rcvr_id;
|
||||
|
||||
if (!PIOS_PPM_validate(ppm_dev)) {
|
||||
/* Invalid device specified */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (channel >= PIOS_PPM_IN_MAX_NUM_CHANNELS) {
|
||||
/* Channel out of range */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ppm_dev->new_sample_semaphores[channel] == 0) {
|
||||
vSemaphoreCreateBinary(ppm_dev->new_sample_semaphores[channel]);
|
||||
}
|
||||
return ppm_dev->new_sample_semaphores[channel];
|
||||
}
|
||||
#endif /* if defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
/**
|
||||
* Get the value of an input channel
|
||||
* \param[in] channel Number of the channel desired (zero based)
|
||||
@ -296,6 +332,15 @@ static void PIOS_PPM_tim_edge_cb(__attribute__((unused)) uint32_t tim_id,
|
||||
i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) {
|
||||
ppm_dev->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
|
||||
}
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
/* Signal that a new sample is ready on this channel. */
|
||||
if (ppm_dev->new_sample_semaphores[chan_idx] != 0) {
|
||||
signed portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
|
||||
if (xSemaphoreGiveFromISR(ppm_dev->new_sample_semaphores[chan_idx], &pxHigherPriorityTaskWoken) == pdTRUE) {
|
||||
portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for this? */
|
||||
}
|
||||
}
|
||||
#endif /* USE_FREERTOS */
|
||||
}
|
||||
|
||||
ppm_dev->Fresh = TRUE;
|
||||
|
@ -36,9 +36,13 @@
|
||||
|
||||
/* Provide a RCVR driver */
|
||||
static int32_t PIOS_PPM_Get(uint32_t rcvr_id, uint8_t channel);
|
||||
static xSemaphoreHandle PIOS_PPM_Get_Semaphore(uint32_t rcvr_id, uint8_t channel);
|
||||
|
||||
const struct pios_rcvr_driver pios_ppm_rcvr_driver = {
|
||||
.read = PIOS_PPM_Get,
|
||||
.read = PIOS_PPM_Get,
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
.get_semaphore = PIOS_PPM_Get_Semaphore
|
||||
#endif
|
||||
};
|
||||
|
||||
#define PIOS_PPM_IN_MIN_NUM_CHANNELS 4
|
||||
@ -72,6 +76,10 @@ struct pios_ppm_dev {
|
||||
uint8_t supv_timer;
|
||||
bool Tracking;
|
||||
bool Fresh;
|
||||
|
||||
#ifdef PIOS_INCLUDE_FREERTOS
|
||||
xSemaphoreHandle new_sample_semaphores[PIOS_PPM_IN_MIN_NUM_CHANNELS];
|
||||
#endif /* PIOS_INCLUDE_FREERTOS */
|
||||
};
|
||||
|
||||
static bool PIOS_PPM_validate(struct pios_ppm_dev *ppm_dev)
|
||||
@ -89,6 +97,11 @@ static struct pios_ppm_dev *PIOS_PPM_alloc(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize the semaphores to 0.
|
||||
for (uint8_t i = 0; i < PIOS_PPM_IN_MIN_NUM_CHANNELS; ++i) {
|
||||
ppm_dev->new_sample_semaphores[i] = 0;
|
||||
}
|
||||
|
||||
ppm_dev->magic = PIOS_PPM_DEV_MAGIC;
|
||||
return ppm_dev;
|
||||
}
|
||||
@ -194,6 +207,28 @@ out_fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static xSemaphoreHandle PIOS_PPM_Get_Semaphore(uint32_t rcvr_id, uint8_t channel)
|
||||
{
|
||||
struct pios_ppm_dev *ppm_dev = (struct pios_ppm_dev *)rcvr_id;
|
||||
|
||||
if (!PIOS_PPM_validate(ppm_dev)) {
|
||||
/* Invalid device specified */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (channel >= PIOS_PPM_IN_MAX_NUM_CHANNELS) {
|
||||
/* Channel out of range */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ppm_dev->new_sample_semaphores[channel] == 0) {
|
||||
vSemaphoreCreateBinary(ppm_dev->new_sample_semaphores[channel]);
|
||||
}
|
||||
return ppm_dev->new_sample_semaphores[channel];
|
||||
}
|
||||
#endif /* if defined(PIOS_INCLUDE_FREERTOS) */
|
||||
|
||||
/**
|
||||
* Get the value of an input channel
|
||||
* \param[in] channel Number of the channel desired (zero based)
|
||||
@ -286,6 +321,15 @@ static void PIOS_PPM_tim_edge_cb(__attribute__((unused)) uint32_t tim_id, uint32
|
||||
i < PIOS_PPM_IN_MAX_NUM_CHANNELS; i++) {
|
||||
ppm_dev->CaptureValue[i] = PIOS_RCVR_TIMEOUT;
|
||||
}
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
/* Signal that a new sample is ready on this channel. */
|
||||
if (ppm_dev->new_sample_semaphores[chan_idx] != 0) {
|
||||
signed portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE;
|
||||
if (xSemaphoreGiveFromISR(ppm_dev->new_sample_semaphores[chan_idx], &pxHigherPriorityTaskWoken) == pdTRUE) {
|
||||
portEND_SWITCHING_ISR(pxHigherPriorityTaskWoken); /* FIXME: is this the right place for his? */
|
||||
}
|
||||
}
|
||||
#endif /* USE_FREERTOS */
|
||||
}
|
||||
|
||||
ppm_dev->Fresh = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user