From 3ebc19fc2dfbc3e7070584e49a0f79c19c8b47b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 3 Feb 2018 22:06:31 +0100 Subject: [PATCH] fixes and start of ADC. Not really working yet --- FreeRTOSConfig.h | 2 +- framework/resources.h | 8 +- framework/unit_registry.c | 2 +- freertos.c | 2 + gex.mk | 1 + platform/debug_uart.c | 5 +- platform/hw_utils.c | 87 ++++++++++- platform/hw_utils.h | 31 +++- platform/irq_dispatcher.c | 69 +++++++-- platform/platform.c | 2 + platform/platform.h | 1 + platform/timebase.c | 2 + units/1wire/_ow_init.c | 1 - units/1wire/_ow_internal.h | 3 - units/1wire/_ow_search.c | 1 - units/1wire/_ow_settings.c | 1 - units/1wire/unit_1wire.c | 2 - units/adc/_adc_init.c | 225 ++++++++++++++++++++++++++++- units/adc/_adc_internal.h | 22 +++ units/adc/_adc_settings.c | 45 +++++- units/adc/unit_adc.c | 4 +- units/digital_in/_din_init.c | 2 - units/digital_in/_din_settings.c | 1 - units/digital_in/unit_din.c | 2 - units/digital_out/_dout_init.c | 1 - units/digital_out/_dout_settings.c | 1 - units/i2c/_i2c_init.c | 4 +- units/i2c/_i2c_settings.c | 1 - units/neopixel/_npx_init.c | 6 +- units/spi/_spi_init.c | 6 +- units/test/unit_test.c | 2 +- units/usart/_usart_dmas.c | 4 +- units/usart/_usart_init.c | 11 +- units/usart/_usart_internal.h | 4 + units/usart/_usart_settings.c | 6 +- utils/malloc_safe.h | 8 +- utils/stacksmon.h | 2 +- 37 files changed, 503 insertions(+), 74 deletions(-) diff --git a/FreeRTOSConfig.h b/FreeRTOSConfig.h index 51bc917..2be418b 100644 --- a/FreeRTOSConfig.h +++ b/FreeRTOSConfig.h @@ -153,7 +153,7 @@ to exclude the API function. */ #elif defined(GEX_PLAT_F072_DISCOVERY) // This is for F072 #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 3 - #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 3 + #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1 #define configPRIO_BITS 2 diff --git a/framework/resources.h b/framework/resources.h index 2fec7a3..7ee9f4f 100644 --- a/framework/resources.h +++ b/framework/resources.h @@ -38,7 +38,7 @@ void rsc_init_registry(void); * @param pin - pin number 0-15 * @return success */ -error_t rsc_claim_pin(Unit *unit, char port_name, uint8_t pin); +error_t rsc_claim_pin(Unit *unit, char port_name, uint8_t pin) __attribute__((warn_unused_result)); /** * Claim a resource by the Resource enum @@ -47,7 +47,7 @@ error_t rsc_claim_pin(Unit *unit, char port_name, uint8_t pin); * @param rsc - resource to claim * @return success */ -error_t rsc_claim(Unit *unit, Resource rsc); +error_t rsc_claim(Unit *unit, Resource rsc) __attribute__((warn_unused_result)); /** * Claim a range of resources (use for resources of the same type, e.g. USART1-5) @@ -57,7 +57,7 @@ error_t rsc_claim(Unit *unit, Resource rsc); * @param rsc1 - last resource to claim * @return success (E_SUCCESS = complete claim) */ -error_t rsc_claim_range(Unit *unit, Resource rsc0, Resource rsc1); +error_t rsc_claim_range(Unit *unit, Resource rsc0, Resource rsc1) __attribute__((warn_unused_result)); /** * Claim GPIOs by bitmask and port name, atomically. @@ -68,7 +68,7 @@ error_t rsc_claim_range(Unit *unit, Resource rsc0, Resource rsc1); * @param pins - pins, bitmask * @return success (E_SUCCESS = complete claim) */ -error_t rsc_claim_gpios(Unit *unit, char port_name, uint16_t pins); +error_t rsc_claim_gpios(Unit *unit, char port_name, uint16_t pins) __attribute__((warn_unused_result)); /** * Release all resources held by a unit, de-init held GPIOs diff --git a/framework/unit_registry.c b/framework/unit_registry.c index f0203fb..482dda8 100644 --- a/framework/unit_registry.c +++ b/framework/unit_registry.c @@ -606,7 +606,7 @@ void ureg_tick_units(void) UlistEntry *li = ulist_head; while (li != NULL) { Unit *const pUnit = &li->unit; - if (pUnit->status == E_SUCCESS && pUnit->tick_interval > 0) { + if (pUnit && pUnit->data && pUnit->status == E_SUCCESS && pUnit->tick_interval > 0) { if (pUnit->_tick_cnt == 0) { if (pUnit->driver->updateTick) { pUnit->driver->updateTick(pUnit); diff --git a/freertos.c b/freertos.c index 045e3e0..3c69f35 100644 --- a/freertos.c +++ b/freertos.c @@ -146,6 +146,8 @@ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ stackmon_register("Main", mainTaskStack, sizeof(mainTaskStack)); stackmon_register("Job+Msg", msgJobQueTaskStack, sizeof(msgJobQueTaskStack)); + stackmon_register("Idle", xIdleStack, sizeof(xIdleStack)); + stackmon_register("Timers", xTimersStack, sizeof(xTimersStack)); /* USER CODE END Init */ /* Create the mutex(es) */ diff --git a/gex.mk b/gex.mk index ee4b54c..94a9543 100644 --- a/gex.mk +++ b/gex.mk @@ -13,6 +13,7 @@ GEX_SRC_DIR = \ User/units/1wire \ User/units/i2c \ User/units/spi \ + User/units/adc \ User/TinyFrame \ User/CWPack \ User/tasks diff --git a/platform/debug_uart.c b/platform/debug_uart.c index ce28d75..f572bc2 100644 --- a/platform/debug_uart.c +++ b/platform/debug_uart.c @@ -66,7 +66,10 @@ void DebugUart_PreInit(void) { // configure AF only if platform uses AF numbers #if !PLAT_NO_AFNUM - hw_configure_gpio_af(DEBUG_USART_PORT, DEBUG_USART_PIN, DEBUG_USART_AF); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" + (void) hw_configure_gpio_af(DEBUG_USART_PORT, DEBUG_USART_PIN, DEBUG_USART_AF); +#pragma GCC diagnostic pop #endif hw_periph_clock_enable(DEBUG_USART); diff --git a/platform/hw_utils.c b/platform/hw_utils.c index a14c33b..b395d44 100644 --- a/platform/hw_utils.c +++ b/platform/hw_utils.c @@ -4,6 +4,7 @@ #include "platform.h" #include +#include #include "hw_utils.h" #include "macro.h" @@ -263,16 +264,64 @@ char * pinmask2str(uint16_t pins, char *buffer) if (!first) { b += SPRINTF(b, ", "); } + if (start == (uint32_t)(i+1)) { b += SPRINTF(b, "%"PRIu32, start); } -// else if (start == (uint32_t)(i+2)) { -// // exception for 2-long ranges - don't show as range -// b += SPRINTF(b, "%"PRIu32",%"PRIu32, start, i + 1); -// } else { b += SPRINTF(b, "%"PRIu32"-%"PRIu32, start, i + 1); } + + first = false; + on = false; + } + } + } + + return buffer; +} + +char * pinmask2str_up(uint16_t pins, char *buffer) +{ + char *b = buffer; + uint32_t start = 0; + bool on = false; + bool first = true; + + // shortcut if none are set + if (pins == 0) { + buffer[0] = 0; + return buffer; + } + + for (int32_t i = 0; i <= 16; i++) { + bool bit; + + if (i == 16) { + bit = false; + } else { + bit = 0 != (pins & 1); + pins >>= 1; + } + + if (bit) { + if (!on) { + start = (uint32_t) i; + on = true; + } + } else { + if (on) { + if (!first) { + b += SPRINTF(b, ", "); + } + + if (start == (uint32_t)(i-1)) { + b += SPRINTF(b, "%"PRIu32, start); + } + else { + b += SPRINTF(b, "%"PRIu32"-%"PRIu32, start, i - 1); + } + first = false; on = false; } @@ -387,6 +436,36 @@ error_t hw_configure_sparse_pins(char port_name, uint16_t mask, GPIO_TypeDef **p return E_SUCCESS; } +/** Solve a timer/counter's count and prescaller value */ +bool solve_timer(uint32_t base_freq, uint32_t required_freq, bool is16bit, + uint16_t *presc, uint32_t *count, float *real_freq) +{ + if (required_freq == 0) return false; + const float fPresc = base_freq / required_freq; + uint32_t wCount = (uint32_t) lrintf(fPresc); + + const uint32_t ceil = is16bit ? UINT16_MAX : UINT32_MAX; + + uint32_t wPresc = 1; + while (wCount > ceil) { + wPresc <<= 1; + wCount >>= 1; + } + + if (wPresc > ceil || count == 0) { + return false; + } + + *count = wCount; + *presc = (uint16_t) wPresc; + + if (wPresc * wCount == 0) return false; + *real_freq = (base_freq / (wPresc * wCount)); + + return true; +} + + void hw_periph_clock_enable(void *periph) { // GPIOs are enabled by default on start-up diff --git a/platform/hw_utils.h b/platform/hw_utils.h index 15baecd..240d577 100644 --- a/platform/hw_utils.h +++ b/platform/hw_utils.h @@ -78,6 +78,7 @@ uint16_t parse_pinmask(const char *value, bool *suc); /** * Convert a pin bitmap to the ASCII format understood by str_parse_pinmask() + * This is the downto variant (15..0) * * @param pins - sparse pin map * @param buffer - output string buffer @@ -85,6 +86,16 @@ uint16_t parse_pinmask(const char *value, bool *suc); */ char * pinmask2str(uint16_t pins, char *buffer); +/** + * Convert a pin bitmap to the ASCII format understood by str_parse_pinmask() + * This is the ascending variant (0..15) + * + * @param pins - sparse pin map + * @param buffer - output string buffer + * @return the output buffer + */ +char * pinmask2str_up(uint16_t pins, char *buffer); + /** * Spread packed port pins using a mask * @@ -126,7 +137,7 @@ void hw_deinit_unit_pins(Unit *unit); * @param ll_af - LL alternate function constant * @return success */ -error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af); +error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af) __attribute__((warn_unused_result)); /** * Configure multiple pins using the bitmap pattern @@ -140,7 +151,7 @@ error_t hw_configure_gpio_af(char port_name, uint8_t pin_num, uint32_t ll_af); */ error_t hw_configure_sparse_pins(char port_name, uint16_t mask, GPIO_TypeDef **port_dest, - uint32_t ll_mode, uint32_t ll_otype); + uint32_t ll_mode, uint32_t ll_otype) __attribute__((warn_unused_result)); /** Helper struct for defining alternate mappings */ struct PinAF { @@ -161,6 +172,22 @@ void hw_periph_clock_enable(void *periph); */ void hw_periph_clock_disable(void *periph); +/** + * Solve a timer/counter's count and prescaller value to meet the desired + * overflow frequency. The resulting values are the dividing factors; + * subtract 1 before writing them into the peripheral registers. + * + * @param[in] base_freq - the counter's input clock frequency in Hz + * @param[in] required_freq - desired overflow frequency + * @param[in] is16bit - limit counter to 16 bits (prescaller is always 16-bit) + * @param[out] presc - field for storing the computed prescaller value + * @param[out] count - field for storing the computed counter value + * @param[out] real_freq - field for storing the computed real frequency + * @return true on success + */ +bool solve_timer(uint32_t base_freq, uint32_t required_freq, bool is16bit, + uint16_t *presc, uint32_t *count, float *real_freq); + // ---------- LL extras ------------ static inline bool LL_DMA_IsActiveFlag_G(uint32_t isr_snapshot, uint8_t channel) diff --git a/platform/irq_dispatcher.c b/platform/irq_dispatcher.c index 2908254..13e18a0 100644 --- a/platform/irq_dispatcher.c +++ b/platform/irq_dispatcher.c @@ -61,6 +61,10 @@ static struct callbacks_ { struct cbslot dma2_7; struct cbslot dma2_8; + struct cbslot tim6; + struct cbslot tim7; + struct cbslot tim15; + // XXX add more callbacks here when needed } callbacks; @@ -68,41 +72,62 @@ void irqd_init(void) { memset(&callbacks, 0, sizeof(callbacks)); + // TODO move the priorities to some define + // NVIC_EnableIRQ(WWDG_IRQn); /*!< Window WatchDog Interrupt */ // NVIC_EnableIRQ(PVD_VDDIO2_IRQn); /*!< PVD & VDDIO2 Interrupt through EXTI Lines 16 and 31 */ // NVIC_EnableIRQ(RTC_IRQn); /*!< RTC Interrupt through EXTI Lines 17, 19 and 20 */ // NVIC_EnableIRQ(FLASH_IRQn); /*!< FLASH global Interrupt */ // NVIC_EnableIRQ(RCC_CRS_IRQn); /*!< RCC & CRS global 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(EXTI4_15_IRQn); /*!< EXTI Line 4 to 15 Interrupt */ + HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0); + HAL_NVIC_SetPriority(EXTI2_3_IRQn, 2, 0); + HAL_NVIC_SetPriority(EXTI4_15_IRQn, 2, 0); + // NVIC_EnableIRQ(TSC_IRQn); /*!< Touch Sensing Controller Interrupts */ + 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_Channel4_5_6_7_IRQn); /*!< DMA1 Channel 4 to Channel 7 Interrupt */ - HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 0); - HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3, 0); - HAL_NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 3, 0); + HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 2, 0); + HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 2, 0); + HAL_NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 2, 0); + // NVIC_EnableIRQ(ADC1_COMP_IRQn); /*!< ADC1 and COMP interrupts (ADC interrupt combined with EXTI Lines 21 and 22 */ // NVIC_EnableIRQ(TIM1_IRQn); /*!< TIM1 global Interrupt */ // NVIC_EnableIRQ(TIM2_IRQn); /*!< TIM2 global Interrupt */ // NVIC_EnableIRQ(TIM3_IRQn); /*!< TIM3 global Interrupt */ -// NVIC_EnableIRQ(TIM6_DAC_IRQn); /*!< TIM6 global and DAC channel underrun error Interrupt */ -// NVIC_EnableIRQ(TIM7_IRQn); /*!< TIM7 global Interrupt */ -// --used internally-- NVIC_EnableIRQ(TIM14_IRQn); /*!< TIM14 global Interrupt */ -// NVIC_EnableIRQ(TIM15_IRQn); /*!< TIM15 global Interrupt */ + + NVIC_EnableIRQ(TIM6_DAC_IRQn); /*!< TIM6 global and DAC channel underrun error Interrupt */ + HAL_NVIC_SetPriority(TIM7_IRQn, 2, 0); // Used for DAC timing + + NVIC_EnableIRQ(TIM7_IRQn); /*!< TIM7 global Interrupt */ + HAL_NVIC_SetPriority(TIM7_IRQn, 2, 0); + + /* Tim14 is used for HAL timebase, because SysTick is used to time FreeRTOS and has the lowest priority. */ + /* Tim14's priority is set to 0 in the init routine, which runs early in the startup sequence */ + // NVIC_EnableIRQ(TIM14_IRQn); /*!< TIM14 global Interrupt */ + + NVIC_EnableIRQ(TIM15_IRQn); /*!< TIM15 global Interrupt */ + HAL_NVIC_SetPriority(TIM15_IRQn, 2, 0); + // NVIC_EnableIRQ(TIM16_IRQn); /*!< TIM16 global Interrupt */ // NVIC_EnableIRQ(TIM17_IRQn); /*!< TIM17 global Interrupt */ // NVIC_EnableIRQ(I2C1_IRQn); /*!< I2C1 Event Interrupt & EXTI Line23 Interrupt (I2C1 wakeup) */ // NVIC_EnableIRQ(I2C2_IRQn); /*!< I2C2 Event Interrupt */ // NVIC_EnableIRQ(SPI1_IRQn); /*!< SPI1 global Interrupt */ // NVIC_EnableIRQ(SPI2_IRQn); /*!< SPI2 global Interrupt */ + NVIC_EnableIRQ(USART1_IRQn); /*!< USART1 global Interrupt & EXTI Line25 Interrupt (USART1 wakeup) */ NVIC_EnableIRQ(USART2_IRQn); /*!< USART2 global Interrupt & EXTI Line26 Interrupt (USART2 wakeup) */ NVIC_EnableIRQ(USART3_4_IRQn); /*!< USART3 and USART4 global Interrupt */ - HAL_NVIC_SetPriority(USART1_IRQn, 3, 0); - HAL_NVIC_SetPriority(USART2_IRQn, 3, 0); - HAL_NVIC_SetPriority(USART3_4_IRQn, 3, 0); + HAL_NVIC_SetPriority(USART1_IRQn, 2, 0); + HAL_NVIC_SetPriority(USART2_IRQn, 2, 0); + HAL_NVIC_SetPriority(USART3_4_IRQn, 2, 0); + // NVIC_EnableIRQ(CEC_CAN_IRQn); /*!< CEC and CAN global Interrupts & EXTI Line27 Interrupt */ // NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); /*!< TIM1 Break, Update, Trigger and Commutation Interrupt */ // - handled by hal msp init @@ -130,6 +155,10 @@ static struct cbslot *get_slot_for_periph(void *periph) else if (periph == USART5) slot = &callbacks.usart5; #endif + else if (periph == TIM6) slot = &callbacks.tim6; + else if (periph == TIM7) slot = &callbacks.tim7; + else if (periph == TIM15) slot = &callbacks.tim15; + else if (periph >= EXTIS[0] && periph <= EXTIS[15]) { slot = &callbacks.exti[periph - EXTIS[0]]; } @@ -265,6 +294,26 @@ void EXTI4_15_IRQHandler(void) } +// ------------ INTERRUPTS ------------- + +// TIM14 is used to generate HAL timebase and its handler is in the file "timebase.c" + +void TIM6_DAC_IRQHandler(void) +{ + CALL_IRQ_HANDLER(callbacks.tim6); +} + +void TIM7_IRQHandler(void) +{ + CALL_IRQ_HANDLER(callbacks.tim7); +} + +void TIM15_IRQHandler(void) +{ + CALL_IRQ_HANDLER(callbacks.tim15); +} + + // other ISRs... #if 0 diff --git a/platform/platform.c b/platform/platform.c index e1eff83..cead5c4 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -13,6 +13,7 @@ #include "units/neopixel/unit_neopixel.h" #include "units/i2c/unit_i2c.h" #include "units/1wire/unit_1wire.h" +#include "units/adc/unit_adc.h" #include "units/test/unit_test.h" #include "units/usart/unit_usart.h" #include "units/spi/unit_spi.h" @@ -84,6 +85,7 @@ void plat_init_resources(void) ureg_add_type(&UNIT_SPI); ureg_add_type(&UNIT_USART); ureg_add_type(&UNIT_1WIRE); + ureg_add_type(&UNIT_ADC); // Free all present resources { diff --git a/platform/platform.h b/platform/platform.h index f9199df..1b52749 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -13,6 +13,7 @@ #include #include #include +#include // FreeRTOS includes #include diff --git a/platform/timebase.c b/platform/timebase.c index 932c92a..958f8cd 100644 --- a/platform/timebase.c +++ b/platform/timebase.c @@ -15,6 +15,8 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) // This makes it a good choice for the timebase generation. We set it to generate // an interrupt every 1 ms + assert_param(TickPriority == 0); // any other setting can lead to crashes + // - TIM14 is always up-counting // - using APB1 clock __HAL_RCC_TIM14_CLK_ENABLE(); diff --git a/units/1wire/_ow_init.c b/units/1wire/_ow_init.c index 10f21f7..0893d10 100644 --- a/units/1wire/_ow_init.c +++ b/units/1wire/_ow_init.c @@ -7,7 +7,6 @@ #define OW_INTERNAL #include "_ow_internal.h" -#include "_ow_init.h" /** Allocate data structure and set defaults */ error_t OW_preInit(Unit *unit) diff --git a/units/1wire/_ow_internal.h b/units/1wire/_ow_internal.h index 7e00a6d..436dd93 100644 --- a/units/1wire/_ow_internal.h +++ b/units/1wire/_ow_internal.h @@ -27,9 +27,6 @@ struct priv { struct ow_search_state searchState; }; -/** Allocate data structure and set defaults */ -error_t OW_preInit(Unit *unit); - /** Load from a binary buffer stored in Flash */ void OW_loadBinary(Unit *unit, PayloadParser *pp); diff --git a/units/1wire/_ow_search.c b/units/1wire/_ow_search.c index 5a5a978..50cbe79 100644 --- a/units/1wire/_ow_search.c +++ b/units/1wire/_ow_search.c @@ -9,7 +9,6 @@ #include "_ow_search.h" #include "_ow_internal.h" #include "_ow_low_level.h" -#include "_ow_checksum.h" #include "_ow_commands.h" void ow_search_init(Unit *unit, uint8_t command, bool test_checksums) diff --git a/units/1wire/_ow_settings.c b/units/1wire/_ow_settings.c index c879c9c..c43b3bf 100644 --- a/units/1wire/_ow_settings.c +++ b/units/1wire/_ow_settings.c @@ -7,7 +7,6 @@ #define OW_INTERNAL #include "_ow_internal.h" -#include "_ow_settings.h" /** Load from a binary buffer stored in Flash */ void OW_loadBinary(Unit *unit, PayloadParser *pp) diff --git a/units/1wire/unit_1wire.c b/units/1wire/unit_1wire.c index 84a187a..194c391 100644 --- a/units/1wire/unit_1wire.c +++ b/units/1wire/unit_1wire.c @@ -9,8 +9,6 @@ // 1WIRE master #define OW_INTERNAL #include "_ow_internal.h" -#include "_ow_init.h" -#include "_ow_settings.h" #include "_ow_low_level.h" /** diff --git a/units/adc/_adc_init.c b/units/adc/_adc_init.c index cc228d0..5f2d9e4 100644 --- a/units/adc/_adc_init.c +++ b/units/adc/_adc_init.c @@ -8,29 +8,241 @@ #define ADC_INTERNAL #include "_adc_internal.h" +const uint32_t LL_ADC_SAMPLETIMES[] = { + LL_ADC_SAMPLINGTIME_1CYCLE_5, + LL_ADC_SAMPLINGTIME_7CYCLES_5, + LL_ADC_SAMPLINGTIME_13CYCLES_5, + LL_ADC_SAMPLINGTIME_28CYCLES_5, + LL_ADC_SAMPLINGTIME_41CYCLES_5, + LL_ADC_SAMPLINGTIME_55CYCLES_5, + LL_ADC_SAMPLINGTIME_71CYCLES_5, + LL_ADC_SAMPLINGTIME_239CYCLES_5, +}; + + /** Allocate data structure and set defaults */ error_t UADC_preInit(Unit *unit) { struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv)); if (priv == NULL) return E_OUT_OF_MEM; - // + priv->channels = 1; // PA0 + priv->enable_tsense = false; + priv->enable_vref = false; + priv->sample_time = 0b010; // 13.5c + priv->frequency = 4; //1000 return E_SUCCESS; } +static void UADC_DMA_Handler(void *arg) +{ + Unit *unit = arg; + + dbg("ADC DMA ISR hit"); + assert_param(unit); + struct priv *priv = unit->data; + assert_param(priv); + + const uint32_t isrsnapshot = priv->DMAx->ISR; + + if (LL_DMA_IsActiveFlag_G(isrsnapshot, priv->dma_chnum)) { + bool tc = LL_DMA_IsActiveFlag_TC(isrsnapshot, priv->dma_chnum); + bool ht = LL_DMA_IsActiveFlag_HT(isrsnapshot, priv->dma_chnum); + + // Here we have to either copy it somewhere else, or notify another thread (queue?) + // that the data is ready for reading + + if (ht) { + uint16_t start = 0; + uint16_t end = (uint16_t) (priv->dma_buffer_size / 2); + // TODO handle first half + LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum); + } + + if (tc) { + uint16_t start = (uint16_t) (priv->dma_buffer_size / 2); + uint16_t end = (uint16_t) priv->dma_buffer_size; + // TODO handle second half + LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum); + } + + if (LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_chnum)) { + // this shouldn't happen - error + dbg("ADC DMA TE!"); + LL_DMA_ClearFlag_TE(priv->DMAx, priv->dma_chnum); + } + } +} + /** Finalize unit set-up */ error_t UADC_init(Unit *unit) { bool suc = true; struct priv *priv = unit->data; - // + // Written for F072 which has only one ADC + + TRY(rsc_claim(unit, R_ADC1)); + TRY(rsc_claim(unit, R_DMA1_1)); + TRY(rsc_claim(unit, R_TIM15)); + + priv->DMAx = DMA1; + priv->DMA_CHx = DMA1_Channel1; + priv->dma_chnum = 1; + priv->ADCx = ADC1; + priv->ADCx_Common = ADC1_COMMON; + priv->TIMx = TIM15; + + // ----------------------- CONFIGURE PINS -------------------------- + { + // Claim and configure all analog pins + priv->nb_channels = 0; + for (uint8_t i = 0; i < 16; i++) { + if (priv->channels & (1 << i)) { + char c; + uint8_t num; + if (i <= 7) { + c = 'A'; + num = i; + } + else if (i <= 9) { + c = 'B'; + num = (uint8_t) (i - 8); + } + else { + c = 'C'; + num = (uint8_t) (i - 10); + } + + TRY(rsc_claim_pin(unit, c, num)); + uint32_t ll_pin = hw_pin2ll(num, &suc); + GPIO_TypeDef *port = hw_port2periph(c, &suc); + assert_param(suc); + + LL_GPIO_SetPinPull(port, ll_pin, LL_GPIO_PULL_NO); + LL_GPIO_SetPinMode(port, ll_pin, LL_GPIO_MODE_ANALOG); + priv->nb_channels++; + } + } + if (priv->enable_tsense) priv->nb_channels++; + if (priv->enable_vref) priv->nb_channels++; + + if (priv->nb_channels == 0) { + dbg("!! Need at least 1 channel"); + return E_BAD_CONFIG; + } + } + + // ------------------- ENABLE CLOCKS -------------------------- + { + // enable peripherals clock + hw_periph_clock_enable(priv->ADCx); + hw_periph_clock_enable(priv->TIMx); + } + + // ------------------- CONFIGURE THE TIMER -------------------------- + dbg("Setting up TIMER"); + { + // Find suitable timer values + uint16_t presc; + uint32_t count; + float real_freq; + if (!solve_timer(PLAT_APB1_HZ, priv->frequency, true, &presc, &count, + &real_freq)) { + dbg("Failed to resolve timer params."); + return E_BAD_VALUE; + } + dbg("Frequency error %d ppm, presc %d, count %d", + (int) lrintf(1000000.0f * ((real_freq - priv->frequency) / (float)priv->frequency)), (int) presc, (int) count); + + LL_TIM_SetPrescaler(priv->TIMx, (uint32_t) (presc - 1)); + LL_TIM_SetAutoReload(priv->TIMx, count - 1); + LL_TIM_EnableARRPreload(priv->TIMx); + LL_TIM_EnableUpdateEvent(priv->TIMx); + LL_TIM_GenerateEvent_UPDATE(priv->TIMx); // load the prescaller value + } + + // --------------------- CONFIGURE THE ADC --------------------------- + dbg("Setting up ADC"); + { + // Calibrate the ADC + dbg("Wait for calib"); + LL_ADC_StartCalibration(priv->ADCx); + while (LL_ADC_IsCalibrationOnGoing(priv->ADCx)) {} + dbg("ADC calibrated."); + + uint32_t mask = 0; + if (priv->enable_vref) mask |= LL_ADC_PATH_INTERNAL_VREFINT; + if (priv->enable_tsense) mask |= LL_ADC_PATH_INTERNAL_TEMPSENSOR; + LL_ADC_SetCommonPathInternalCh(priv->ADCx_Common, mask); + LL_ADC_SetDataAlignment(priv->ADCx, LL_ADC_DATA_ALIGN_RIGHT); + LL_ADC_SetResolution(priv->ADCx, LL_ADC_RESOLUTION_12B); + LL_ADC_REG_SetDMATransfer(priv->ADCx, LL_ADC_REG_DMA_TRANSFER_UNLIMITED); + + // configure channels + LL_ADC_REG_SetSequencerChannels(priv->ADCx, priv->channels); + if (priv->enable_tsense) LL_ADC_REG_SetSequencerChAdd(priv->ADCx, LL_ADC_CHANNEL_TEMPSENSOR); + if (priv->enable_vref) LL_ADC_REG_SetSequencerChAdd(priv->ADCx, LL_ADC_CHANNEL_VREFINT); + + LL_ADC_REG_SetTriggerSource(priv->ADCx, LL_ADC_REG_TRIG_EXT_TIM15_TRGO); + + LL_ADC_SetSamplingTimeCommonChannels(priv->ADCx, LL_ADC_SAMPLETIMES[priv->sample_time]); + + LL_ADC_Enable(priv->ADCx); + } + + // --------------------- CONFIGURE DMA ------------------------------- + dbg("Setting up DMA"); + { + // The length must be a 2*multiple of the number of channels + // this is a horrible way to do it but will work + uint16_t itemcount = (uint16_t) (priv->nb_channels * (uint16_t) (UADC_DMA_MAX_BUF_LEN / (2 * priv->nb_channels))); + priv->dma_buffer_size = (uint16_t) (itemcount * 2); + dbg("DMA item count is %d (%d bytes)", itemcount, priv->dma_buffer_size); + + priv->dma_buffer = malloc_ck(priv->dma_buffer_size); + if (NULL == priv->dma_buffer) return E_OUT_OF_MEM; + assert_param(((uint32_t) priv->dma_buffer & 3) == 0); // must be aligned + + { + LL_DMA_InitTypeDef init; + LL_DMA_StructInit(&init); + init.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + + init.Mode = LL_DMA_MODE_CIRCULAR; + init.NbData = itemcount; + + init.PeriphOrM2MSrcAddress = (uint32_t) &priv->ADCx->DR; + init.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD; + init.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + + init.MemoryOrM2MDstAddress = (uint32_t) priv->dma_buffer; + init.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD; + init.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + + assert_param(SUCCESS == LL_DMA_Init(priv->DMAx, priv->dma_chnum, &init)); + + irqd_attach(priv->DMA_CHx, UADC_DMA_Handler, unit); + // Interrupt on transfer 1/2 and complete + // We will capture the first and second half and send it while the other half is being filled. + LL_DMA_EnableIT_HT(priv->DMAx, priv->dma_chnum); + LL_DMA_EnableIT_TC(priv->DMAx, priv->dma_chnum); + } + + LL_DMA_EnableChannel(priv->DMAx, priv->dma_chnum); + } + + dbg("ADC inited, starting the timer ..."); + + // FIXME - temporary demo - counter start... + LL_TIM_EnableCounter(priv->TIMx); return E_SUCCESS; } + /** Tear down the unit */ void UADC_deInit(Unit *unit) { @@ -38,7 +250,14 @@ void UADC_deInit(Unit *unit) // de-init peripherals if (unit->status == E_SUCCESS ) { - // + //LL_ADC_DeInit(priv->ADCx); + LL_ADC_CommonDeInit(priv->ADCx_Common); + LL_TIM_DeInit(priv->TIMx); + + irqd_detach(priv->DMAx, UADC_DMA_Handler); + LL_DMA_DeInit(priv->DMAx, priv->dma_chnum); + + free_ck(priv->dma_buffer); } // Release all resources, deinit pins diff --git a/units/adc/_adc_internal.h b/units/adc/_adc_internal.h index c6c7225..319f218 100644 --- a/units/adc/_adc_internal.h +++ b/units/adc/_adc_internal.h @@ -14,10 +14,32 @@ /** Private data structure */ struct priv { // settings + uint16_t channels; //!< bit flags (will be recorded in order 0-15) + bool enable_tsense; //!< append a signal from the temperature channel (voltage proportional to Tj) + bool enable_vref; //!< append a signal from the internal voltage reference + uint8_t sample_time; //!< 0-7 (corresponds to 1.5-239.5 cycles) - time for the sampling capacitor to charge + uint32_t frequency; //!< Timer frequency in Hz. Note: not all frequencies can be achieved accurately + + // TODO averaging (maybe a separate component?) + // TODO threshold watchdog with hysteresis (maybe a separate component?) + // TODO trigger level, edge direction, hold-off, pre-trigger buffer (extract from the DMA buffer) // internal state + ADC_TypeDef *ADCx; + ADC_Common_TypeDef *ADCx_Common; + TIM_TypeDef *TIMx; + DMA_TypeDef *DMAx; + uint8_t dma_chnum; + DMA_Channel_TypeDef *DMA_CHx; + uint16_t *dma_buffer; + uint8_t nb_channels; // nr of enabled adc channels + uint16_t dma_buffer_size; // real number of bytes }; +// max size of the DMA buffer. The actual buffer size will be adjusted to accommodate +// an even number of sample groups (sets of channels) +#define UADC_DMA_MAX_BUF_LEN 512 + /** Allocate data structure and set defaults */ error_t UADC_preInit(Unit *unit); diff --git a/units/adc/_adc_settings.c b/units/adc/_adc_settings.c index 79101cd..e35ec86 100644 --- a/units/adc/_adc_settings.c +++ b/units/adc/_adc_settings.c @@ -16,7 +16,11 @@ void UADC_loadBinary(Unit *unit, PayloadParser *pp) uint8_t version = pp_u8(pp); (void)version; - // + priv->channels = pp_u16(pp); + priv->enable_tsense = pp_bool(pp); + priv->enable_vref = pp_bool(pp); + priv->sample_time = pp_u8(pp); + priv->frequency = pp_u32(pp); } /** Write to a binary buffer for storing in Flash */ @@ -26,7 +30,11 @@ void UADC_writeBinary(Unit *unit, PayloadBuilder *pb) pb_u8(pb, 0); // version - // + pb_u16(pb, priv->channels); + pb_bool(pb, priv->enable_tsense); + pb_bool(pb, priv->enable_vref); + pb_u8(pb, priv->sample_time); + pb_u32(pb, priv->frequency); } // ------------------------------------------------------------------------ @@ -37,8 +45,21 @@ error_t UADC_loadIni(Unit *unit, const char *key, const char *value) bool suc = true; struct priv *priv = unit->data; - if (false) { - // + if (streq(key, "channels")) { + priv->channels = parse_pinmask(value, &suc); + } + else if (streq(key, "enable_tsense")) { + priv->enable_tsense = str_parse_yn(value, &suc); + } + else if (streq(key, "enable_vref")) { + priv->enable_vref = str_parse_yn(value, &suc); + } + else if (streq(key, "sample_time")) { + priv->sample_time = (uint8_t) avr_atoi(value); + if (priv->sample_time > 7) return E_BAD_VALUE; + } + else if (streq(key, "frequency")) { + priv->frequency = (uint32_t) avr_atoi(value); } else { return E_BAD_KEY; @@ -53,6 +74,20 @@ void UADC_writeIni(Unit *unit, IniWriter *iw) { struct priv *priv = unit->data; - // + iw_comment(iw, "Enabled channels, comma separated"); + iw_comment(iw, "0-7 = A0-A7, 8-9 = B0-B1, 10-15 = C0-C5"); + iw_entry(iw, "channels", "%s", pinmask2str_up(priv->channels, unit_tmp512)); + + iw_comment(iw, "Enable Tsense channel"); + iw_entry(iw, "enable_tsense", str_yn(priv->enable_tsense)); + + iw_comment(iw, "Enable Vref channel"); + iw_entry(iw, "enable_vref", str_yn(priv->enable_tsense)); + + iw_comment(iw, "Sampling time (0-7)"); + iw_entry(iw, "sample_time", "%d", (int)priv->sample_time); + + iw_comment(iw, "Sampling frequency (Hz)"); + iw_entry(iw, "frequency", "%d", (int)priv->frequency); } diff --git a/units/adc/unit_adc.c b/units/adc/unit_adc.c index e966b18..c1a3e73 100644 --- a/units/adc/unit_adc.c +++ b/units/adc/unit_adc.c @@ -11,7 +11,7 @@ // ------------------------------------------------------------------------ enum TplCmd_ { - // + CMD_DUMMY, }; /** Handle a request message */ @@ -28,7 +28,7 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P /** Unit template */ const UnitDriver UNIT_ADC = { .name = "ADC", - .description = "Template unit", + .description = "Analog inputs", // Settings .preInit = UADC_preInit, .cfgLoadBinary = UADC_loadBinary, diff --git a/units/digital_in/_din_init.c b/units/digital_in/_din_init.c index ab7be55..7d501ce 100644 --- a/units/digital_in/_din_init.c +++ b/units/digital_in/_din_init.c @@ -7,8 +7,6 @@ #define DIN_INTERNAL #include "_din_internal.h" -#include "_din_init.h" -#include "_din_exti.h" /** Allocate data structure and set defaults */ error_t DIn_preInit(Unit *unit) diff --git a/units/digital_in/_din_settings.c b/units/digital_in/_din_settings.c index 699a719..5c5f235 100644 --- a/units/digital_in/_din_settings.c +++ b/units/digital_in/_din_settings.c @@ -7,7 +7,6 @@ #define DIN_INTERNAL #include "_din_internal.h" -#include "_din_settings.h" /** Load from a binary buffer stored in Flash */ void DIn_loadBinary(Unit *unit, PayloadParser *pp) diff --git a/units/digital_in/unit_din.c b/units/digital_in/unit_din.c index 73b9f05..0e66784 100644 --- a/units/digital_in/unit_din.c +++ b/units/digital_in/unit_din.c @@ -7,8 +7,6 @@ #define DIN_INTERNAL #include "_din_internal.h" -#include "_din_settings.h" -#include "_din_init.h" // ------------------------------------------------------------------------ diff --git a/units/digital_out/_dout_init.c b/units/digital_out/_dout_init.c index 55856cf..8ee2a0c 100644 --- a/units/digital_out/_dout_init.c +++ b/units/digital_out/_dout_init.c @@ -7,7 +7,6 @@ #define DOUT_INTERNAL #include "_dout_internal.h" -#include "_dout_init.h" /** Allocate data structure and set defaults */ error_t DOut_preInit(Unit *unit) diff --git a/units/digital_out/_dout_settings.c b/units/digital_out/_dout_settings.c index b262b6b..f275504 100644 --- a/units/digital_out/_dout_settings.c +++ b/units/digital_out/_dout_settings.c @@ -7,7 +7,6 @@ #define DOUT_INTERNAL #include "_dout_internal.h" -#include "_dout_settings.h" /** Load from a binary buffer stored in Flash */ void DOut_loadBinary(Unit *unit, PayloadParser *pp) diff --git a/units/i2c/_i2c_init.c b/units/i2c/_i2c_init.c index 2b696fa..a2bde44 100644 --- a/units/i2c/_i2c_init.c +++ b/units/i2c/_i2c_init.c @@ -118,8 +118,8 @@ error_t UI2C_init(Unit *unit) TRY(rsc_claim_pin(unit, portname, pin_sda)); TRY(rsc_claim_pin(unit, portname, pin_scl)); - hw_configure_gpio_af(portname, pin_sda, af_i2c); - hw_configure_gpio_af(portname, pin_scl, af_i2c); + TRY(hw_configure_gpio_af(portname, pin_sda, af_i2c)); + TRY(hw_configure_gpio_af(portname, pin_scl, af_i2c)); hw_periph_clock_enable(priv->periph); diff --git a/units/i2c/_i2c_settings.c b/units/i2c/_i2c_settings.c index 348e756..72ec502 100644 --- a/units/i2c/_i2c_settings.c +++ b/units/i2c/_i2c_settings.c @@ -7,7 +7,6 @@ #define I2C_INTERNAL #include "_i2c_internal.h" -#include "_i2c_settings.h" /** Load from a binary buffer stored in Flash */ void UI2C_loadBinary(Unit *unit, PayloadParser *pp) diff --git a/units/neopixel/_npx_init.c b/units/neopixel/_npx_init.c index 471aab0..f27a0f0 100644 --- a/units/neopixel/_npx_init.c +++ b/units/neopixel/_npx_init.c @@ -13,10 +13,10 @@ error_t Npx_preInit(Unit *unit) { struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv)); - if (priv == NULL) + if (priv == NULL) return E_OUT_OF_MEM; - // some defaults - priv->pin_number = 0; + // some defaults + priv->pin_number = 0; priv->port_name = 'A'; priv->pixels = 1; diff --git a/units/spi/_spi_init.c b/units/spi/_spi_init.c index 3a779fd..a76bf08 100644 --- a/units/spi/_spi_init.c +++ b/units/spi/_spi_init.c @@ -132,9 +132,9 @@ error_t USPI_init(Unit *unit) TRY(rsc_claim_pin(unit, spi_portname, pin_miso)); TRY(rsc_claim_pin(unit, spi_portname, pin_sck)); - hw_configure_gpio_af(spi_portname, pin_mosi, af_spi); - hw_configure_gpio_af(spi_portname, pin_miso, af_spi); - hw_configure_gpio_af(spi_portname, pin_sck, af_spi); + TRY(hw_configure_gpio_af(spi_portname, pin_mosi, af_spi)); + TRY(hw_configure_gpio_af(spi_portname, pin_miso, af_spi)); + TRY(hw_configure_gpio_af(spi_portname, pin_sck, af_spi)); // configure SSN GPIOs { diff --git a/units/test/unit_test.c b/units/test/unit_test.c index 322daf6..c551f51 100644 --- a/units/test/unit_test.c +++ b/units/test/unit_test.c @@ -112,7 +112,7 @@ static void bw_dump(struct bulk_write *bulk, const uint8_t *chunk, uint32_t len) } dbg("\r\nBulk write at %d, len %d", (int)bulk->offset, (int)len); - PUTSN((const char *) chunk, len); + PUTSN((const char *) chunk, (uint16_t) len); PUTS("\r\n"); } diff --git a/units/usart/_usart_dmas.c b/units/usart/_usart_dmas.c index 1723832..39de18e 100644 --- a/units/usart/_usart_dmas.c +++ b/units/usart/_usart_dmas.c @@ -190,7 +190,6 @@ error_t UUSART_SetupDMAs(Unit *unit) LL_DMA_EnableChannel(priv->dma, priv->dma_rx_chnum); LL_DMA_EnableChannel(priv->dma, priv->dma_tx_chnum); - // TODO also set up usart timeout interrupt that grabs whatever is in the DMA buffer and sends it return E_SUCCESS; } @@ -205,7 +204,7 @@ static void UUSART_DMA_RxHandler(void *arg) struct priv *priv = unit->data; assert_param(priv); - uint32_t isrsnapshot = priv->dma->ISR; + const uint32_t isrsnapshot = priv->dma->ISR; if (LL_DMA_IsActiveFlag_G(isrsnapshot, priv->dma_rx_chnum)) { bool tc = LL_DMA_IsActiveFlag_TC(isrsnapshot, priv->dma_rx_chnum); @@ -228,6 +227,7 @@ static void UUSART_DMA_RxHandler(void *arg) if (LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_rx_chnum)) { // this shouldn't happen + dbg("USART DMA TE!"); LL_DMA_ClearFlag_TE(priv->dma, priv->dma_rx_chnum); } } diff --git a/units/usart/_usart_init.c b/units/usart/_usart_init.c index 87a733e..6a8d00f 100644 --- a/units/usart/_usart_init.c +++ b/units/usart/_usart_init.c @@ -1,7 +1,6 @@ // // Created by MightyPork on 2018/01/14. // -#include #include "platform.h" #include "unit_base.h" @@ -25,7 +24,7 @@ error_t UUSART_preInit(Unit *unit) priv->baudrate = 115200; priv->parity = 0; //!< 0-none, 1-odd, 2-even priv->stopbits = 1; //!< 0-half, 1-one, 2-1.5, 3-two - priv->direction = 3; // RXTX + priv->direction = UUSART_DIRECTION_RXTX; // RXTX priv->hw_flow_control = false; priv->clock_output = false; @@ -205,7 +204,7 @@ static inline error_t UUSART_configPins(Unit *unit) if (pins_wanted[i]) { if (mappings[i].port == 0) return E_BAD_CONFIG; TRY(rsc_claim_pin(unit, mappings[i].port, mappings[i].pin)); - hw_configure_gpio_af(mappings[i].port, mappings[i].pin, mappings[i].af); + TRY(hw_configure_gpio_af(mappings[i].port, mappings[i].pin, mappings[i].af)); } } @@ -252,9 +251,9 @@ error_t UUSART_init(Unit *unit) : LL_USART_STOPBITS_2); LL_USART_SetTransferDirection(priv->periph, - priv->direction == 1 ? LL_USART_DIRECTION_RX : - priv->direction == 2 ? LL_USART_DIRECTION_TX - : LL_USART_DIRECTION_TX_RX); + (priv->direction == UUSART_DIRECTION_RX) ? LL_USART_DIRECTION_RX : + (priv->direction == UUSART_DIRECTION_TX) ? LL_USART_DIRECTION_TX + : LL_USART_DIRECTION_TX_RX); LL_USART_SetHWFlowCtrl(priv->periph, priv->hw_flow_control == 0 ? LL_USART_HWCONTROL_NONE : diff --git a/units/usart/_usart_internal.h b/units/usart/_usart_internal.h index 243651e..7b4584a 100644 --- a/units/usart/_usart_internal.h +++ b/units/usart/_usart_internal.h @@ -17,6 +17,10 @@ #define UUSART_RXBUF_LEN 128 #define UUSART_TXBUF_LEN 128 +#define UUSART_DIRECTION_RX 1 +#define UUSART_DIRECTION_TX 2 +#define UUSART_DIRECTION_RXTX 3 + /** Private data structure */ struct priv { uint8_t periph_num; //!< 1-6 diff --git a/units/usart/_usart_settings.c b/units/usart/_usart_settings.c index 4e17273..c827762 100644 --- a/units/usart/_usart_settings.c +++ b/units/usart/_usart_settings.c @@ -104,9 +104,9 @@ error_t UUSART_loadIni(Unit *unit, const char *key, const char *value) } else if (streq(key, "direction")) { priv->direction = (uint8_t) str_parse_3(value, - "RX", 1, - "TX", 2, - "RXTX", 3, &suc); + "RX", UUSART_DIRECTION_RX, + "TX", UUSART_DIRECTION_TX, + "RXTX", UUSART_DIRECTION_RXTX, &suc); } else if (streq(key, "hw-flow-control")) { priv->hw_flow_control = (uint8_t) str_parse_4(value, diff --git a/utils/malloc_safe.h b/utils/malloc_safe.h index 5f9d372..bbb1bb1 100644 --- a/utils/malloc_safe.h +++ b/utils/malloc_safe.h @@ -15,10 +15,10 @@ #include #include -void *malloc_ck_do(size_t size, const char* file, uint32_t line) __attribute__((malloc)); -void *calloc_ck_do(size_t nmemb, size_t size, const char* file, uint32_t line) __attribute__((malloc)); -char *strdup_ck_do(const char *s, const char* file, uint32_t line) __attribute__((malloc)); -char *strndup_ck_do(const char *s, uint32_t len, const char* file, uint32_t line) __attribute__((malloc)); +void *malloc_ck_do(size_t size, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); +void *calloc_ck_do(size_t nmemb, size_t size, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); +char *strdup_ck_do(const char *s, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); +char *strndup_ck_do(const char *s, uint32_t len, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); #if DEBUG_MALLOC diff --git a/utils/stacksmon.h b/utils/stacksmon.h index cddc53b..cdeeb56 100644 --- a/utils/stacksmon.h +++ b/utils/stacksmon.h @@ -12,7 +12,7 @@ #if USE_STACK_MONITOR /** Number of tracked stacks, max */ -#define STACK_NUM 3 +#define STACK_NUM 4 /** * Check canaries and trap if they're dead