exti working but something is fucked up in the job queue or tinyframe

sipo
Ondřej Hruška 7 years ago
parent 255f96c754
commit 45b4fb45e9
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      TinyFrame/TF_Integration.c
  2. 88
      platform/hw_utils.c
  3. 13
      platform/hw_utils.h
  4. 108
      platform/irq_dispatcher.c
  5. 6
      platform/irq_dispatcher.h
  6. 2
      platform/plat_compat.h
  7. 3
      tasks/sched_queue.h
  8. 3
      tasks/task_msg.c
  9. 142
      units/digital_in/unit_din.c
  10. 3
      units/usart/unit_usart.c

@ -20,7 +20,7 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
#define CHUNK 64 // same as TF_SENDBUF_LEN, so we should always have only one run of the loop #define CHUNK 64 // same as TF_SENDBUF_LEN, so we should always have only one run of the loop
int32_t total = (int32_t) len; int32_t total = (int32_t) len;
while (total > 0) { while (total > 0) {
assert_param(osOK == osSemaphoreWait(semVcomTxReadyHandle, 5000)); assert_param(osOK == osSemaphoreWait(semVcomTxReadyHandle, 1000));
uint16_t chunksize = (uint16_t) MIN(total, CHUNK); uint16_t chunksize = (uint16_t) MIN(total, CHUNK);
assert_param(USBD_OK == CDC_Transmit_FS((uint8_t *) buff, chunksize)); assert_param(USBD_OK == CDC_Transmit_FS((uint8_t *) buff, chunksize));

@ -2,14 +2,67 @@
// Created by MightyPork on 2017/11/26. // Created by MightyPork on 2017/11/26.
// //
#include "platform.h"
#include <utils/avrlibc.h> #include <utils/avrlibc.h>
#include "hw_utils.h" #include "hw_utils.h"
#include "macro.h" #include "macro.h"
#define PINS_COUNT 16 const uint32_t LL_SYSCFG_EXTI_PORTS[PORTS_COUNT] = {
LL_SYSCFG_EXTI_PORTA,
LL_SYSCFG_EXTI_PORTB,
LL_SYSCFG_EXTI_PORTC,
LL_SYSCFG_EXTI_PORTD,
LL_SYSCFG_EXTI_PORTE,
#if PORTS_COUNT>5
LL_SYSCFG_EXTI_PORTF,
#endif
#if PORTS_COUNT>6
LL_SYSCFG_EXTI_PORTG,
#endif
};
const uint32_t LL_SYSCFG_EXTI_LINES[16] = {
LL_SYSCFG_EXTI_LINE0,
LL_SYSCFG_EXTI_LINE1,
LL_SYSCFG_EXTI_LINE2,
LL_SYSCFG_EXTI_LINE3,
LL_SYSCFG_EXTI_LINE4,
LL_SYSCFG_EXTI_LINE5,
LL_SYSCFG_EXTI_LINE6,
LL_SYSCFG_EXTI_LINE7,
LL_SYSCFG_EXTI_LINE8,
LL_SYSCFG_EXTI_LINE9,
LL_SYSCFG_EXTI_LINE10,
LL_SYSCFG_EXTI_LINE11,
LL_SYSCFG_EXTI_LINE12,
LL_SYSCFG_EXTI_LINE13,
LL_SYSCFG_EXTI_LINE14,
LL_SYSCFG_EXTI_LINE15,
};
COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(LL_SYSCFG_EXTI_LINES));
const uint32_t LL_EXTI_LINES[16] = {
LL_EXTI_LINE_0,
LL_EXTI_LINE_1,
LL_EXTI_LINE_2,
LL_EXTI_LINE_3,
LL_EXTI_LINE_4,
LL_EXTI_LINE_5,
LL_EXTI_LINE_6,
LL_EXTI_LINE_7,
LL_EXTI_LINE_8,
LL_EXTI_LINE_9,
LL_EXTI_LINE_10,
LL_EXTI_LINE_11,
LL_EXTI_LINE_12,
LL_EXTI_LINE_13,
LL_EXTI_LINE_14,
LL_EXTI_LINE_15,
};
COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(LL_EXTI_LINES));
/** Pin number to LL bitfield mapping */ /** Pin number to LL bitfield mapping */
static const uint32_t ll_pins[PINS_COUNT] = { const uint32_t LL_GPIO_PINS[16] = {
LL_GPIO_PIN_0, LL_GPIO_PIN_0,
LL_GPIO_PIN_1, LL_GPIO_PIN_1,
LL_GPIO_PIN_2, LL_GPIO_PIN_2,
@ -27,10 +80,10 @@ static const uint32_t ll_pins[PINS_COUNT] = {
LL_GPIO_PIN_14, LL_GPIO_PIN_14,
LL_GPIO_PIN_15, LL_GPIO_PIN_15,
}; };
COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(ll_pins)); COMPILER_ASSERT(16 == ELEMENTS_IN_ARRAY(LL_GPIO_PINS));
/** Port number (A=0) to config struct pointer mapping */ /** Port number (A=0) to config struct pointer mapping */
static GPIO_TypeDef * const port_periphs[] = { GPIO_TypeDef * const GPIO_PERIPHS[PORTS_COUNT] = {
GPIOA, GPIOA,
GPIOB, GPIOB,
GPIOC, GPIOC,
@ -43,20 +96,20 @@ static GPIO_TypeDef * const port_periphs[] = {
GPIOG, GPIOG,
#endif #endif
}; };
COMPILER_ASSERT(PORTS_COUNT == ELEMENTS_IN_ARRAY(port_periphs)); COMPILER_ASSERT(PORTS_COUNT == ELEMENTS_IN_ARRAY(GPIO_PERIPHS));
/** Convert pin number to LL bitfield */ /** Convert pin number to LL bitfield */
uint32_t hw_pin2ll(uint8_t pin_number, bool *suc) uint32_t hw_pin2ll(uint8_t pin_number, bool *suc)
{ {
assert_param(suc != NULL); assert_param(suc != NULL);
if(pin_number >= PINS_COUNT) { if(pin_number > 15) {
dbg("Bad pin: %d", pin_number); dbg("Bad pin: %d", pin_number);
// TODO proper report // TODO proper report
*suc = false; *suc = false;
return 0; return 0;
} }
return ll_pins[pin_number]; return LL_GPIO_PINS[pin_number];
} }
/** Convert port name (A,B,C...) to peripheral struct pointer */ /** Convert port name (A,B,C...) to peripheral struct pointer */
@ -71,7 +124,7 @@ GPIO_TypeDef *hw_port2periph(char port_name, bool *suc)
} }
uint8_t num = (uint8_t) (port_name - 'A'); uint8_t num = (uint8_t) (port_name - 'A');
return port_periphs[num]; return GPIO_PERIPHS[num];
} }
/** Convert a pin to resource handle */ /** Convert a pin to resource handle */
@ -85,7 +138,7 @@ Resource hw_pin2resource(char port_name, uint8_t pin_number, bool *suc)
return R_NONE; return R_NONE;
} }
if(pin_number >= PINS_COUNT) { if(pin_number > 15) {
dbg("Bad pin: %d", pin_number); // TODO proper report dbg("Bad pin: %d", pin_number); // TODO proper report
*suc = false; *suc = false;
return R_NONE; return R_NONE;
@ -261,14 +314,27 @@ uint16_t pinmask_pack(uint16_t spread, uint16_t mask)
return result; return result;
} }
/** Convert spread port pin number to a packed index using a mask */
uint8_t pinmask_translate(uint16_t mask, uint8_t index)
{
int cnt = 0;
for (int i = 0; i<16; i++) {
if (mask & (1<<i)) {
if (i == index) return (uint8_t) cnt;
cnt++;
}
}
return 0;
}
/** Configure unit pins as analog (part of unit teardown) */ /** Configure unit pins as analog (part of unit teardown) */
void hw_deinit_unit_pins(Unit *unit) void hw_deinit_unit_pins(Unit *unit)
{ {
for (uint32_t rsc = R_PA0; rsc <= R_PF15; rsc++) { for (uint32_t rsc = R_PA0; rsc <= R_PF15; rsc++) {
if (RSC_IS_HELD(unit->resources, rsc)) { if (RSC_IS_HELD(unit->resources, rsc)) {
rsc_dbg("Freeing pin %s", rsc_get_name((Resource)rsc)); rsc_dbg("Freeing pin %s", rsc_get_name((Resource)rsc));
GPIO_TypeDef *port = port_periphs[(rsc-R_PA0) / 16]; GPIO_TypeDef *port = GPIO_PERIPHS[(rsc-R_PA0) / 16];
uint32_t ll_pin = ll_pins[(rsc-R_PA0)%16]; uint32_t ll_pin = LL_GPIO_PINS[(rsc-R_PA0)%16];
LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG); LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG);
} }
} }

@ -11,6 +11,12 @@
#include "platform.h" #include "platform.h"
#include "resources.h" #include "resources.h"
extern const uint32_t LL_SYSCFG_EXTI_PORTS[PORTS_COUNT];
extern const uint32_t LL_SYSCFG_EXTI_LINES[16];
extern GPIO_TypeDef * const GPIO_PERIPHS[PORTS_COUNT];
extern const uint32_t LL_GPIO_PINS[16];
extern const uint32_t LL_EXTI_LINES[16];
/** /**
* Convert pin number to LL driver bitfield for working with the pin. * Convert pin number to LL driver bitfield for working with the pin.
* *
@ -97,6 +103,13 @@ uint16_t pinmask_spread(uint16_t packed, uint16_t mask);
*/ */
uint16_t pinmask_pack(uint16_t spread, uint16_t mask); uint16_t pinmask_pack(uint16_t spread, uint16_t mask);
/**
* Convert spread port pin number to a packed index using a mask
*
* eg. with a mask 0b1010 and index 3, the result is 1 (bit 1 of the packed - 0bX0)
*/
uint8_t pinmask_translate(uint16_t mask, uint8_t index);
/** /**
* Set all GPIO resources held by unit to analog. * Set all GPIO resources held by unit to analog.
* This is a part of unit teardown. * This is a part of unit teardown.

@ -2,9 +2,29 @@
// Created by MightyPork on 2018/01/14. // Created by MightyPork on 2018/01/14.
// //
#include <utils/hexdump.h>
#include "platform.h" #include "platform.h"
#include "irq_dispatcher.h" #include "irq_dispatcher.h"
#include "hw_utils.h"
void * const EXTIS[16] = {
// dumym values for easier debug - those are used instead of periph addresses because EXTIs have no dedicated periph control blocks
(void *const) 0x9000,
(void *const) 0x9001,
(void *const) 0x9002,
(void *const) 0x9003,
(void *const) 0x9004,
(void *const) 0x9005,
(void *const) 0x9006,
(void *const) 0x9007,
(void *const) 0x9008,
(void *const) 0x9009,
(void *const) 0x900A,
(void *const) 0x900B,
(void *const) 0x900C,
(void *const) 0x900D,
(void *const) 0x900E,
(void *const) 0x900F,
};
struct cbslot { struct cbslot {
IrqCallback callback; IrqCallback callback;
@ -12,6 +32,8 @@ struct cbslot {
}; };
static struct callbacks_ { static struct callbacks_ {
struct cbslot exti[16];
struct cbslot usart1; struct cbslot usart1;
struct cbslot usart2; struct cbslot usart2;
struct cbslot usart3; struct cbslot usart3;
@ -51,9 +73,9 @@ void irqd_init(void)
// NVIC_EnableIRQ(RTC_IRQn); /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */ // NVIC_EnableIRQ(RTC_IRQn); /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */
// NVIC_EnableIRQ(FLASH_IRQn); /*!< FLASH global Interrupt */ // NVIC_EnableIRQ(FLASH_IRQn); /*!< FLASH global Interrupt */
// NVIC_EnableIRQ(RCC_CRS_IRQn); /*!< RCC & CRS global Interrupt */ // NVIC_EnableIRQ(RCC_CRS_IRQn); /*!< RCC & CRS global Interrupt */
// NVIC_EnableIRQ(EXTI0_1_IRQn); /*!< EXTI Line 0 and 1 Interrupt */ NVIC_EnableIRQ(EXTI0_1_IRQn); /*!< EXTI Line 0 and 1 Interrupt */
// NVIC_EnableIRQ(EXTI2_3_IRQn); /*!< EXTI Line 2 and 3 Interrupt */ NVIC_EnableIRQ(EXTI2_3_IRQn); /*!< EXTI Line 2 and 3 Interrupt */
// NVIC_EnableIRQ(EXTI4_15_IRQn); /*!< EXTI Line 4 to 15 Interrupt */ NVIC_EnableIRQ(EXTI4_15_IRQn); /*!< EXTI Line 4 to 15 Interrupt */
// NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */ // NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */
NVIC_EnableIRQ(DMA1_Channel1_IRQn); /*!< DMA1 Channel 1 Interrupt */ NVIC_EnableIRQ(DMA1_Channel1_IRQn); /*!< DMA1 Channel 1 Interrupt */
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /*!< DMA1 Channel 2 and Channel 3 Interrupt */ NVIC_EnableIRQ(DMA1_Channel2_3_IRQn); /*!< DMA1 Channel 2 and Channel 3 Interrupt */
@ -107,6 +129,10 @@ static struct cbslot *get_slot_for_periph(void *periph)
else if (periph == USART5) slot = &callbacks.usart5; else if (periph == USART5) slot = &callbacks.usart5;
#endif #endif
else if (periph >= EXTIS[0] && periph <= EXTIS[15]) {
slot = &callbacks.exti[periph - EXTIS[0]];
}
// --- DMA1 --- // --- DMA1 ---
else if (periph == DMA1_Channel1) slot = &callbacks.dma1_1; else if (periph == DMA1_Channel1) slot = &callbacks.dma1_1;
else if (periph == DMA1_Channel2) slot = &callbacks.dma1_2; else if (periph == DMA1_Channel2) slot = &callbacks.dma1_2;
@ -154,12 +180,16 @@ void irqd_attach(void *periph, IrqCallback callback, void *arg)
slot->arg = arg; slot->arg = arg;
} }
void irqd_detach(void *periph, IrqCallback callback) void* irqd_detach(void *periph, IrqCallback callback)
{ {
void *oldArg = NULL;
struct cbslot *slot = get_slot_for_periph(periph); struct cbslot *slot = get_slot_for_periph(periph);
if (slot->callback == callback) { if (slot->callback == callback) {
oldArg = slot->arg;
slot->callback = NULL; slot->callback = NULL;
slot->arg = NULL; slot->arg = NULL;
return oldArg;
} else { } else {
trap("Detach IRQ %p() from %p but %p() bound instead", callback, periph, slot->callback); trap("Detach IRQ %p() from %p but %p() bound instead", callback, periph, slot->callback);
} }
@ -167,6 +197,8 @@ void irqd_detach(void *periph, IrqCallback callback)
#define CALL_IRQ_HANDLER(slot) do { if (slot.callback) slot.callback(slot.arg); } while (0) #define CALL_IRQ_HANDLER(slot) do { if (slot.callback) slot.callback(slot.arg); } while (0)
// ------------ USARTS ------------
void USART1_IRQHandler(void) void USART1_IRQHandler(void)
{ {
CALL_IRQ_HANDLER(callbacks.usart1); CALL_IRQ_HANDLER(callbacks.usart1);
@ -177,32 +209,6 @@ void USART2_IRQHandler(void)
CALL_IRQ_HANDLER(callbacks.usart2); CALL_IRQ_HANDLER(callbacks.usart2);
} }
#if 0
static bool usart_check_irq(USART_TypeDef *USARTx)
{
uint32_t isrflags = USARTx->ISR;
uint32_t cr1its = USARTx->CR1;
uint32_t cr2its = USARTx->CR2;
uint32_t cr3its = USARTx->CR3;
if ((cr1its & USART_CR1_RTOIE) && (isrflags & USART_ISR_RTOF)) return true;
if ((cr1its & USART_CR1_RXNEIE) && (isrflags & USART_ISR_RXNE)) return true;
if ((cr1its & USART_CR1_TCIE) && (isrflags & USART_ISR_TC)) return true;
if ((cr1its & USART_CR1_TXEIE) && (isrflags & USART_ISR_TXE)) return true;
if ((cr3its & USART_CR3_EIE) && (isrflags & (USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE))) return true;
if ((cr1its & USART_CR1_IDLEIE) && (isrflags & USART_ISR_IDLE)) return true;
if ((cr1its & USART_CR1_PEIE) && (isrflags & USART_ISR_PE)) return true;
if ((cr1its & USART_CR1_CMIE) && (isrflags & USART_ISR_CMF)) return true;
if ((cr1its & USART_CR1_EOBIE) && (isrflags & USART_ISR_EOBF)) return true;
if ((cr2its & USART_CR2_LBDIE) && (isrflags & USART_ISR_LBDF)) return true;
if ((cr3its & USART_CR3_CTSIE) && (isrflags & USART_ISR_CTS)) return true;
if ((cr3its & USART_CR3_WUFIE) && (isrflags & USART_ISR_WUF)) return true;
return false;
}
#endif
void USART3_4_IRQHandler(void) void USART3_4_IRQHandler(void)
{ {
// we won't check the flags here, both can be pending and it's better to let the handler deal with it // we won't check the flags here, both can be pending and it's better to let the handler deal with it
@ -210,6 +216,8 @@ void USART3_4_IRQHandler(void)
CALL_IRQ_HANDLER(callbacks.usart4); CALL_IRQ_HANDLER(callbacks.usart4);
} }
// ------------ DMA --------------
void DMA1_Channel1_IRQHandler(void) void DMA1_Channel1_IRQHandler(void)
{ {
CALL_IRQ_HANDLER(callbacks.dma1_1); CALL_IRQ_HANDLER(callbacks.dma1_1);
@ -229,43 +237,57 @@ void DMA1_Channel4_5_6_7_IRQHandler(void)
if (LL_DMA_IsActiveFlag_GI7(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_7); if (LL_DMA_IsActiveFlag_GI7(DMA1)) CALL_IRQ_HANDLER(callbacks.dma1_7);
} }
#if 0 // ------------ EXTI ------------
void WWDG_IRQHandler(void)
static void fire_exti_cb(uint8_t start, uint8_t end)
{ {
// for (int i = start; i <= end; i++) {
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINES[i])) {
CALL_IRQ_HANDLER(callbacks.exti[i]);
}
}
} }
void PVD_VDDIO2_IRQHandler(void) void EXTI0_1_IRQHandler(void)
{ {
// fire_exti_cb(0, 1);
} }
void RTC_IRQHandler(void) void EXTI2_3_IRQHandler(void)
{ {
// fire_exti_cb(2, 3);
} }
void FLASH_IRQHandler(void) void EXTI4_15_IRQHandler(void)
{
fire_exti_cb(4, 15);
}
// other ISRs...
#if 0
void WWDG_IRQHandler(void)
{ {
// //
} }
void RCC_CRS_IRQHandler(void) void PVD_VDDIO2_IRQHandler(void)
{ {
// //
} }
void EXTI0_1_IRQHandler(void) void RTC_IRQHandler(void)
{ {
// //
} }
void EXTI2_3_IRQHandler(void) void FLASH_IRQHandler(void)
{ {
// //
} }
void EXTI4_15_IRQHandler(void) void RCC_CRS_IRQHandler(void)
{ {
// //
} }

@ -7,6 +7,9 @@
#ifndef GEX_F072_IRQ_DISPATCHER_H #ifndef GEX_F072_IRQ_DISPATCHER_H
#define GEX_F072_IRQ_DISPATCHER_H #define GEX_F072_IRQ_DISPATCHER_H
// Dummy peripherals for use with the
extern void * const EXTIS[16];
/** /**
* Initialize the interrupt dispatcher * Initialize the interrupt dispatcher
*/ */
@ -35,7 +38,8 @@ void irqd_attach(void *periph, IrqCallback callback, void *data);
* *
* @param periph - peripheral we're attaching to * @param periph - peripheral we're attaching to
* @param callback - callback to remove, if it doesn't match, do nothing * @param callback - callback to remove, if it doesn't match, do nothing
* @return the arg, if any
*/ */
void irqd_detach(void *periph, IrqCallback callback); void* irqd_detach(void *periph, IrqCallback callback);
#endif //GEX_F072_IRQ_DISPATCHER_H #endif //GEX_F072_IRQ_DISPATCHER_H

@ -24,7 +24,7 @@
#define FLASH_SAVE_BUF_LEN 128 // Malloc'd buffer for saving to flash #define FLASH_SAVE_BUF_LEN 128 // Malloc'd buffer for saving to flash
#define MSG_QUE_SLOT_SIZE 64 // FIXME this should be possible to lower, but there's some bug with bulk transfer / INI parser #define MSG_QUE_SLOT_SIZE 64 // FIXME this should be possible to lower, but there's some bug with bulk transfer / INI parser
#define RX_QUE_CAPACITY 8 // TinyFrame rx queue size (64 bytes each) #define RX_QUE_CAPACITY 16 // TinyFrame rx queue size (64 bytes each)
#define TF_MAX_PAYLOAD_RX 512 // TF max Rx payload #define TF_MAX_PAYLOAD_RX 512 // TF max Rx payload
#define TF_SENDBUF_LEN 64 // TF transmit buffer (can be less than a full frame) #define TF_SENDBUF_LEN 64 // TF transmit buffer (can be less than a full frame)

@ -30,10 +30,12 @@ struct sched_que_item {
union { union {
TF_ID frame_id; // typically used to pass frame id to the callback TF_ID frame_id; // typically used to pass frame id to the callback
void *data1; // arbitrary pointer or int void *data1; // arbitrary pointer or int
uint32_t d32_1; // passing a number
}; };
/** Data word 2 */ /** Data word 2 */
union { union {
uint32_t d32; // passing a number uint32_t d32; // passing a number
uint32_t d32_2; // passing a number
uint8_t *buf; // uchar buffer uint8_t *buf; // uchar buffer
const uint8_t *cbuf; // const uchar buffer const uint8_t *cbuf; // const uchar buffer
const char *str; // string const char *str; // string
@ -43,6 +45,7 @@ struct sched_que_item {
union { union {
uint32_t len; // typically length of the buffer uint32_t len; // typically length of the buffer
void *data3; // arbitrary pointer void *data3; // arbitrary pointer
uint32_t d32_3; // passing a number
}; };
}; };

@ -17,11 +17,12 @@ static void que_safe_post(struct rx_sched_combined_que_item *slot)
if (inIRQ()) { if (inIRQ()) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
assert_param(pdPASS == xQueueSendFromISR(queMsgJobHandle, slot, &xHigherPriorityTaskWoken)); assert_param(pdPASS == xQueueSendFromISR(queMsgJobHandle, slot, &xHigherPriorityTaskWoken));
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
#if USE_STACK_MONITOR #if USE_STACK_MONITOR
count = (uint32_t) uxQueueMessagesWaitingFromISR(queMsgJobHandle); count = (uint32_t) uxQueueMessagesWaitingFromISR(queMsgJobHandle);
#endif #endif
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
} else { } else {
assert_param(pdPASS == xQueueSend(queMsgJobHandle, slot, MSG_QUE_POST_TIMEOUT)); assert_param(pdPASS == xQueueSend(queMsgJobHandle, slot, MSG_QUE_POST_TIMEOUT));

@ -2,10 +2,12 @@
// Created by MightyPork on 2017/11/25. // Created by MightyPork on 2017/11/25.
// //
#include <stm32f072xb.h>
#include "comm/messages.h"
#include "unit_base.h" #include "unit_base.h"
#include "utils/avrlibc.h"
#include "platform/irq_dispatcher.h"
#include "comm/messages.h"
#include "unit_din.h" #include "unit_din.h"
#include "tasks/task_msg.h"
/** Private data structure */ /** Private data structure */
struct priv { struct priv {
@ -13,7 +15,11 @@ struct priv {
uint16_t pins; // pin mask uint16_t pins; // pin mask
uint16_t pulldown; // pull-downs (default is pull-up) uint16_t pulldown; // pull-downs (default is pull-up)
uint16_t pullup; // pull-ups uint16_t pullup; // pull-ups
uint16_t trig_rise;
uint16_t trig_fall;
uint16_t trig_holdoff; // ms
uint16_t holdoff_countdowns[16];
GPIO_TypeDef *port; GPIO_TypeDef *port;
}; };
@ -32,7 +38,11 @@ static void DI_loadBinary(Unit *unit, PayloadParser *pp)
priv->pulldown = pp_u16(pp); priv->pulldown = pp_u16(pp);
priv->pullup = pp_u16(pp); priv->pullup = pp_u16(pp);
dbg("load bin, pulldown = %X", priv->pulldown); if (version >= 1) {
priv->trig_rise = pp_u16(pp);
priv->trig_fall = pp_u16(pp);
priv->trig_holdoff = pp_u16(pp);
}
} }
/** Write to a binary buffer for storing in Flash */ /** Write to a binary buffer for storing in Flash */
@ -40,12 +50,15 @@ static void DI_writeBinary(Unit *unit, PayloadBuilder *pb)
{ {
struct priv *priv = unit->data; struct priv *priv = unit->data;
pb_u8(pb, 0); // version pb_u8(pb, 1); // version
pb_char(pb, priv->port_name); pb_char(pb, priv->port_name);
pb_u16(pb, priv->pins); pb_u16(pb, priv->pins);
pb_u16(pb, priv->pulldown); pb_u16(pb, priv->pulldown);
pb_u16(pb, priv->pullup); pb_u16(pb, priv->pullup);
pb_u16(pb, priv->trig_rise);
pb_u16(pb, priv->trig_fall);
pb_u16(pb, priv->trig_holdoff);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -68,6 +81,15 @@ static error_t DI_loadIni(Unit *unit, const char *key, const char *value)
else if (streq(key, "pull-down")) { else if (streq(key, "pull-down")) {
priv->pulldown = parse_pinmask(value, &suc); priv->pulldown = parse_pinmask(value, &suc);
} }
else if (streq(key, "trig-rise")) {
priv->trig_rise = parse_pinmask(value, &suc);
}
else if (streq(key, "trig-fall")) {
priv->trig_fall = parse_pinmask(value, &suc);
}
else if (streq(key, "trig-hold-off")) {
priv->trig_holdoff = (uint16_t) avr_atoi(value);
}
else { else {
return E_BAD_KEY; return E_BAD_KEY;
} }
@ -93,6 +115,15 @@ static void DI_writeIni(Unit *unit, IniWriter *iw)
iw_comment(iw, "Pins with pull-down"); iw_comment(iw, "Pins with pull-down");
iw_entry(iw, "pull-down", "%s", pinmask2str(priv->pulldown, unit_tmp512)); iw_entry(iw, "pull-down", "%s", pinmask2str(priv->pulldown, unit_tmp512));
iw_comment(iw, "Trigger pins activated by rising edge");
iw_entry(iw, "trig-rise", "%s", pinmask2str(priv->trig_rise, unit_tmp512));
iw_comment(iw, "Trigger pins activated by falling edge");
iw_entry(iw, "trig-fall", "%s", pinmask2str(priv->trig_fall, unit_tmp512));
iw_comment(iw, "Trigger hold-off time (ms)");
iw_entry(iw, "trig-hold-off", "%d", (int)priv->trig_holdoff);
#if PLAT_NO_FLOATING_INPUTS #if PLAT_NO_FLOATING_INPUTS
iw_comment(iw, "NOTE: Pins use pull-up by default.\r\n"); iw_comment(iw, "NOTE: Pins use pull-up by default.\r\n");
#endif #endif
@ -112,9 +143,60 @@ static error_t DI_preInit(Unit *unit)
priv->pulldown = 0x0000; priv->pulldown = 0x0000;
priv->pullup = 0x0000; priv->pullup = 0x0000;
priv->trig_rise = 0x0000;
priv->trig_fall = 0x0000;
priv->trig_holdoff = 20;
return E_SUCCESS; return E_SUCCESS;
} }
static void ID_SendTriggerReportToMaster(Job *job)
{
Unit *unit = job->data1;
PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL);
pb_u8(&pb, unit->callsign);
pb_u8(&pb, 0x00); // report type "Trigger"
pb_u16(&pb, (uint16_t) job->d32_2); // packed, 1 on the triggering pin
pb_u16(&pb, (uint16_t) job->d32_3); //
assert_param(pb.ok);
com_send_pb(MSG_UNIT_REPORT, &pb);
}
static void DI_handleExti(void *arg)
{
Unit *unit = arg;
struct priv *priv = unit->data;
uint16_t snapshot = (uint16_t) priv->port->IDR;
uint16_t trigger_map = 0;
uint16_t mask = 1;
for (int i = 0; i < 16; i++, mask <<= 1) {
if ((priv->trig_rise|priv->trig_fall) & mask) {
if (LL_EXTI_ReadFlag_0_31(LL_EXTI_LINES[i])) {
if (priv->holdoff_countdowns[i] == 0) {
trigger_map |= 1<<i;
priv->holdoff_countdowns[i] = priv->trig_holdoff;
}
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINES[i]);
}
}
}
// FIXME the job is not correctly handled, somehow. queue fills but is not collected
if (trigger_map != 0) {
Job j = {
.data1 = unit,
.d32_2 = pinmask_pack(trigger_map, priv->pins),
.d32_3 = snapshot,
.cb = ID_SendTriggerReportToMaster
};
scheduleJob(&j);
}
}
/** Finalize unit set-up */ /** Finalize unit set-up */
static error_t DI_init(Unit *unit) static error_t DI_init(Unit *unit)
{ {
@ -150,7 +232,27 @@ static error_t DI_init(Unit *unit)
if (priv->pulldown & mask) pull = LL_GPIO_PULL_DOWN; if (priv->pulldown & mask) pull = LL_GPIO_PULL_DOWN;
if (priv->pullup & mask) pull = LL_GPIO_PULL_UP; if (priv->pullup & mask) pull = LL_GPIO_PULL_UP;
LL_GPIO_SetPinPull(priv->port, ll_pin, pull); LL_GPIO_SetPinPull(priv->port, ll_pin, pull);
if ((priv->trig_rise|priv->trig_fall) & mask) {
LL_EXTI_EnableIT_0_31(LL_EXTI_LINES[i]);
if (priv->trig_rise & mask) {
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINES[i]);
} }
if (priv->trig_fall & mask) {
LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINES[i]);
}
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTS[priv->port_name-'A'], LL_SYSCFG_EXTI_LINES[i]);
irqd_attach(EXTIS[i], DI_handleExti, unit);
}
}
}
// request ticks if we have triggers
if (priv->trig_rise|priv->trig_fall) {
unit->tick_interval = 1;
} }
return E_SUCCESS; return E_SUCCESS;
@ -160,8 +262,23 @@ static error_t DI_init(Unit *unit)
/** Tear down the unit */ /** Tear down the unit */
static void DI_deInit(Unit *unit) static void DI_deInit(Unit *unit)
{ {
struct priv *priv = unit->data;
// pins are de-inited during teardown // pins are de-inited during teardown
if (unit->status == E_SUCCESS) {
// Detach EXTI handlers and disable interrupts
if (priv->trig_rise | priv->trig_fall) {
uint16_t mask = 1;
for (int i = 0; i < 16; i++, mask <<= 1) {
if ((priv->trig_rise | priv->trig_fall) & mask) {
LL_EXTI_DisableIT_0_31(LL_EXTI_LINES[i]);
irqd_detach(EXTIS[i], DI_handleExti);
}
}
}
}
// Release all resources // Release all resources
rsc_teardown(unit); rsc_teardown(unit);
@ -203,6 +320,22 @@ static error_t DI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Pay
} }
} }
/**
* Decrement all the hold-off timers on tick
*
* @param unit
*/
static void DI_updateTick(Unit *unit)
{
struct priv *priv = unit->data;
for (int i = 0; i < 16; i++) {
if (priv->holdoff_countdowns[i] > 0) {
priv->holdoff_countdowns[i]--;
}
}
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Unit template */ /** Unit template */
@ -220,4 +353,5 @@ const UnitDriver UNIT_DIN = {
.deInit = DI_deInit, .deInit = DI_deInit,
// Function // Function
.handleRequest = DI_handleRequest, .handleRequest = DI_handleRequest,
.updateTick = DI_updateTick,
}; };

@ -19,7 +19,8 @@ static void UUSART_SendReceivedDataToMaster(Job *job)
uint32_t readpos = job->d32; uint32_t readpos = job->d32;
uint32_t count = job->len; uint32_t count = job->len;
// TODO modify TF to allow writing in multiple chunks to avoid this useless buffer copying // TODO use TF's Multipart sending
// TODO add API for building reports
PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL); PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL);
pb_u8(&pb, unit->callsign); pb_u8(&pb, unit->callsign);
pb_u8(&pb, 0x00); // report type "Data received" pb_u8(&pb, 0x00); // report type "Data received"

Loading…
Cancel
Save