From 4d9ceb4cc0e974998197fa63bcbb6e4a8f339cc8 Mon Sep 17 00:00:00 2001 From: BOBAH Date: Fri, 31 Aug 2018 13:33:53 +0500 Subject: [PATCH] Added support for STM32F205 (board with crystal 16MHz) --- aprinter/board/Stm32f2_cnc_pins.h | 65 ++ aprinter/hal/stm32/Stm32f2Adc.h | 369 ++++++++++ aprinter/hal/stm32/Stm32f2Clock.h | 447 ++++++++++++ aprinter/hal/stm32/Stm32f2Pins.h | 311 +++++++++ aprinter/hal/stm32/Stm32f2Sdio.h | 658 ++++++++++++++++++ aprinter/hal/stm32/Stm32f2UsbSerial.h | 381 ++++++++++ aprinter/hal/stm32/Stm32f2Watchdog.h | 118 ++++ aprinter/platform/stm32f2/stm32f205.ld | 112 +++ aprinter/platform/stm32f2/stm32f2_support.cpp | 166 +++++ aprinter/platform/stm32f2/stm32f2_support.h | 52 ++ .../platform/stm32f2/stm32f2xx_hal_conf.h | 395 +++++++++++ aprinter/platform/stm32f2/usbd_conf.c | 610 ++++++++++++++++ aprinter/platform/stm32f2/usbd_conf.h | 74 ++ aprinter/platform/stm32f2/usbd_desc.c | 145 ++++ aprinter/platform/stm32f2/usbd_desc.h | 43 ++ config_system/generator/generate.py | 69 ++ config_system/gui/aprinter_config_editor.py | 41 ++ config_system/gui/init.js | 3 + flash.py | 9 + nix/aprinter.nix | 8 +- nix/boards.nix | 16 + nix/default.nix | 7 +- nix/stm32cubef2.nix | 52 ++ patches/stm32cubef2-warnings.patch | 603 ++++++++++++++++ patches/stm32cubef2.patch | 103 +++ scripts/build-arm-stm32f2.sh | 132 ++++ test-commands.txt | 3 + 27 files changed, 4989 insertions(+), 3 deletions(-) create mode 100755 aprinter/board/Stm32f2_cnc_pins.h create mode 100755 aprinter/hal/stm32/Stm32f2Adc.h create mode 100755 aprinter/hal/stm32/Stm32f2Clock.h create mode 100755 aprinter/hal/stm32/Stm32f2Pins.h create mode 100755 aprinter/hal/stm32/Stm32f2Sdio.h create mode 100755 aprinter/hal/stm32/Stm32f2UsbSerial.h create mode 100755 aprinter/hal/stm32/Stm32f2Watchdog.h create mode 100755 aprinter/platform/stm32f2/stm32f205.ld create mode 100755 aprinter/platform/stm32f2/stm32f2_support.cpp create mode 100755 aprinter/platform/stm32f2/stm32f2_support.h create mode 100755 aprinter/platform/stm32f2/stm32f2xx_hal_conf.h create mode 100755 aprinter/platform/stm32f2/usbd_conf.c create mode 100755 aprinter/platform/stm32f2/usbd_conf.h create mode 100755 aprinter/platform/stm32f2/usbd_desc.c create mode 100755 aprinter/platform/stm32f2/usbd_desc.h create mode 100644 nix/stm32cubef2.nix create mode 100755 patches/stm32cubef2-warnings.patch create mode 100755 patches/stm32cubef2.patch create mode 100755 scripts/build-arm-stm32f2.sh diff --git a/aprinter/board/Stm32f2_cnc_pins.h b/aprinter/board/Stm32f2_cnc_pins.h new file mode 100755 index 00000000..4ad5c6fe --- /dev/null +++ b/aprinter/board/Stm32f2_cnc_pins.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef AMBROLIB_STM32F205_CNC_PINS_H +#define AMBROLIB_STM32F205_CNC_PINS_H + +#include + +namespace APrinter { + +/* +List of internally connected pins: + +// LEDs +PB7 + +// User button + +// USB-device +PA11 PA12 + +// USB-host +PB15 PB14 + +// SDIO +PA15 PD2 PC12 PC11 PC10 PC9 PC8 + +// LCD + +// I2C +PB8 PB9 + +// Oscillator +PH0 PH1 + +// ST-LINK +PA13 PA14 + +*/ + +} + +#endif diff --git a/aprinter/hal/stm32/Stm32f2Adc.h b/aprinter/hal/stm32/Stm32f2Adc.h new file mode 100755 index 00000000..914df76d --- /dev/null +++ b/aprinter/hal/stm32/Stm32f2Adc.h @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef AMBROLIB_STM32F2_ADC_H +#define AMBROLIB_STM32F2_ADC_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace APrinter { + +#define STM32F2ADC_DEFINE_SUBADC(AdcDefName, AdcNumber, DmaNumber, DmaStreamNumber, DmaChannelNumber) \ +struct AdcDefName { \ + using Number = WrapInt; \ + static void adc_clk_enable () { __HAL_RCC_ADC##AdcNumber##_CLK_ENABLE(); } \ + static void adc_clk_disable () { __HAL_RCC_ADC##AdcNumber##_CLK_DISABLE(); } \ + static ADC_TypeDef * adc () { return ADC##AdcNumber; } \ + static void dma_clk_enable () { __HAL_RCC_DMA##DmaNumber##_CLK_ENABLE(); } \ + static DMA_Stream_TypeDef * dma_stream () { return DMA##DmaNumber##_Stream##DmaStreamNumber; } \ + static uint32_t const DmaChannelSelection = DMA_CHANNEL_##DmaChannelNumber; \ +}; + +template +class Stm32f2Adc { + using Context = typename Arg::Context; + using ParentObject = typename Arg::ParentObject; + using ParamsPinsList = typename Arg::PinsList; + using Params = typename Arg::Params; + + static int const ClockDivider = Params::ClockDivider; + static int const SampleTimeSelection = Params::SampleTimeSelection; + + static_assert(ClockDivider == 2 || ClockDivider == 4 || ClockDivider == 6 || ClockDivider == 8, ""); + static_assert(SampleTimeSelection >= 0 && SampleTimeSelection <= 7, ""); + + AMBRO_DECLARE_GET_MEMBER_TYPE_FUNC(GetMemberType_Number, Number) + AMBRO_DECLARE_GET_MEMBER_TYPE_FUNC(GetMemberType_NumAdcPinsWrapped, NumAdcPinsWrapped) + + template + struct AdcMapping { + using AdcList = TAdcList; + static int const InputNumber = TInputNumber; + }; + + template + using AdcNumbers = MakeTypeList...>; + +#if defined(STM32F205xx) + STM32F2ADC_DEFINE_SUBADC(AdcDef1, 1, 2, 0, 0) + STM32F2ADC_DEFINE_SUBADC(AdcDef2, 2, 2, 2, 1) + STM32F2ADC_DEFINE_SUBADC(AdcDef3, 3, 2, 1, 2) + using AdcDefList = MakeTypeList; + using PinDefList = MakeTypeList< + TypeDictEntry, AdcMapping, 0>>, + TypeDictEntry, AdcMapping, 1>>, + TypeDictEntry, AdcMapping, 2>>, + TypeDictEntry, AdcMapping, 3>>, + TypeDictEntry, AdcMapping, 4>>, + TypeDictEntry, AdcMapping, 5>>, + TypeDictEntry, AdcMapping, 6>>, + TypeDictEntry, AdcMapping, 7>>, + TypeDictEntry, AdcMapping, 8>>, + TypeDictEntry, AdcMapping, 9>>, + TypeDictEntry, AdcMapping, 10>>, + TypeDictEntry, AdcMapping, 11>>, + TypeDictEntry, AdcMapping, 12>>, + TypeDictEntry, AdcMapping, 13>>, + TypeDictEntry, AdcMapping, 14>>, + TypeDictEntry, AdcMapping, 15>> + >; +#else +#error Chip not supported by Stm32f2Adc +#endif + + template + using GetAdcIndexForNumber = TypeListIndexMapped; + + static int const MaxPinsPerAdc = 16; + static int const AdcPrescalerCode = (ClockDivider / 2) - 1; + +public: + struct Object; + +private: + using TheDebugObject = DebugObject; + + // We assign the requested pins (ParamsPinsList) to the ADCs in a greedy manner. + // This means that we go through the pins in order, and assign each pin to the + // first ADC which can use this pin as input and does not yet have all 16 inputs + // assigned. + // Sometime we may want to extend this to allow the user to specify the + // assignments. Because the greedy algorithm mail fail to assign all pins even + // though a solution exists. + + template + struct AssignPin { + using PinDef = TypeListGet; + using PrevAssignments = typename AssignPin<(PinIndex - 1)>::Assignments; + using PinMappingFindRes = TypeDictFind; + static_assert(PinMappingFindRes::Found, "Invalid pin specified for ADC"); + using PinMapping = typename PinMappingFindRes::Result; + using PossibleAdcIndices = MapTypeList>; + template using CanUseAdc = WrapBool<(TypeListLength>::Value < MaxPinsPerAdc)>; + using AssignFindRes = TypeListFindMapped, WrapBool>; + static_assert(AssignFindRes::Found, "No ADC available to assign pin to"); + static int const AssignedAdcIndex = TypeListGet::Value; + template using AssignmentsForAdc = If< + (AdcIndex == AssignedAdcIndex), + ConsTypeList, TypeListGet>, + TypeListGet + >; + using Assignments = IndexElemList; + }; + + template + struct AssignPin<-1, Dummy> { + template using AssignmentsForAdc = EmptyTypeList; + using Assignments = IndexElemList; + }; + + using PinAssignments = typename AssignPin<(TypeListLength::Value - 1)>::Assignments; + + template + struct Adc { + using AdcDef = TypeListGet; + using AssignedPinIndices = TypeListGet; + static int const NumAdcPins = TypeListLength::Value; + static_assert(NumAdcPins <= MaxPinsPerAdc, ""); + using NumAdcPinsWrapped = WrapInt; + + static void init (Context c) + { + auto *o = Object::self(c); + + AdcDef::dma_clk_enable(); + AdcDef::adc_clk_enable(); + + o->dma = DMA_HandleTypeDef(); + o->dma.Instance = AdcDef::dma_stream(); + o->dma.Init.Channel = AdcDef::DmaChannelSelection; + o->dma.Init.Direction = DMA_PERIPH_TO_MEMORY; + o->dma.Init.PeriphInc = DMA_PINC_DISABLE; + o->dma.Init.MemInc = DMA_MINC_ENABLE; + o->dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + o->dma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + o->dma.Init.Mode = DMA_CIRCULAR; + o->dma.Init.Priority = DMA_PRIORITY_HIGH; + o->dma.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&o->dma) != HAL_OK) { + AMBRO_ASSERT_ABORT("HAL_DMA_Init failed"); + } + + AdcDef::adc()->CR1 = ADC_CR1_SCAN | ADC_CR1_OVRIE; + AdcDef::adc()->CR2 = ADC_CR2_CONT | ADC_CR2_DMA | ADC_CR2_DDS | ADC_CR2_EOCS; + AdcDef::adc()->SMPR1 = 0; + AdcDef::adc()->SMPR2 = 0; + AdcDef::adc()->SQR1 = (uint32_t)(NumAdcPins - 1) << 20; + AdcDef::adc()->SQR2 = 0; + AdcDef::adc()->SQR3 = 0; + AdcDef::adc()->JSQR = 0; + + ListFor([&] APRINTER_TL(pin, pin::init(c))); + + AdcDef::adc()->CR2 |= ADC_CR2_ADON; + } + + static void start (Context c) + { + auto *o = Object::self(c); + + HAL_DMA_Abort(&o->dma); + + if (HAL_DMA_Start(&o->dma, (uint32_t)&AdcDef::adc()->DR, (uint32_t)&o->adc_values, NumAdcPins) != HAL_OK) { + AMBRO_ASSERT_ABORT("HAL_DMA_Start failed"); + } + + AdcDef::adc()->SR &= ~ADC_SR_OVR; + AdcDef::adc()->CR2 |= ADC_CR2_SWSTART; + } + + static void deinit (Context c) + { + auto *o = Object::self(c); + + AdcDef::adc()->CR1 = 0; + AdcDef::adc()->CR2 = 0; + + HAL_DMA_Abort(&o->dma); + HAL_DMA_DeInit(&o->dma); + + AdcDef::adc_clk_disable(); + } + + static void handle_irq (InterruptContext c) + { + if (AdcDef::adc()->SR & ADC_SR_OVR) { + start(c); + } + } + + template + struct AdcPin { + static int const PinIndex = TypeListGet::Value; + using PinDef = TypeListGet; + using TheAssignPin = AssignPin; + static int const SqrIndex = AdcPinIndex / 6; + static int const SqrOffset = AdcPinIndex % 6; + static int const SmprIndex = AdcPinIndex / 10; + static int const SmprOffset = AdcPinIndex % 10; + + static void init (Context c) + { + Object::self(c)->adc_values[AdcPinIndex] = 0; + + Context::Pins::template setAnalog(c); + + *sqr_reg() |= (uint32_t)TheAssignPin::PinMapping::InputNumber << (5 * SqrOffset); + *smpr_reg() |= (uint32_t)SampleTimeSelection << (3 * SmprOffset); + } + + static uint32_t volatile * sqr_reg () + { + return SqrIndex == 0 ? &AdcDef::adc()->SQR3 : + SqrIndex == 1 ? &AdcDef::adc()->SQR2 : + SqrIndex == 2 ? &AdcDef::adc()->SQR1 : nullptr; + } + + static uint32_t volatile * smpr_reg () + { + return SmprIndex == 0 ? &AdcDef::adc()->SMPR2 : + SmprIndex == 1 ? &AdcDef::adc()->SMPR1 : nullptr; + } + }; + using AdcPinList = IndexElemList; + + struct Object : public ObjBase { + DMA_HandleTypeDef dma; + uint16_t adc_values[NumAdcPins]; + }; + }; + using AllAdcList = IndexElemList; + + using UsedAdcList = FilterTypeList< + AllAdcList, + ComposeFunctions< + NotFunc, + ComposeFunctions< + IsEqualFunc>, + GetMemberType_NumAdcPinsWrapped + > + > + >; + +public: + using FixedType = FixedPoint<12, false, -12>; + + static void init (Context c) + { + ADC->CCR = ((uint32_t)AdcPrescalerCode << 16); + + ListFor([&] APRINTER_TL(adc, adc::init(c))); + + NVIC_ClearPendingIRQ(ADC_IRQn); + NVIC_SetPriority(ADC_IRQn, INTERRUPT_PRIORITY); + + ListFor([&] APRINTER_TL(adc, adc::start(c))); + + memory_barrier(); + NVIC_EnableIRQ(ADC_IRQn); + + TheDebugObject::init(c); + } + + static void deinit (Context c) + { + TheDebugObject::deinit(c); + + NVIC_DisableIRQ(ADC_IRQn); + memory_barrier(); + + ListFor([&] APRINTER_TL(adc, adc::deinit(c))); + + NVIC_ClearPendingIRQ(ADC_IRQn); + } + + template + static FixedType getValue (ThisContext c) + { + TheDebugObject::access(c); + + static int const PinIndex = TypeListIndex::Value; + using PinAdc = Adc::AssignedAdcIndex>; + static int const AdcPinIndex = TypeListIndex>::Value; + auto *adc_o = PinAdc::Object::self(c); + memory_barrier_dma(); + return FixedType::importBits(((uint16_t volatile *)adc_o->adc_values)[AdcPinIndex]); + } + + static void handle_irq (InterruptContext c) + { + ListFor([&] APRINTER_TL(adc, adc::handle_irq(c))); + } + +public: + struct Object : public ObjBase + >> {}; +}; + +APRINTER_ALIAS_STRUCT_EXT(Stm32f2AdcService, ( + APRINTER_AS_VALUE(int, ClockDivider), + APRINTER_AS_VALUE(int, SampleTimeSelection) +), ( + APRINTER_ALIAS_STRUCT_EXT(Adc, ( + APRINTER_AS_TYPE(Context), + APRINTER_AS_TYPE(ParentObject), + APRINTER_AS_TYPE(PinsList) + ), ( + using Params = Stm32f2AdcService; + APRINTER_DEF_INSTANCE(Adc, Stm32f2Adc) + )) +)) + +#define APRINTER_STM32F2_ADC_GLOBAL(adc, context) \ +extern "C" \ +__attribute__((used)) \ +void ADC_IRQHandler (void) \ +{ \ + adc::handle_irq(MakeInterruptContext(context)); \ +} + +} + +#endif diff --git a/aprinter/hal/stm32/Stm32f2Clock.h b/aprinter/hal/stm32/Stm32f2Clock.h new file mode 100755 index 00000000..e2927fc8 --- /dev/null +++ b/aprinter/hal/stm32/Stm32f2Clock.h @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2013 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef AMBROLIB_STM32F2_CLOCK_H +#define AMBROLIB_STM32F2_CLOCK_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +struct Stm32f2Clock__IrqCompHelper { + static void call () {} +}; + +namespace APrinter { + +using Stm32f2ClockDefaultExtraClearance = AMBRO_WRAP_DOUBLE(0.0); + +#define STM32F2CLOCK_DEFINE_TC(tc_num, is_32bit, clock_type) \ +struct Stm32f2ClockTIM##tc_num { \ + static bool const Is32Bit = is_32bit; \ + static TIM_TypeDef * tim () { return TIM##tc_num; } \ + static int const ClockType = clock_type; \ + static void enable_clock () { __HAL_RCC_TIM##tc_num##_CLK_ENABLE(); } \ + static void disable_clock () { __HAL_RCC_TIM##tc_num##_CLK_DISABLE(); } \ + static IRQn_Type const Irq = APRINTER_JOIN(STM32F2CLOCK_IRQ_FOR_TIM##tc_num, IRQn); \ +}; + +// Note: these have _ at the end so that TIMn macros don't get in the way. +#define STM32F2CLOCK_IRQ_FOR_TIM1 TIM1_CC_ +#define STM32F2CLOCK_IRQ_FOR_TIM2 TIM2_ +#define STM32F2CLOCK_IRQ_FOR_TIM3 TIM3_ +#define STM32F2CLOCK_IRQ_FOR_TIM4 TIM4_ +#define STM32F2CLOCK_IRQ_FOR_TIM5 TIM5_ +#define STM32F2CLOCK_IRQ_FOR_TIM8 TIM8_CC_ +#define STM32F2CLOCK_IRQ_FOR_TIM9 TIM1_BRK_TIM9_ +#define STM32F2CLOCK_IRQ_FOR_TIM10 TIM1_UP_TIM10_ +#define STM32F2CLOCK_IRQ_FOR_TIM11 TIM1_TRG_COM_TIM11_ +#define STM32F2CLOCK_IRQ_FOR_TIM12 TIM8_BRK_TIM12_ +#define STM32F2CLOCK_IRQ_FOR_TIM13 TIM8_UP_TIM13_ +#define STM32F2CLOCK_IRQ_FOR_TIM14 TIM8_TRG_COM_TIM14_ + +// Some timers we don't support: +// - APB2 timers, because they are based on a different clock (could try prescaler adjustment). +//STM32F2CLOCK_DEFINE_TC(1, false, 2) +STM32F2CLOCK_DEFINE_TC(2, true, 1) +STM32F2CLOCK_DEFINE_TC(3, false, 1) +STM32F2CLOCK_DEFINE_TC(4, false, 1) +STM32F2CLOCK_DEFINE_TC(5, true, 1) +//STM32F2CLOCK_DEFINE_TC(8, false, 2) +//STM32F2CLOCK_DEFINE_TC(9, false, 2) +//STM32F2CLOCK_DEFINE_TC(10, false, 2) +//STM32F2CLOCK_DEFINE_TC(11, false, 2) +STM32F2CLOCK_DEFINE_TC(12, false, 1) +STM32F2CLOCK_DEFINE_TC(13, false, 1) +STM32F2CLOCK_DEFINE_TC(14, false, 1) + +#define STM32F2CLOCK_DEFINE_COMP(comp_num, ccmr_num, ccmr_bit_offset, ccer_bit_offset, ccie_bit, if_bit) \ +struct Stm32f2ClockComp##comp_num { \ + static uint32_t volatile * ccmr (TIM_TypeDef *tim) { return &tim->CCMR##ccmr_num; } \ + static int const CcmrBitOffset = ccmr_bit_offset; \ + static int const CcerBitOffset = ccer_bit_offset; \ + static uint32_t volatile * ccr (TIM_TypeDef *tim) { return &tim->CCR##comp_num; } \ + static uint32_t const CcieBit = ccie_bit; \ + static uint32_t const IfBit = if_bit; \ +}; + +STM32F2CLOCK_DEFINE_COMP(1, 1, 0, 0, TIM_DIER_CC1IE, TIM_SR_CC1IF) +STM32F2CLOCK_DEFINE_COMP(2, 1, 8, 4, TIM_DIER_CC2IE, TIM_SR_CC2IF) +STM32F2CLOCK_DEFINE_COMP(3, 2, 0, 8, TIM_DIER_CC3IE, TIM_SR_CC3IF) +STM32F2CLOCK_DEFINE_COMP(4, 2, 8, 12, TIM_DIER_CC4IE, TIM_SR_CC4IF) + +template +class Stm32f2Clock { + using Context = typename Arg::Context; + using ParentObject = typename Arg::ParentObject; + using TcsList = typename Arg::TcsList; + using Params = typename Arg::Params; + + static uint16_t const Prescale = Params::Prescale; + + static_assert(TypeListLength::Value > 0, "Need at least one timer."); + static_assert(TypeListGet::Is32Bit, "First timer must be 32-bit."); + static_assert(TypeListGet::ClockType == 1, "First timer must be APB1-clocked"); + +public: + struct Object; + using TimeType = uint32_t; + + static constexpr TimeType prescale_divide = (TimeType)Prescale + 1; + static constexpr double apb1_timers_freq = F_CPU / APB1_TIMERS_DIV; + + static constexpr double time_unit = (double)prescale_divide / apb1_timers_freq; + static constexpr double time_freq = (double)apb1_timers_freq / prescale_divide; + +private: + using TheDebugObject = DebugObject; + + template + struct MyTc { + static int const TcIndex = TTcIndex; + using TcSpec = TypeListGet; + + static void init (Context c) + { + TcSpec::enable_clock(); + TcSpec::tim()->CR1 = 0; + TcSpec::tim()->CR2 = 0; + TcSpec::tim()->SMCR = 0; + TcSpec::tim()->DIER = 0; + TcSpec::tim()->SR = 0; + TcSpec::tim()->CCMR1 = 0; + TcSpec::tim()->CCMR2 = 0; + TcSpec::tim()->CCER = 0; + TcSpec::tim()->PSC = Prescale; + TcSpec::tim()->ARR = TcSpec::Is32Bit ? UINT32_MAX : UINT16_MAX; + TcSpec::tim()->EGR = TIM_EGR_UG; + TcSpec::tim()->CNT = (TcIndex == 0); + NVIC_ClearPendingIRQ(TcSpec::Irq); + NVIC_SetPriority(TcSpec::Irq, INTERRUPT_PRIORITY); + NVIC_EnableIRQ(TcSpec::Irq); + } + + static void init_start (Context c) + { + TcSpec::tim()->CR1 = TIM_CR1_CEN; + } + + static void deinit (Context c) + { + NVIC_DisableIRQ(TcSpec::Irq); + TcSpec::tim()->CR1 = 0; + TcSpec::tim()->SR = 0; + NVIC_ClearPendingIRQ(TcSpec::Irq); + TcSpec::disable_clock(); + } + + static void irq_handler (InterruptContext c) + { + // Ack interrupts. + TcSpec::tim()->SR = 0; + + Stm32f2Clock__IrqCompHelper::call(); + Stm32f2Clock__IrqCompHelper::call(); + Stm32f2Clock__IrqCompHelper::call(); + Stm32f2Clock__IrqCompHelper::call(); + } + }; + + using MyTcsList = IndexElemList; + + template + using FindTc = MyTc::Value>; + +public: + static void init (Context c) + { + ListFor([&] APRINTER_TL(tc, tc::init(c))); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + ListFor([&] APRINTER_TL(tc, tc::init_start(c))); + } + + TheDebugObject::init(c); + } + + static void deinit (Context c) + { + TheDebugObject::deinit(c); + + ListForReverse([&] APRINTER_TL(tc, tc::deinit(c))); + } + + template + static TimeType getTime (ThisContext c) + { + TheDebugObject::access(c); + + return MyTc<0>::TcSpec::tim()->CNT; + } + + template + static void tc_irq_handler (InterruptContext c) + { + FindTc::irq_handler(c); + } + +public: + struct Object : public ObjBase> {}; +}; + +APRINTER_ALIAS_STRUCT_EXT(Stm32f2ClockService, ( + APRINTER_AS_VALUE(uint16_t, Prescale) +), ( + APRINTER_ALIAS_STRUCT_EXT(Clock, ( + APRINTER_AS_TYPE(Context), + APRINTER_AS_TYPE(ParentObject), + APRINTER_AS_TYPE(TcsList) + ), ( + using Params = Stm32f2ClockService; + APRINTER_DEF_INSTANCE(Clock, Stm32f2Clock) + )) +)) + +#define AMBRO_STM32F2_CLOCK_TC_GLOBAL(tc_num, clock, context) \ +extern "C" \ +__attribute__((used)) \ +void APRINTER_JOIN(STM32F2CLOCK_IRQ_FOR_TIM##tc_num, IRQHandler) (void) \ +{ \ + clock::tc_irq_handler(MakeInterruptContext((context))); \ +} + +template +class Stm32f2ClockInterruptTimer { + using Context = typename Arg::Context; + using ParentObject = typename Arg::ParentObject; + using Handler = typename Arg::Handler; + using Params = typename Arg::Params; + +public: + struct Object; + using Clock = typename Context::Clock; + using TimeType = typename Clock::TimeType; + using HandlerContext = InterruptContext; + using TcSpec = typename Params::Tc; + using Comp = typename Params::Comp; + using ExtraClearance = typename Params::ExtraClearance; + +private: + using TheDebugObject = DebugObject; + +public: + static void init (Context c) + { + auto *o = Object::self(c); + TheDebugObject::init(c); + +#ifdef AMBROLIB_ASSERTIONS + o->m_running = false; +#endif + + // Setup the channel. But, it's not strictly needed because the + // appropriate bits need to just be zerod and they already were + // when we did the Clock initialization. + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + *ccmr_reg() = (*ccmr_reg() & ~((uint32_t)255 << Comp::CcmrBitOffset)) | ((uint32_t)0 << Comp::CcmrBitOffset); + TcSpec::tim()->CCER = (TcSpec::tim()->CCER & ~((uint32_t)15 << Comp::CcerBitOffset)) | ((uint32_t)0 << Comp::CcerBitOffset); + } + } + + static void deinit (Context c) + { + TheDebugObject::deinit(c); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + TcSpec::tim()->DIER &= ~Comp::CcieBit; + } + + memory_barrier(); + } + + template + static void setFirst (ThisContext c, TimeType time) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(!o->m_running) + AMBRO_ASSERT(!(TcSpec::tim()->DIER & Comp::CcieBit)) + + o->m_time = time; +#ifdef AMBROLIB_ASSERTIONS + o->m_running = true; +#endif + memory_barrier(); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + *ccr_reg() = adjust_set_time(time); + TcSpec::tim()->DIER |= Comp::CcieBit; + } + } + + static void setNext (HandlerContext c, TimeType time) + { + auto *o = Object::self(c); + AMBRO_ASSERT(o->m_running) + AMBRO_ASSERT(TcSpec::tim()->DIER & Comp::CcieBit) + + o->m_time = time; + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + *ccr_reg() = adjust_set_time(time); + } + } + + template + static void unset (ThisContext c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + TcSpec::tim()->DIER &= ~Comp::CcieBit; + } + + memory_barrier(); + +#ifdef AMBROLIB_ASSERTIONS + o->m_running = false; +#endif + } + + template + static TimeType getLastSetTime (ThisContext c) + { + auto *o = Object::self(c); + + return o->m_time; + } + + static void irq_handler (InterruptContext c) + { + auto *o = Object::self(c); + + if (!(TcSpec::tim()->DIER & Comp::CcieBit)) { + return; + } + + AMBRO_ASSERT(o->m_running) + + TimeType now = Clock::template MyTc<0>::TcSpec::tim()->CNT; + now -= o->m_time; + + if (now < UINT32_C(0x80000000)) { + if (!Handler::call(c)) { +#ifdef AMBROLIB_ASSERTIONS + o->m_running = false; +#endif + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + TcSpec::tim()->DIER &= ~Comp::CcieBit; + } + } + } + } + +private: + static uint32_t volatile * ccr_reg (void) + { + return Comp::ccr(TcSpec::tim()); + } + + static uint32_t volatile * ccmr_reg (void) + { + return Comp::ccmr(TcSpec::tim()); + } + + AMBRO_ALWAYS_INLINE + static TimeType adjust_set_time (TimeType time) + { + TimeType now = Clock::template MyTc<0>::TcSpec::tim()->CNT; + now -= time; + now += clearance; + if (now < UINT32_C(0x80000000)) { + time += now; + } + return time; + } + + static const TimeType clearance = MaxValue((64 / Clock::prescale_divide) + 2, ExtraClearance::value() * Clock::time_freq); + +public: + struct Object : public ObjBase> { + TimeType m_time; +#ifdef AMBROLIB_ASSERTIONS + bool m_running; +#endif + }; +}; + +APRINTER_ALIAS_STRUCT_EXT(Stm32f2ClockInterruptTimerService, ( + APRINTER_AS_TYPE(Tc), + APRINTER_AS_TYPE(Comp), + APRINTER_AS_TYPE(ExtraClearance) +), ( + APRINTER_ALIAS_STRUCT_EXT(InterruptTimer, ( + APRINTER_AS_TYPE(Context), + APRINTER_AS_TYPE(ParentObject), + APRINTER_AS_TYPE(Handler) + ), ( + using Params = Stm32f2ClockInterruptTimerService; + APRINTER_DEF_INSTANCE(InterruptTimer, Stm32f2ClockInterruptTimer) + )) +)) + +#define AMBRO_STM32F2_CLOCK_INTERRUPT_TIMER_GLOBAL(tcspec, comp, timer, context) \ +static_assert( \ + TypesAreEqual::Value && \ + TypesAreEqual::Value, \ + "Incorrect INTERRUPT_TIMER_GLOBA macro used" \ +); \ +template <> \ +struct Stm32f2Clock__IrqCompHelper { \ + static void call () \ + { \ + timer::irq_handler(MakeInterruptContext((context))); \ + } \ +}; + +} + +#endif diff --git a/aprinter/hal/stm32/Stm32f2Pins.h b/aprinter/hal/stm32/Stm32f2Pins.h new file mode 100755 index 00000000..78f7524e --- /dev/null +++ b/aprinter/hal/stm32/Stm32f2Pins.h @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2013 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef AMBROLIB_STM32F2_PINS_H +#define AMBROLIB_STM32F2_PINS_H + +#include + +#include +#include +#include +#include +#include + +namespace APrinter { + +template +struct Stm32f2Port { + static GPIO_TypeDef * gpio () { return (GPIO_TypeDef *)TGpioAddr; } +}; + +using Stm32f2PortA = Stm32f2Port; +using Stm32f2PortB = Stm32f2Port; +using Stm32f2PortC = Stm32f2Port; +using Stm32f2PortD = Stm32f2Port; +#ifdef GPIOE +using Stm32f2PortE = Stm32f2Port; +#endif +#ifdef GPIOF +using Stm32f2PortF = Stm32f2Port; +#endif +#ifdef GPIOG +using Stm32f2PortG = Stm32f2Port; +#endif +using Stm32f2PortH = Stm32f2Port; +#ifdef GPIOI +using Stm32f2PortI = Stm32f2Port; +#endif +#ifdef GPIOJ +using Stm32f2PortJ = Stm32f2Port; +#endif +#ifdef GPIOK +using Stm32f2PortK = Stm32f2Port; +#endif + +template +struct Stm32f2Pin { + using Port = TPort; + static const int PinIndex = TPinIndex; +}; + +template +struct Stm32f2PinPullMode { + static uint8_t const Pupdr = TPupdr; +}; +using Stm32f2PinPullModeNone = Stm32f2PinPullMode<0>; +using Stm32f2PinPullModePullUp = Stm32f2PinPullMode<1>; +using Stm32f2PinPullModePullDown = Stm32f2PinPullMode<2>; + +template +struct Stm32f2PinOutputType { + static uint8_t const Optyper = TOptyper; +}; +using Stm32f2PinOutputTypeNormal = Stm32f2PinOutputType<0>; +using Stm32f2PinOutputTypeOpenDrain = Stm32f2PinOutputType<1>; + +template +struct Stm32f2PinOutputSpeed { + static uint8_t const Ospeedr = TOspeedr; +}; +using Stm32f2PinOutputSpeedLow = Stm32f2PinOutputSpeed<0>; +using Stm32f2PinOutputSpeedMedium = Stm32f2PinOutputSpeed<1>; +using Stm32f2PinOutputSpeedFast = Stm32f2PinOutputSpeed<2>; +using Stm32f2PinOutputSpeedHigh = Stm32f2PinOutputSpeed<3>; + +template +struct Stm32f2PinInputMode { + static uint8_t const Pupdr = PullMode::Pupdr; +}; +using Stm32f2PinInputModeNormal = Stm32f2PinInputMode; +using Stm32f2PinInputModePullUp = Stm32f2PinInputMode; +using Stm32f2PinInputModePullDown = Stm32f2PinInputMode; + +template +struct Stm32f2PinOutputMode { + static uint8_t const Optyper = OutputType::Optyper; + static uint8_t const Ospeedr = OutputSpeed::Ospeedr; + static uint8_t const Pupdr = PullMode::Pupdr; +}; +using Stm32f2PinOutputModeNormal = Stm32f2PinOutputMode; +using Stm32f2PinOutputModeOpenDrain = Stm32f2PinOutputMode; + +template +class Stm32f2Pins { + using Context = typename Arg::Context; + using ParentObject = typename Arg::ParentObject; + +public: + struct Object; + +private: + using TheDebugObject = DebugObject; + +public: + static void init (Context c) + { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); +#ifdef GPIOF + __HAL_RCC_GPIOF_CLK_ENABLE(); +#endif +#ifdef GPIOG + __HAL_RCC_GPIOG_CLK_ENABLE(); +#endif + __HAL_RCC_GPIOH_CLK_ENABLE(); +#ifdef GPIOI + __HAL_RCC_GPIOI_CLK_ENABLE(); +#endif +#ifdef GPIOJ + __HAL_RCC_GPIOJ_CLK_ENABLE(); +#endif +#ifdef GPIOK + __HAL_RCC_GPIOK_CLK_ENABLE(); +#endif + + TheDebugObject::init(c); + } + + static void deinit (Context c) + { + TheDebugObject::deinit(c); + +#ifdef GPIOK + __HAL_RCC_GPIOK_CLK_DISABLE(); +#endif +#ifdef GPIOJ + __HAL_RCC_GPIOJ_CLK_DISABLE(); +#endif +#ifdef GPIOI + __HAL_RCC_GPIOI_CLK_DISABLE(); +#endif + __HAL_RCC_GPIOH_CLK_DISABLE(); +#ifdef GPIOG + __HAL_RCC_GPIOG_CLK_DISABLE(); +#endif +#ifdef GPIOF + __HAL_RCC_GPIOF_CLK_DISABLE(); +#endif + __HAL_RCC_GPIOE_CLK_DISABLE(); + __HAL_RCC_GPIOD_CLK_DISABLE(); + __HAL_RCC_GPIOC_CLK_DISABLE(); + __HAL_RCC_GPIOB_CLK_DISABLE(); + __HAL_RCC_GPIOA_CLK_DISABLE(); + } + + template + static void setInput (ThisContext c) + { + TheDebugObject::access(c); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + set_pupdr(); + set_moder(); + } + } + + template + static void setOutput (ThisContext c) + { + TheDebugObject::access(c); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + set_pupdr(); + set_optyper(); + set_ospeedr(); + set_moder(); + } + } + + template + static void setAlternateFunction (ThisContext c) + { + TheDebugObject::access(c); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + set_pupdr(); + set_optyper(); + set_ospeedr(); + set_af(); + set_moder(); + } + } + + template + static void setAnalog (ThisContext c) + { + TheDebugObject::access(c); + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + set_pupdr(); + set_moder(); + } + } + + template + static bool get (ThisContext c) + { + TheDebugObject::access(c); + + return (Pin::Port::gpio()->IDR & (UINT32_C(1) << Pin::PinIndex)); + } + + template + static void set (ThisContext c, bool x) + { + TheDebugObject::access(c); + + if (x) { + Pin::Port::gpio()->BSRR = (UINT32_C(1) << Pin::PinIndex); + } else { + Pin::Port::gpio()->BSRR = (UINT32_C(1) << (16 + Pin::PinIndex)); + } + } + + template + static void emergencySet (bool x) + { + if (x) { + Pin::Port::gpio()->BSRR = (UINT32_C(1) << Pin::PinIndex); + } else { + Pin::Port::gpio()->BSRR = (UINT32_C(1) << (16 + Pin::PinIndex)); + } + } + +private: + template + static void set_moder () + { + Pin::Port::gpio()->MODER = set_bits(Pin::Port::gpio()->MODER, 2 * Pin::PinIndex, 2, Value); + } + + template + static void set_pupdr () + { + Pin::Port::gpio()->PUPDR = set_bits(Pin::Port::gpio()->PUPDR, 2 * Pin::PinIndex, 2, Value); + } + + template + static void set_optyper () + { + Pin::Port::gpio()->OTYPER = set_bits(Pin::Port::gpio()->OTYPER, Pin::PinIndex, 1, Value); + } + + template + static void set_ospeedr () + { + Pin::Port::gpio()->OSPEEDR = set_bits(Pin::Port::gpio()->OSPEEDR, 2 * Pin::PinIndex, 2, Value); + } + + template + static void set_af () + { + Pin::Port::gpio()->AFR[Pin::PinIndex / 8] = set_bits(Pin::Port::gpio()->AFR[Pin::PinIndex / 8], 4 * (Pin::PinIndex % 8), 4, Value); + } + + static uint32_t set_bits (uint32_t orig, int offset, int bits, uint32_t val) + { + return (orig & (uint32_t)~(((uint32_t)-1 >> (32 - bits)) << offset)) | (uint32_t)(val << offset); + } + +public: + struct Object : public ObjBase> {}; +}; + +struct Stm32f2PinsService { + APRINTER_ALIAS_STRUCT_EXT(Pins, ( + APRINTER_AS_TYPE(Context), + APRINTER_AS_TYPE(ParentObject) + ), ( + APRINTER_DEF_INSTANCE(Pins, Stm32f2Pins) + )) +}; + +} + +#endif diff --git a/aprinter/hal/stm32/Stm32f2Sdio.h b/aprinter/hal/stm32/Stm32f2Sdio.h new file mode 100755 index 00000000..2dd02ba4 --- /dev/null +++ b/aprinter/hal/stm32/Stm32f2Sdio.h @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef APRINTER_STM32F2SDIO_H +#define APRINTER_STM32F2SDIO_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace APrinter { + +template +class Stm32f2Sdio { + using Context = typename Arg::Context; + using ParentObject = typename Arg::ParentObject; + using CommandHandler = typename Arg::CommandHandler; + using BusyTimeout = typename Arg::BusyTimeout; + using Params = typename Arg::Params; + +public: + struct Object; + +private: + static_assert(Params::SdClockPrescaler >= 0 && Params::SdClockPrescaler <= 255, ""); + + using TheClockUtils = ClockUtils; + using TheDebugObject = DebugObject; + using FastEvent = typename Context::EventLoop::template FastEventSpec; + + enum {INIT_STATE_OFF, INIT_STATE_POWERON, INIT_STATE_ON}; + enum {CMD_STATE_READY, CMD_STATE_BUSY, CMD_STATE_WAIT_BUSY}; + enum {DATA_STATE_READY, DATA_STATE_WAIT_COMPL, DATA_STATE_WAIT_RXTX, DATA_STATE_WAIT_DMA}; + + static int const SdPinsAF = 12; + using SdPinsMode = Stm32f2PinOutputMode; + + using SdPinCK = Stm32f2Pin; + using SdPinCmd = Stm32f2Pin; + using SdPinD0 = Stm32f2Pin; + using SdPinD1 = Stm32f2Pin; + using SdPinD2 = Stm32f2Pin; + using SdPinD3 = Stm32f2Pin; + + static SDIO_TypeDef * sdio () { return SDIO; } + + static typename TheClockUtils::TimeType const DmaTimeoutTicks = 0.5 * TheClockUtils::time_freq; + static typename TheClockUtils::TimeType const BusyTimeoutTicks = BusyTimeout::value() * TheClockUtils::time_freq; + +public: + static bool const IsWideMode = Params::IsWideMode; + static size_t const BlockSize = 512; + static size_t const MaxIoBlocks = -1; + static int const MaxIoDescriptors = INT_MAX; + + static void init (Context c) + { + auto *o = Object::self(c); + + Context::Pins::template setAlternateFunction(c); + Context::Pins::template setAlternateFunction(c); + Context::Pins::template setAlternateFunction(c); + if (IsWideMode) { + Context::Pins::template setAlternateFunction(c); + Context::Pins::template setAlternateFunction(c); + Context::Pins::template setAlternateFunction(c); + } + + Context::EventLoop::template initFastEvent(c, Stm32f2Sdio::event_handler); + + NVIC_DisableIRQ(SDIO_IRQn); + NVIC_SetPriority(SDIO_IRQn, INTERRUPT_PRIORITY-1); + + o->init_state = INIT_STATE_OFF; + + TheDebugObject::init(c); + } + + static void deinit (Context c) + { + TheDebugObject::deinit(c); + + reset_internal(c); + } + + static void reset (Context c) + { + TheDebugObject::access(c); + + reset_internal(c); + } + + static void startPowerOn (Context c, SdioIface::InterfaceParams if_params) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(o->init_state == INIT_STATE_OFF) + + msp_init(c); + + configure_interface(if_params); + + __SDIO_DISABLE(); + + SDIO_PowerState_ON(sdio()); + + o->init_state = INIT_STATE_POWERON; + } + + static void completePowerOn (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(o->init_state == INIT_STATE_POWERON) + + __SDIO_ENABLE(); + + o->init_state = INIT_STATE_ON; + o->pending = false; + o->cmd_state = CMD_STATE_READY; + o->data_state = DATA_STATE_READY; + } + + static void reconfigureInterface (Context c, SdioIface::InterfaceParams if_params) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(o->init_state == INIT_STATE_ON) + AMBRO_ASSERT(!o->pending) + AMBRO_ASSERT(o->cmd_state == CMD_STATE_READY) + AMBRO_ASSERT(o->data_state == DATA_STATE_READY) + + configure_interface(if_params); + } + + static void startCommand (Context c, SdioIface::CommandParams cmd_params) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(o->init_state == INIT_STATE_ON) + AMBRO_ASSERT(!o->pending) + AMBRO_ASSERT(o->cmd_state == CMD_STATE_READY) + AMBRO_ASSERT(o->data_state == DATA_STATE_READY) + + o->data_dir = cmd_params.direction; + + if (cmd_params.direction != SdioIface::DATA_DIR_NONE) { + AMBRO_ASSERT(cmd_params.direction == SdioIface::DATA_DIR_READ || cmd_params.direction == SdioIface::DATA_DIR_WRITE) + AMBRO_ASSERT(cmd_params.num_blocks >= 1) + AMBRO_ASSERT(cmd_params.num_blocks <= MaxIoBlocks) + AMBRO_ASSERT(CheckTransferVector(cmd_params.data_vector, cmd_params.num_blocks * (size_t)(BlockSize/4))) + + o->data_num_blocks = cmd_params.num_blocks; + o->data_vector = cmd_params.data_vector; + + if (cmd_params.direction == SdioIface::DATA_DIR_READ) { + start_data(c); + } + } + + sdio()->ICR = SDIO_FLAG_CMDSENT|SDIO_FLAG_CCRCFAIL|SDIO_FLAG_CTIMEOUT|SDIO_FLAG_CMDREND; + + uint32_t response_sdio; + switch (cmd_params.response_type) { + case SdioIface::RESPONSE_NONE: + response_sdio = SDIO_RESPONSE_NO; break; + case SdioIface::RESPONSE_SHORT: + case SdioIface::RESPONSE_SHORT_BUSY: + response_sdio = SDIO_RESPONSE_SHORT; break; + case SdioIface::RESPONSE_LONG: + response_sdio = SDIO_RESPONSE_LONG; break; + default: + AMBRO_ASSERT(0); + } + + SDIO_CmdInitTypeDef cmd = SDIO_CmdInitTypeDef(); + cmd.Argument = cmd_params.argument; + cmd.CmdIndex = cmd_params.cmd_index; + cmd.Response = response_sdio; + cmd.WaitForInterrupt = SDIO_WAIT_NO; + cmd.CPSM = SDIO_CPSM_ENABLE; + SDIO_SendCommand(sdio(), &cmd); + + o->cmd_state = CMD_STATE_BUSY; + o->cmd_index = cmd_params.cmd_index; + o->cmd_response_type = cmd_params.response_type; + o->cmd_flags = cmd_params.flags; + o->pending = true; + o->results = SdioIface::CommandResults{SdioIface::CMD_ERROR_NONE}; + o->data_error = SdioIface::DATA_ERROR_NONE; + + Context::EventLoop::template triggerFastEvent(c); + } + + // This interrupt is called when we can transfer at least 8 words + // from the FIFO (read) or into the FIFO (write). It must be fast! + AMBRO_ALWAYS_INLINE + static void sdio_irq (InterruptContext c) + { + auto *o = Object::self(c); + //AMBRO_ASSERT(o->data_dir == SdioIface::DATA_DIR_READ || o->data_dir == SdioIface::DATA_DIR_WRITE) + //AMBRO_ASSERT(o->descriptor_index < o->data_vector.num_descriptors) + //AMBRO_ASSERT(o->buffer_ptr[0] != o->buffer_ptr[1]) + + // Fetch the current buffer pointers. + uint32_t *buffer_ptr0 = o->buffer_ptr[0]; + uint32_t *buffer_ptr1 = o->buffer_ptr[1]; + + // Compute the difference between the addresses. + // The sign of this determined whether we are reading or writing. + uint32_t buffer_diff = (char *)buffer_ptr1 - (char *)buffer_ptr0; + + // Note that while we will be doing the transfers, we could get a positive + // edges of the RXFIFOHF/TXFIFOHE flag, but anyway end up up with the + // flag cleared. Due to the edge the NVIC would immediately reschedule + // the interrupt, and we could then run without sufficient data/space in + // the FIFO. So we will use NVIC_ClearPendingIRQ before allowing another + // interrupt to fire. + + if (buffer_diff < UINT32_C(0x80000000)) { + // We are reading - buffer_diff is the number of bytes left. + + // Read words. + if (AMBRO_LIKELY(buffer_diff >= 32)) { + uint32_t fifo_out; + asm( + "ldmia %[fifo]!, {r4, r5, r6, r7}\n" + "stmia %[buffer_ptr0]!, {r4, r5, r6, r7}\n" + "ldmia %[fifo]!, {r4, r5, r6, r7}\n" + "stmia %[buffer_ptr0]!, {r4, r5, r6, r7}\n" + : [buffer_ptr0] "=&r" (buffer_ptr0), + [fifo] "=&r" (fifo_out) + : "[buffer_ptr0]" (buffer_ptr0), + "[fifo]" (&sdio()->FIFO) + : "r4", "r5", "r6", "r7", "memory" + ); + } else { + int rem_words = buffer_diff / 4; + int i = 0; + do { + buffer_ptr0[i++] = sdio()->FIFO; + } while (i < rem_words); + buffer_ptr0 = buffer_ptr1; + } + + // More bytes in buffer? + if (AMBRO_LIKELY(buffer_ptr0 < buffer_ptr1)) { + o->buffer_ptr[0] = buffer_ptr0; + NVIC_ClearPendingIRQ(SDIO_IRQn); + return; + } + } else { + // We are writing - negate buffer_diff to get the number of bytes left. + buffer_diff = -buffer_diff; + + // Write words. + if (AMBRO_LIKELY(buffer_diff >= 32)) { + uint32_t fifo_out; + asm( + "ldmia %[buffer_ptr1]!, {r4, r5, r6, r7}\n" + "stmia %[fifo]!, {r4, r5, r6, r7}\n" + "ldmia %[buffer_ptr1]!, {r4, r5, r6, r7}\n" + "stmia %[fifo]!, {r4, r5, r6, r7}\n" + : [buffer_ptr1] "=&r" (buffer_ptr1), + [fifo] "=&r" (fifo_out) + : "[buffer_ptr1]" (buffer_ptr1), + "[fifo]" (&sdio()->FIFO) + : "r4", "r5", "r6", "r7", "memory" + ); + } else { + int rem_words = buffer_diff / 4; + int i = 0; + do { + sdio()->FIFO = buffer_ptr1[i++]; + } while (i < rem_words); + buffer_ptr1 = buffer_ptr0; + } + + // More bytes in buffer? + if (AMBRO_LIKELY(buffer_ptr1 < buffer_ptr0)) { + o->buffer_ptr[1] = buffer_ptr1; + NVIC_ClearPendingIRQ(SDIO_IRQn); + return; + } + } + + // Moving to the next buffer. + int descriptor_index = o->descriptor_index + 1; + o->descriptor_index = descriptor_index; + + // If this was the last buffer, disable the IRQ, and stop. + if (AMBRO_UNLIKELY(descriptor_index >= o->data_vector.num_descriptors)) { + NVIC_DisableIRQ(SDIO_IRQn); + return; + } + + // Load the new buffer pointers. + auto desc = o->data_vector.descriptors[descriptor_index]; + bool buffer_order = (o->data_dir == SdioIface::DATA_DIR_READ); + o->buffer_ptr[!buffer_order] = desc.buffer_ptr; + o->buffer_ptr[ buffer_order] = desc.buffer_ptr + desc.num_words; + + NVIC_ClearPendingIRQ(SDIO_IRQn); + } + + using EventLoopFastEvents = MakeTypeList; + +private: + static void msp_init (Context c) + { + __HAL_RCC_SDIO_CLK_ENABLE(); + } + + static void msp_deinit (Context c) + { + __HAL_RCC_SDIO_CLK_DISABLE(); + } + + static void configure_interface (SdioIface::InterfaceParams if_params) + { + SD_InitTypeDef tmpinit = SD_InitTypeDef(); + tmpinit.ClockEdge = SDIO_CLOCK_EDGE_RISING; + tmpinit.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + tmpinit.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + tmpinit.BusWide = if_params.wide_data_bus ? SDIO_BUS_WIDE_4B : SDIO_BUS_WIDE_1B; + tmpinit.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + tmpinit.ClockDiv = if_params.clock_full_speed ? Params::SdClockPrescaler : SDIO_INIT_CLK_DIV; + SDIO_Init(sdio(), tmpinit); + } + + static void start_data (Context c) + { + auto *o = Object::self(c); + AMBRO_ASSERT(o->data_state == DATA_STATE_READY) + AMBRO_ASSERT(o->data_dir == SdioIface::DATA_DIR_READ || o->data_dir == SdioIface::DATA_DIR_WRITE) + AMBRO_ASSERT(o->data_vector.num_descriptors > 0) + + sdio()->ICR = SDIO_FLAG_DCRCFAIL|SDIO_FLAG_DTIMEOUT|SDIO_FLAG_RXOVERR|SDIO_FLAG_TXUNDERR|SDIO_FLAG_STBITERR|SDIO_FLAG_DATAEND; + + o->data_state = DATA_STATE_WAIT_COMPL; + o->descriptor_index = 0; + + auto desc = o->data_vector.descriptors[0]; + bool buffer_order = (o->data_dir == SdioIface::DATA_DIR_READ); + o->buffer_ptr[!buffer_order] = desc.buffer_ptr; + o->buffer_ptr[ buffer_order] = desc.buffer_ptr + desc.num_words; + + memory_barrier(); + + if (o->data_dir == SdioIface::DATA_DIR_READ) { + sdio()->MASK = SDIO_MASK_RXFIFOHFIE; + } else { + sdio()->MASK = SDIO_MASK_TXFIFOHEIE; + } + + NVIC_ClearPendingIRQ(SDIO_IRQn); + NVIC_EnableIRQ(SDIO_IRQn); + + SDIO_DataInitTypeDef data_init = SDIO_DataInitTypeDef(); + data_init.DataTimeOut = Params::DataTimeoutBusClocks; + data_init.DataLength = (uint32_t)o->data_num_blocks * BlockSize; + data_init.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + data_init.TransferDir = o->data_dir == SdioIface::DATA_DIR_READ ? SDIO_TRANSFER_DIR_TO_SDIO : SDIO_TRANSFER_DIR_TO_CARD; + data_init.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + data_init.DPSM = SDIO_DPSM_ENABLE; + SDIO_ConfigData(sdio(), &data_init); + } + + static void reset_internal (Context c) + { + auto *o = Object::self(c); + + if (o->init_state == INIT_STATE_ON) { + if (o->cmd_state != CMD_STATE_READY) { + sdio()->CMD = 0; + } + + if (o->data_state != DATA_STATE_READY) { + NVIC_DisableIRQ(SDIO_IRQn); + sdio()->DCTRL = 0; + } + } + + if (o->init_state >= INIT_STATE_POWERON) { + SDIO_PowerState_OFF(sdio()); + msp_deinit(c); + } + + o->init_state = INIT_STATE_OFF; + + Context::EventLoop::template resetFastEvent(c); + } + + static void event_handler (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(o->init_state == INIT_STATE_ON) + AMBRO_ASSERT(o->pending) + AMBRO_ASSERT(o->cmd_state != CMD_STATE_READY || o->data_state != DATA_STATE_READY) + + work_cmd(c); + work_data(c); + + if (o->cmd_state != CMD_STATE_READY || o->data_state != DATA_STATE_READY) { + Context::EventLoop::template triggerFastEvent(c); + return; + } + + o->pending = false; + + return CommandHandler::call(c, o->results, o->data_error); + } + + static void work_cmd (Context c) + { + auto *o = Object::self(c); + AMBRO_ASSERT(o->cmd_state == CMD_STATE_READY || o->cmd_state == CMD_STATE_BUSY || o->cmd_state == CMD_STATE_WAIT_BUSY) + + if (o->cmd_state == CMD_STATE_READY) { + return; + } + + uint32_t status = sdio()->STA; + + if (o->cmd_state == CMD_STATE_BUSY) { + if (o->cmd_response_type == SdioIface::RESPONSE_NONE) { + if (!(status & SDIO_FLAG_CMDSENT)) { + return; + } + } else { + if (!(o->cmd_flags & SdioIface::CMD_FLAG_NO_CRC_CHECK)) { + if ((status & SDIO_FLAG_CCRCFAIL)) { + o->results.error_code = SdioIface::CMD_ERROR_RESPONSE_CHECKSUM; + goto cmd_done; + } + } + + if ((status & SDIO_FLAG_CTIMEOUT)) { + o->results.error_code = SdioIface::CMD_ERROR_RESPONSE_TIMEOUT; + goto cmd_done; + } + + if (!(status & SDIO_FLAG_CMDREND) && !(status & SDIO_FLAG_CCRCFAIL)) { + return; + } + + if (!(o->cmd_flags & SdioIface::CMD_FLAG_NO_CMDNUM_CHECK)) { + if (SDIO_GetCommandResponse(sdio()) != o->cmd_index) { + o->results.error_code = SdioIface::CMD_ERROR_BAD_RESPONSE_CMD; + goto cmd_done; + } + } + + o->results.response[0] = sdio()->RESP1; + + if (o->cmd_response_type == SdioIface::RESPONSE_LONG) { + o->results.response[1] = sdio()->RESP2; + o->results.response[2] = sdio()->RESP3; + o->results.response[3] = sdio()->RESP4; + } + + if (o->cmd_response_type == SdioIface::RESPONSE_SHORT_BUSY) { + o->cmd_state = CMD_STATE_WAIT_BUSY; + o->busy_poll_timer.setAfter(c, BusyTimeoutTicks); + } + } + } + + if (o->cmd_state == CMD_STATE_WAIT_BUSY) { + // The SDIO peripheral does not indicate the busy status but + // looking at the D0 pin level seems to work. + if (!(Context::Pins::template get(c))) { + if (!(o->busy_poll_timer.isExpired(c))) { + return; + } + o->results.error_code = SdioIface::CMD_ERROR_BUSY_TIMEOUT; + } + } + + cmd_done: + o->cmd_state = CMD_STATE_READY; + + if (o->data_dir == SdioIface::DATA_DIR_WRITE) { + start_data(c); + } + } + + static void work_data (Context c) + { + auto *o = Object::self(c); + + if (o->data_state == DATA_STATE_READY) { + return; + } + + uint32_t status = sdio()->STA; + + while (true) { + switch (o->data_state) { + case DATA_STATE_WAIT_COMPL: { + if ((status & SDIO_FLAG_DCRCFAIL)) { + o->data_error = SdioIface::DATA_ERROR_CHECKSUM; + } + else if ((status & SDIO_FLAG_DTIMEOUT)) { + o->data_error = SdioIface::DATA_ERROR_TIMEOUT; + } + else if ((status & SDIO_FLAG_RXOVERR)) { + o->data_error = SdioIface::DATA_ERROR_RX_OVERRUN; + } + else if ((status & SDIO_FLAG_TXUNDERR)) { + o->data_error = SdioIface::DATA_ERROR_TX_OVERRUN; + } + else if ((status & SDIO_FLAG_STBITERR)) { + o->data_error = SdioIface::DATA_ERROR_STBITER; + } + else if (!(status & SDIO_FLAG_DATAEND)) { + return; + } + + o->data_state = DATA_STATE_WAIT_RXTX; + } break; + + case DATA_STATE_WAIT_RXTX: { + if ((status & SDIO_FLAG_RXACT) || (status & SDIO_FLAG_TXACT)) { + return; + } + + // When reading, we need to make sure the last words in the FIFO get flushed to memory, + // in case less than 8 words remain which would not trigger the RXFIFOHF flag. + // There is no such issue for writing, because as SDIO transmits, there will eventually + // be at least 8 words free in the FIFO, triggering the interrupt. + if (o->data_dir == SdioIface::DATA_DIR_READ) { + sdio()->MASK = SDIO_MASK_RXDAVLIE; + } + + o->data_state = DATA_STATE_WAIT_DMA; + o->poll_timer.setAfter(c, DmaTimeoutTicks); + } break; + + case DATA_STATE_WAIT_DMA: { + if (o->data_error == SdioIface::DATA_ERROR_NONE) { + // Need to wait for the transfer to complete. + int descriptor_index; + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + descriptor_index = o->descriptor_index; + } + if (descriptor_index < o->data_vector.num_descriptors) { + if (!o->poll_timer.isExpired(c)) { + return; + } + o->data_error = SdioIface::DATA_ERROR_DMA; + } + } + + NVIC_DisableIRQ(SDIO_IRQn); + sdio()->DCTRL = 0; + + memory_barrier(); + + o->data_state = DATA_STATE_READY; + return; + } break; + + default: + AMBRO_ASSERT(false); + } + } + } + +public: + struct Object : public ObjBase> { + uint8_t init_state; + bool pending; + uint8_t cmd_state; + uint8_t data_state; + uint8_t cmd_index; + uint8_t cmd_response_type; + uint8_t cmd_flags; + uint8_t data_dir; + size_t data_num_blocks; + TransferVector data_vector; + int descriptor_index; + uint32_t *buffer_ptr[2]; + SdioIface::CommandResults results; + SdioIface::DataErrorCode data_error; + typename TheClockUtils::PollTimer poll_timer; + typename TheClockUtils::PollTimer busy_poll_timer; + }; +}; + +#define APRINTER_STM32F2_SDIO_GLOBAL(sdio, context) \ +extern "C" \ +__attribute__((used)) \ +void SDIO_IRQHandler (void) \ +{ \ + sdio::sdio_irq(MakeInterruptContext((context))); \ +} + +template < + bool TIsWideMode, + uint32_t TDataTimeoutBusClocks, + int TSdClockPrescaler +> +struct Stm32f2SdioService { + static bool const IsWideMode = TIsWideMode; + static uint32_t const DataTimeoutBusClocks = TDataTimeoutBusClocks; + static int const SdClockPrescaler = TSdClockPrescaler; + + APRINTER_ALIAS_STRUCT_EXT(Sdio, ( + APRINTER_AS_TYPE(Context), + APRINTER_AS_TYPE(ParentObject), + APRINTER_AS_TYPE(CommandHandler), + APRINTER_AS_TYPE(BusyTimeout) + ), ( + using Params = Stm32f2SdioService; + APRINTER_DEF_INSTANCE(Sdio, Stm32f2Sdio) + )) +}; + +} + +#endif diff --git a/aprinter/hal/stm32/Stm32f2UsbSerial.h b/aprinter/hal/stm32/Stm32f2UsbSerial.h new file mode 100755 index 00000000..61385b14 --- /dev/null +++ b/aprinter/hal/stm32/Stm32f2UsbSerial.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef APRINTER_STM32F2_USB_SERIAL_H +#define APRINTER_STM32F2_USB_SERIAL_H + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace APrinter { + +template +class Stm32f2UsbSerial { +private: + using RecvFastEvent = typename Context::EventLoop::template FastEventSpec; + using SendFastEvent = typename Context::EventLoop::template FastEventSpec; + +public: + struct Object; + using RecvSizeType = BoundedInt; + using SendSizeType = BoundedInt; + +private: + using TheDebugObject = DebugObject; + + static size_t const UsbRxBufferSize = 1024; + static_assert(UsbRxBufferSize >= CDC_DATA_HS_OUT_PACKET_SIZE, ""); + static_assert(UsbRxBufferSize >= CDC_DATA_FS_OUT_PACKET_SIZE, ""); + + // TBD: Is this too much, what is the right limit on tx size? + static size_t const UsbMaxTxSize = 1024; + +public: + static void init (Context c, uint32_t baud) + { + auto *o = Object::self(c); + + Context::EventLoop::template initFastEvent(c, Stm32f2UsbSerial::recv_event_handler); + o->m_recv_start = RecvSizeType::import(0); + o->m_recv_end = RecvSizeType::import(0); + o->m_recv_force = false; + o->m_recv_rx_active = true; + + Context::EventLoop::template initFastEvent(c, Stm32f2UsbSerial::send_event_handler); + o->m_send_start = SendSizeType::import(0); + o->m_send_end = SendSizeType::import(0); + o->m_send_event = SendSizeType::import(0); + o->m_send_tx_active = false; + + o->m_line_coding.bitrate = 115200; + o->m_line_coding.format = 0; + o->m_line_coding.paritytype = 0; + o->m_line_coding.datatype = 8; + + o->m_cdc_ops.Init = Stm32f2UsbSerial::cdc_cb_init; + o->m_cdc_ops.DeInit = Stm32f2UsbSerial::cdc_cb_deinit; + o->m_cdc_ops.Control = Stm32f2UsbSerial::cdc_cb_control; + o->m_cdc_ops.Receive = Stm32f2UsbSerial::cdc_cb_receive; + o->m_cdc_ops.TxCompleted = Stm32f2UsbSerial::cdc_cb_tx_completed; + + if (USBD_RegisterClass(&USBD_Device, USBD_CDC_CLASS) != USBD_OK) { + AMBRO_ASSERT_ABORT("USBD_RegisterClass failed"); + } + + if (USBD_CDC_RegisterInterface(&USBD_Device, &o->m_cdc_ops) != USBD_OK) { + AMBRO_ASSERT_ABORT("USBD_CDC_RegisterInterface failed"); + } + + TheDebugObject::init(c); + } + + static void deinit (Context c) + { + auto *o = Object::self(c); + TheDebugObject::deinit(c); + + Context::EventLoop::template resetFastEvent(c); + Context::EventLoop::template resetFastEvent(c); + } + + static RecvSizeType recvQuery (Context c, bool *out_overrun) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + AMBRO_ASSERT(out_overrun) + + *out_overrun = (o->m_recv_end == BoundedModuloDec(o->m_recv_start)); + return recv_avail(o->m_recv_start, o->m_recv_end); + } + + static char * recvGetChunkPtr (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + return (o->m_recv_buffer + o->m_recv_start.value()); + } + + static void recvConsume (Context c, RecvSizeType amount) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + AMBRO_ASSERT(amount <= recv_avail(o->m_recv_start, o->m_recv_end)) + o->m_recv_start = BoundedModuloAdd(o->m_recv_start, amount); + Context::EventLoop::template triggerFastEvent(c); + } + + static void recvClearOverrun (Context c) + { + TheDebugObject::access(c); + } + + static void recvForceEvent (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + o->m_recv_force = true; + Context::EventLoop::template triggerFastEvent(c); + } + + static SendSizeType sendQuery (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + return send_avail(o->m_send_start, o->m_send_end); + } + + static SendSizeType sendGetChunkLen (Context c, SendSizeType rem_length) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + if (o->m_send_end.value() > 0 && rem_length > BoundedModuloNegative(o->m_send_end)) { + rem_length = BoundedModuloNegative(o->m_send_end); + } + + return rem_length; + } + + static char * sendGetChunkPtr (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + return (o->m_send_buffer + o->m_send_end.value()); + } + + static void sendProvide (Context c, SendSizeType amount) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + AMBRO_ASSERT(amount <= send_avail(o->m_send_start, o->m_send_end)) + o->m_send_end = BoundedModuloAdd(o->m_send_end, amount); + } + + static void sendPoke (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + Context::EventLoop::template triggerFastEvent(c); + } + + static void sendRequestEvent (Context c, SendSizeType min_amount) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + o->m_send_event = min_amount; + Context::EventLoop::template triggerFastEvent(c); + } + + using EventLoopFastEvents = MakeTypeList; + +private: + static RecvSizeType recv_avail (RecvSizeType start, RecvSizeType end) + { + return BoundedModuloSubtract(end, start); + } + + static SendSizeType send_avail (SendSizeType start, SendSizeType end) + { + return BoundedModuloDec(BoundedModuloSubtract(start, end)); + } + + static void recv_event_handler (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + bool rx_active; + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + rx_active = o->m_recv_rx_active; + } + + if (!rx_active) { + RecvSizeType virtual_start = BoundedModuloDec(o->m_recv_start); + while (o->m_recv_rx_buffer_pos < o->m_recv_rx_buffer_len && o->m_recv_end != virtual_start) { + RecvSizeType amount = (o->m_recv_end > virtual_start) ? BoundedModuloNegative(o->m_recv_end) : BoundedUnsafeSubtract(virtual_start, o->m_recv_end); + size_t remaining = o->m_recv_rx_buffer_len - o->m_recv_rx_buffer_pos; + if (amount.m_int > remaining) { + amount.m_int = remaining; + } + char const *src = o->m_recv_rx_buffer + o->m_recv_rx_buffer_pos; + char *dst = o->m_recv_buffer + o->m_recv_end.value(); + memcpy(dst, src, amount.value()); + memcpy(dst + ((size_t)RecvSizeType::maxIntValue() + 1), src, amount.value()); + o->m_recv_rx_buffer_pos += amount.value(); + o->m_recv_end = BoundedModuloAdd(o->m_recv_end, amount); + o->m_recv_force = true; + } + + if (o->m_recv_rx_buffer_pos == o->m_recv_rx_buffer_len) { + o->m_recv_rx_active = true; + USBD_CDC_ReceivePacket(&USBD_Device); + } + } + + if (o->m_recv_force) { + o->m_recv_force = false; + RecvHandler::call(c); + } + } + + static void send_event_handler (Context c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + if (o->m_send_tx_active && USBD_CDC_CheckTxBusy(&USBD_Device) != USBD_BUSY) { + o->m_send_tx_active = false; + o->m_send_start = BoundedModuloAdd(o->m_send_start, o->m_send_tx_len); + } + + if (!o->m_send_tx_active && o->m_send_start != o->m_send_end) { + SendSizeType amount = (o->m_send_end < o->m_send_start) ? BoundedModuloNegative(o->m_send_start) : BoundedUnsafeSubtract(o->m_send_end, o->m_send_start); + if (amount.m_int > UsbMaxTxSize) { + amount.m_int = UsbMaxTxSize; + } + USBD_CDC_SetTxBuffer(&USBD_Device, (uint8_t *)(o->m_send_buffer + o->m_send_start.value()), amount.value()); + if (USBD_CDC_TransmitPacket(&USBD_Device) == USBD_OK) { + o->m_send_tx_active = true; + o->m_send_tx_len = amount; + } + } + + if (o->m_send_event != SendSizeType::import(0) && send_avail(o->m_send_start, o->m_send_end) >= o->m_send_event) { + o->m_send_event = SendSizeType::import(0); + SendHandler::call(c); + } + } + + static int8_t cdc_cb_init (void) + { + auto c = Context(); + auto *o = Object::self(c); + + USBD_CDC_SetRxBuffer(&USBD_Device, (uint8_t *)o->m_recv_rx_buffer); + return USBD_OK; + } + + static int8_t cdc_cb_deinit (void) + { + return USBD_OK; + } + + static int8_t cdc_cb_control (uint8_t cmd, uint8_t *pbuf, uint16_t length) + { + auto c = MakeInterruptContext(Context()); + auto *o = Object::self(c); + + switch (cmd) { + case CDC_SET_LINE_CODING: { + o->m_line_coding.bitrate = ((uint32_t)pbuf[0] << 0) | ((uint32_t)pbuf[1] << 8) | ((uint32_t)pbuf[2] << 16) | ((uint32_t)pbuf[3] << 24); + o->m_line_coding.format = pbuf[4]; + o->m_line_coding.paritytype = pbuf[5]; + o->m_line_coding.datatype = pbuf[6]; + } break; + case CDC_GET_LINE_CODING: { + pbuf[0] = o->m_line_coding.bitrate >> 0; + pbuf[1] = o->m_line_coding.bitrate >> 8; + pbuf[2] = o->m_line_coding.bitrate >> 16; + pbuf[3] = o->m_line_coding.bitrate >> 24; + pbuf[4] = o->m_line_coding.format; + pbuf[5] = o->m_line_coding.paritytype; + pbuf[6] = o->m_line_coding.datatype; + } break; + } + return USBD_OK; + } + + static int8_t cdc_cb_receive (uint8_t *pbuf, uint32_t *len) + { + auto c = MakeInterruptContext(Context()); + auto *o = Object::self(c); + AMBRO_ASSERT_FORCE(o->m_recv_rx_active) + AMBRO_ASSERT_FORCE(*len <= UsbRxBufferSize) + + AMBRO_LOCK_T(InterruptTempLock(), c, lock_c) { + o->m_recv_rx_active = false; + o->m_recv_rx_buffer_len = *len; + o->m_recv_rx_buffer_pos = 0; + } + Context::EventLoop::template triggerFastEvent(c); + return USBD_OK; + } + + static void cdc_cb_tx_completed () + { + auto c = MakeInterruptContext(Context()); + + Context::EventLoop::template triggerFastEvent(c); + } + +public: + struct Object : public ObjBase> { + RecvSizeType m_recv_start; + RecvSizeType m_recv_end; + bool m_recv_force; + bool m_recv_rx_active; + size_t m_recv_rx_buffer_len; + size_t m_recv_rx_buffer_pos; + char m_recv_buffer[2 * ((size_t)RecvSizeType::maxIntValue() + 1)]; + char m_recv_rx_buffer[UsbRxBufferSize]; + SendSizeType m_send_start; + SendSizeType m_send_end; + SendSizeType m_send_event; + bool m_send_tx_active; + SendSizeType m_send_tx_len; + char m_send_buffer[(size_t)SendSizeType::maxIntValue() + 1]; + USBD_CDC_LineCodingTypeDef m_line_coding; + USBD_CDC_ItfTypeDef m_cdc_ops; + }; +}; + +struct Stm32f2UsbSerialService { + template + using Serial = Stm32f2UsbSerial; +}; + +} + +#endif diff --git a/aprinter/hal/stm32/Stm32f2Watchdog.h b/aprinter/hal/stm32/Stm32f2Watchdog.h new file mode 100755 index 00000000..16286406 --- /dev/null +++ b/aprinter/hal/stm32/Stm32f2Watchdog.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef AMBROLIB_STM32F2_WATCHDOG_H +#define AMBROLIB_STM32F2_WATCHDOG_H + +#include + +#include +#include +#include +#include +#include + +namespace APrinter { + +template +class Stm32f2Watchdog { + APRINTER_USE_TYPES1(Arg, (Context, ParentObject, Params)) + + static uint32_t const PrescalerValue = + Params::Divider == 4 ? IWDG_PRESCALER_4 : + Params::Divider == 8 ? IWDG_PRESCALER_8 : + Params::Divider == 16 ? IWDG_PRESCALER_16 : + Params::Divider == 32 ? IWDG_PRESCALER_32 : + Params::Divider == 64 ? IWDG_PRESCALER_64 : + Params::Divider == 128 ? IWDG_PRESCALER_128 : + Params::Divider == 256 ? IWDG_PRESCALER_256 : + UINT32_MAX; + static_assert(PrescalerValue != UINT32_MAX, "Invalid watchdog Divider value"); + static_assert(Params::Reload <= 0xFFF, "Invalid watchdog Reload value"); + +public: + struct Object; + +private: + using TheDebugObject = DebugObject; + +public: + static constexpr double WatchdogTime = Params::Reload / ((double)LSI_VALUE / Params::Divider); + + static void init (Context c) + { + auto *o = Object::self(c); + TheDebugObject::init(c); + + o->iwdg_handle.Instance = IWDG; + o->iwdg_handle.Init.Prescaler = PrescalerValue; + o->iwdg_handle.Init.Reload = Params::Reload; + + HAL_IWDG_Init(&o->iwdg_handle); + } + + static void deinit (Context c) + { + TheDebugObject::deinit(c); + } + + template + static void reset (ThisContext c) + { + auto *o = Object::self(c); + TheDebugObject::access(c); + + HAL_IWDG_Refresh(&o->iwdg_handle); + } + + APRINTER_NO_RETURN + static void emergency_abort () + { + while (true); + } + +public: + struct Object : public ObjBase> { + IWDG_HandleTypeDef iwdg_handle; + }; +}; + +APRINTER_ALIAS_STRUCT_EXT(Stm32f2WatchdogService, ( + APRINTER_AS_VALUE(int, Divider), + APRINTER_AS_VALUE(uint16_t, Reload) +), ( + APRINTER_ALIAS_STRUCT_EXT(Watchdog, ( + APRINTER_AS_TYPE(Context), + APRINTER_AS_TYPE(ParentObject), + APRINTER_AS_VALUE(bool, DebugMode) + ), ( + using Params = Stm32f2WatchdogService; + APRINTER_DEF_INSTANCE(Watchdog, Stm32f2Watchdog) + )) +)) + +} + +#endif diff --git a/aprinter/platform/stm32f2/stm32f205.ld b/aprinter/platform/stm32f2/stm32f205.ld new file mode 100755 index 00000000..f03b2f1e --- /dev/null +++ b/aprinter/platform/stm32f2/stm32f205.ld @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K +} + +/* End of stack is at end of RAM. And NOT one less. See: + http://stackoverflow.com/a/28761856/1020667 */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + KEEP(*(.init)) + KEEP(*(.fini)) + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data.*) + . = ALIGN(4); + _edata = .; + } >RAM AT> FLASH + + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >RAM + + PROVIDE ( _end = _ebss ); + + DISCARD : + { + libgcc.a ( * ) + libc.a ( * ) + libm.a ( * ) + } +} diff --git a/aprinter/platform/stm32f2/stm32f2_support.cpp b/aprinter/platform/stm32f2/stm32f2_support.cpp new file mode 100755 index 00000000..556025c7 --- /dev/null +++ b/aprinter/platform/stm32f2/stm32f2_support.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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 +#include + +#include + +#include "stm32f2_support.h" + +#ifdef APRINTER_ENABLE_USB +#include +#include "usbd_desc.h" +#endif + +static void init_clock (void); +static void init_usb (void); +static void init_final_usb (void); + +#ifdef APRINTER_ENABLE_USB +extern "C" PCD_HandleTypeDef hpcd; +USBD_HandleTypeDef USBD_Device; +#endif + +extern "C" { + void NMI_Handler (void) + { + } + + void HardFault_Handler (void) + { + while (1); + } + + void MemManage_Handler (void) + { + while (1); + } + + void BusFault_Handler (void) + { + while (1); + } + + void UsageFault_Handler (void) + { + while (1); + } + + void SVC_Handler (void) + { + } + + void DebugMon_Handler (void) + { + } + + void PendSV_Handler (void) + { + } + + void SysTick_Handler (void) + { + HAL_IncTick(); + } + +#ifdef APRINTER_ENABLE_USB +#ifdef USE_USB_FS + void OTG_FS_IRQHandler(void) + { + HAL_PCD_IRQHandler(&hpcd); + } +#endif + +#ifdef USE_USB_HS + void OTG_HS_IRQHandler(void) + { + HAL_PCD_IRQHandler(&hpcd); + } +#endif +#endif +} + +void platform_init (void) +{ + HAL_Init(); + init_clock(); + init_usb(); +} + +void platform_init_final (void) +{ + init_final_usb(); +} + +static void init_clock (void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + HAL_StatusTypeDef ret = HAL_OK; + + // Enable Power Control clock. + __HAL_RCC_PWR_CLK_ENABLE(); + + // Enable the HSE oscillator and activate the PLL with the HSE. + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = PLL_M_VALUE; + RCC_OscInitStruct.PLL.PLLN = PLL_N_VALUE; + RCC_OscInitStruct.PLL.PLLP = PLL_P_DIV_VALUE; + RCC_OscInitStruct.PLL.PLLQ = PLL_Q_DIV_VALUE; + ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); + if (ret != HAL_OK) while (1); + + // Select PLL as the system clock source and configure the HCLK, PCLK1 and PCLK2 + // clock dividers. + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = APRINTER_JOIN(RCC_HCLK_DIV, APB1_PRESC_DIV); + RCC_ClkInitStruct.APB2CLKDivider = APRINTER_JOIN(RCC_HCLK_DIV, APB2_PRESC_DIV); + ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); + if (ret != HAL_OK) while (1); +} + +static void init_usb (void) +{ +#ifdef APRINTER_ENABLE_USB + if (USBD_Init(&USBD_Device, &VCP_Desc, 0) != USBD_OK) { + while (1); + } +#endif +} + +static void init_final_usb (void) +{ +#ifdef APRINTER_ENABLE_USB + if (USBD_Start(&USBD_Device) != USBD_OK) { + while (1); + } +#endif +} diff --git a/aprinter/platform/stm32f2/stm32f2_support.h b/aprinter/platform/stm32f2/stm32f2_support.h new file mode 100755 index 00000000..05c14c92 --- /dev/null +++ b/aprinter/platform/stm32f2/stm32f2_support.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +#ifndef AMBROLIB_STM32F2_SUPPORT_H +#define AMBROLIB_STM32F2_SUPPORT_H + +#include + +#include + +#ifdef APRINTER_ENABLE_USB +#include +#endif + +#include + +#define F_CPU (((double)HSE_VALUE * PLL_N_VALUE) / ((double)PLL_P_DIV_VALUE * PLL_M_VALUE)) +#define APB1_TIMERS_DIV (APB1_PRESC_DIV == 1 ? APB1_PRESC_DIV : (APB1_PRESC_DIV / 2)) +#define APB2_TIMERS_DIV (APB2_PRESC_DIV == 1 ? APB2_PRESC_DIV : (APB2_PRESC_DIV / 2)) + +#define INTERRUPT_PRIORITY 4 + +void platform_init (void); +void platform_init_final (void); + +#ifdef APRINTER_ENABLE_USB +extern USBD_HandleTypeDef USBD_Device; +#endif + +#endif diff --git a/aprinter/platform/stm32f2/stm32f2xx_hal_conf.h b/aprinter/platform/stm32f2/stm32f2xx_hal_conf.h new file mode 100755 index 00000000..02bc9d02 --- /dev/null +++ b/aprinter/platform/stm32f2/stm32f2xx_hal_conf.h @@ -0,0 +1,395 @@ +/** + ****************************************************************************** + * @file stm32f2xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2018 STMicroelectronics

+ * + * 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 of STMicroelectronics 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 HOLDER 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F2xx_HAL_CONF_H +#define __STM32F2xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +//#define HAL_ADC_MODULE_ENABLED +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +//#define HAL_DAC_MODULE_ENABLED +/*#define HAL_DCMI_MODULE_ENABLED */ +/*#define HAL_ETH_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_PCCARD_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +/*#define HAL_HASH_MODULE_ENABLED */ +//#define HAL_I2C_MODULE_ENABLED +/*#define HAL_I2S_MODULE_ENABLED */ +#define HAL_IWDG_MODULE_ENABLED +/*#define HAL_RNG_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +#define HAL_SD_MODULE_ENABLED +/*#define HAL_MMC_MODULE_ENABLED */ +//#define HAL_SPI_MODULE_ENABLED +/*#define HAL_TIM_MODULE_ENABLED */ +//#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +//#define HAL_HCD_MODULE_ENABLED +/*#define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)16000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f2xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f2xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f2xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f2xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f2xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f2xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f2xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f2xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f2xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f2xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f2xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f2xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f2xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f2xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f2xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f2xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f2xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f2xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f2xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f2xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f2xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f2xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f2xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f2xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f2xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f2xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f2xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f2xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f2xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f2xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f2xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f2xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f2xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f2xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f2xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F2xx_HAL_CONF_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/aprinter/platform/stm32f2/usbd_conf.c b/aprinter/platform/stm32f2/usbd_conf.c new file mode 100755 index 00000000..4ebdd6b4 --- /dev/null +++ b/aprinter/platform/stm32f2/usbd_conf.c @@ -0,0 +1,610 @@ +/** + ****************************************************************************** + * @file USB_Device/CDC_Standalone/Src/usbd_conf.c + * @author MCD Application Team + * @version V1.2.1 + * @date 13-March-2015 + * @brief This file implements the USB Device library callbacks and MSP + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f2xx_hal.h" +#include "usbd_core.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +PCD_HandleTypeDef hpcd; + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* + PCD BSP Routines +*******************************************************************************/ +/** + * @brief Initializes the PCD MSP. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + if(hpcd->Instance == USB_OTG_FS) + { + /* Configure USB FS GPIOs */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* Configure DM Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Configure DP Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // /* Configure VBUS Pin */ + // GPIO_InitStruct.Pin = GPIO_PIN_9; + // GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + // GPIO_InitStruct.Pull = GPIO_NOPULL; + // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // /* Configure ID pin */ + // GPIO_InitStruct.Pin = GPIO_PIN_10; + // GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + // GPIO_InitStruct.Pull = GPIO_PULLUP; + // GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Enable USB FS Clocks */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Set USBFS Interrupt priority to 6 */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 6, 0); + + /* Enable USBFS Interrupt */ + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +#ifdef USE_USB_HS + else if(hpcd->Instance == USB_OTG_HS) + { +#ifdef USE_USB_HS_IN_FS + + /* Configure USB FS GPIOs */ + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO for HS on FS mode*/ + GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_14 |GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_OTG_HS_FS; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Configure VBUS Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + GPIO_InitStruct.Pull = GPIO_NOPULL; + +#else + + /* Configure USB HS GPIOs */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOI_CLK_ENABLE(); + + /* CLK */ + GPIO_InitStruct.Pin = GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* D0 */ + GPIO_InitStruct.Pin = GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* D1 D2 D3 D4 D5 D6 D7 */ + GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 |\ + GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* STP */ + GPIO_InitStruct.Pin = GPIO_PIN_0; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /* NXT */ + GPIO_InitStruct.Pin = GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + + /* DIR */ + GPIO_InitStruct.Pin = GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + + /* Enable embedded ULPI */ + __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); +#endif /* USE_USB_HS_IN_FS */ + + /* Enable USB HS Clocks */ + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + + /* Set USBHS Interrupt priority to 6 */ + HAL_NVIC_SetPriority(OTG_HS_IRQn, 6, 0); + + /* Enable USBHS Interrupt */ + HAL_NVIC_EnableIRQ(OTG_HS_IRQn); + } +#endif /* USE_USB_HS */ +} + +/** + * @brief DeInitializes the PCD MSP. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) +{ + if(hpcd->Instance == USB_OTG_FS) + { + /* Disable USB FS Clocks */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + __HAL_RCC_SYSCFG_CLK_DISABLE(); + } +#ifdef USE_USB_HS + else if(hpcd->Instance == USB_OTG_HS) + { + /* Disable USB FS Clocks */ + __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); + __HAL_RCC_SYSCFG_CLK_DISABLE(); + } +#endif /* USE_USB_HS */ +} + +/******************************************************************************* + LL Driver Callbacks (PCD -> USB Device Library) +*******************************************************************************/ + + +/** + * @brief Setup stage callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SetupStage(hpcd->pData, (uint8_t *)hpcd->Setup); +} + +/** + * @brief Data Out stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint Number + * @retval None + */ +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataOutStage(hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); +} + +/** + * @brief Data In stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint Number + * @retval None + */ +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataInStage(hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); +} + +/** + * @brief SOF callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SOF(hpcd->pData); +} + +/** + * @brief Reset callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_SpeedTypeDef speed = USBD_SPEED_FULL; + + /* Set USB Current Speed */ + switch(hpcd->Init.speed) + { + case PCD_SPEED_HIGH: + speed = USBD_SPEED_HIGH; + break; + + case PCD_SPEED_FULL: + speed = USBD_SPEED_FULL; + break; + + default: + speed = USBD_SPEED_FULL; + break; + } + USBD_LL_SetSpeed(hpcd->pData, speed); + + /* Reset Device */ + USBD_LL_Reset(hpcd->pData); +} + +/** + * @brief Suspend callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_Suspend(hpcd->pData); +} + +/** + * @brief Resume callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_Resume(hpcd->pData); +} + +/** + * @brief ISOC Out Incomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint Number + * @retval None + */ +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoOUTIncomplete(hpcd->pData, epnum); +} + +/** + * @brief ISOC In Incomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint Number + * @retval None + */ +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoINIncomplete(hpcd->pData, epnum); +} + +/** + * @brief Connect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_DevConnected(hpcd->pData); +} + +/** + * @brief Disconnect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_DevDisconnected(hpcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Device Library --> PCD) +*******************************************************************************/ +/** + * @brief Initializes the Low Level portion of the Device driver. + * @param pdev: Device handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev) +{ + /* Change Systick prioity */ + NVIC_SetPriority (SysTick_IRQn, 0); + +#ifdef USE_USB_FS + /*Set LL Driver parameters */ + hpcd.Instance = USB_OTG_FS; + hpcd.Init.dev_endpoints = 4; + hpcd.Init.use_dedicated_ep1 = DISABLE; + hpcd.Init.ep0_mps = DEP0CTL_MPS_64; + hpcd.Init.dma_enable = DISABLE; + hpcd.Init.low_power_enable = DISABLE; + hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd.Init.Sof_enable = DISABLE; + hpcd.Init.speed = PCD_SPEED_FULL; + hpcd.Init.vbus_sensing_enable = DISABLE; + /* Link The driver to the stack */ + hpcd.pData = pdev; + pdev->pData = &hpcd; + /*Initialize LL Driver */ + HAL_PCD_Init(&hpcd); + + HAL_PCDEx_SetRxFiFo(&hpcd, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd, 0, 0x40); + HAL_PCDEx_SetTxFiFo(&hpcd, 1, 0x80); + + +#endif +#ifdef USE_USB_HS + /*Set LL Driver parameters */ + hpcd.Instance = USB_OTG_HS; + hpcd.Init.dev_endpoints = 6; + hpcd.Init.use_dedicated_ep1 = 0; + hpcd.Init.ep0_mps = 0x40; + + /* Be aware that enabling USB-DMA mode will result in data being sent only by + multiple of 4 packet sizes. This is due to the fact that USB DMA does + not allow sending data from non word-aligned addresses. + For this specific application, it is advised to not enable this option + unless required. */ + hpcd.Init.dma_enable = 0; + + hpcd.Init.low_power_enable = 0; + +#ifdef USE_USB_HS_IN_FS + hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd.Init.speed = PCD_SPEED_HIGH_IN_FULL; +#else + hpcd.Init.phy_itface = PCD_PHY_ULPI; + hpcd.Init.speed = PCD_SPEED_HIGH; +#endif + hpcd.Init.Sof_enable = 0; + hpcd.Init.vbus_sensing_enable = DISABLE; + /* Link The driver to the stack */ + hpcd.pData = pdev; + pdev->pData = &hpcd; + /*Initialize LL Driver */ + HAL_PCD_Init(&hpcd); + + HAL_PCDEx_SetRxFiFo(&hpcd, 0x200); + HAL_PCDEx_SetTxFiFo(&hpcd, 0, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd, 1, 0x174); + + +#endif + return USBD_OK; +} + +/** + * @brief De-Initializes the Low Level portion of the Device driver. + * @param pdev: Device handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) +{ + HAL_PCD_DeInit(pdev->pData); + return USBD_OK; +} + +/** + * @brief Starts the Low Level portion of the Device driver. + * @param pdev: Device handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) +{ + HAL_PCD_Start(pdev->pData); + return USBD_OK; +} + +/** + * @brief Stops the Low Level portion of the Device driver. + * @param pdev: Device handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) +{ + HAL_PCD_Stop(pdev->pData); + return USBD_OK; +} + +/** + * @brief Opens an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @param ep_type: Endpoint Type + * @param ep_mps: Endpoint Max Packet Size + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t ep_type, + uint16_t ep_mps) +{ + HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); + return USBD_OK; +} + +/** + * @brief Closes an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_PCD_EP_Close(pdev->pData, ep_addr); + return USBD_OK; +} + +/** + * @brief Flushes an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_PCD_EP_Flush(pdev->pData, ep_addr); + return USBD_OK; +} + +/** + * @brief Sets a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_PCD_EP_SetStall(pdev->pData, ep_addr); + return USBD_OK; +} + +/** + * @brief Clears a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); + return USBD_OK; +} + +/** + * @brief Returns Stall condition. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @retval Stall (1: yes, 0: No) + */ +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + PCD_HandleTypeDef *hpcd = pdev->pData; + + if((ep_addr & 0x80) == 0x80) + { + return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + } + else + { + return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; + } +} + +/** + * @brief Assigns an USB address to the device + * @param pdev: Device handle + * @param dev_addr: USB address + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) +{ + HAL_PCD_SetAddress(pdev->pData, dev_addr); + return USBD_OK; +} + +/** + * @brief Transmits data over an endpoint + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @param pbuf: Pointer to data to be sent + * @param size: Data size + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t size) +{ + HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); + return USBD_OK; +} + +/** + * @brief Prepares an endpoint for reception + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @param pbuf:pointer to data to be received + * @param size: data size + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t size) +{ + HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); + return USBD_OK; +} + +/** + * @brief Returns the last transfered packet size. + * @param pdev: Device handle + * @param ep_addr: Endpoint Number + * @retval Recived Data Size + */ +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr); +} + +/** + * @brief Delay routine for the USB Device Library + * @param Delay: Delay in ms + * @retval None + */ +void USBD_LL_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/aprinter/platform/stm32f2/usbd_conf.h b/aprinter/platform/stm32f2/usbd_conf.h new file mode 100755 index 00000000..042fcdd4 --- /dev/null +++ b/aprinter/platform/stm32f2/usbd_conf.h @@ -0,0 +1,74 @@ +/** + ****************************************************************************** + * @file usbd_conf.h + * @author MCD Application Team + * @version V1.2.0 + * @date 26-December-2014 + * @brief General low level driver configuration + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +#include "stm32f2xx.h" +#include +#include +#include + +#define USBD_MAX_NUM_INTERFACES 1 +#define USBD_MAX_NUM_CONFIGURATION 1 +#define USBD_MAX_STR_DESC_SIZ 0x100 +#define USBD_SUPPORT_USER_STRING 0 +#define USBD_SELF_POWERED 1 +#define USBD_DEBUG_LEVEL 0 + +#define USBD_malloc malloc +#define USBD_free free +#define USBD_memset memset +#define USBD_memcpy memcpy + +#if (USBD_DEBUG_LEVEL > 0) +#define USBD_UsrLog(...) printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_UsrLog(...) +#endif + + +#if (USBD_DEBUG_LEVEL > 1) + +#define USBD_ErrLog(...) printf("ERROR: ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_ErrLog(...) +#endif + + +#if (USBD_DEBUG_LEVEL > 2) +#define USBD_DbgLog(...) printf("DEBUG : ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_DbgLog(...) +#endif + +#endif diff --git a/aprinter/platform/stm32f2/usbd_desc.c b/aprinter/platform/stm32f2/usbd_desc.c new file mode 100755 index 00000000..ea9f23b9 --- /dev/null +++ b/aprinter/platform/stm32f2/usbd_desc.c @@ -0,0 +1,145 @@ +/** + ****************************************************************************** + * @file Demonstrations/Src/usbd_desc.c + * @author MCD Application Team + * @version V1.2.0 + * @date 26-December-2014 + * @brief This file provides the USBD descriptors and string formating method. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" + +#define USBD_VID 0x0483 +#define USBD_PID 0x5740 +#define USBD_LANGID_STRING 0x409 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#define USBD_PRODUCT_STRING "STM32 Virtual ComPort" +#define USBD_SERIALNUMBER_STRING "00000000001A" +#define USBD_CONFIGURATION_STRING "VCP Config" +#define USBD_INTERFACE_STRING "VCP Interface" + +uint8_t * USBD_VCP_DeviceDescriptor( USBD_SpeedTypeDef speed , uint16_t *length); +uint8_t * USBD_VCP_LangIDStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length); +uint8_t * USBD_VCP_ManufacturerStrDescriptor ( USBD_SpeedTypeDef speed , uint16_t *length); +uint8_t * USBD_VCP_ProductStrDescriptor ( USBD_SpeedTypeDef speed , uint16_t *length); +uint8_t * USBD_VCP_SerialStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length); +uint8_t * USBD_VCP_ConfigStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length); +uint8_t * USBD_VCP_InterfaceStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length); + +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t * USBD_VCP_USRStringDesc (USBD_SpeedTypeDef speed, uint8_t idx , uint16_t *length); +#endif + +USBD_DescriptorsTypeDef VCP_Desc = +{ + USBD_VCP_DeviceDescriptor, + USBD_VCP_LangIDStrDescriptor, + USBD_VCP_ManufacturerStrDescriptor, + USBD_VCP_ProductStrDescriptor, + USBD_VCP_SerialStrDescriptor, + USBD_VCP_ConfigStrDescriptor, + USBD_VCP_InterfaceStrDescriptor, +}; + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = + { + 0x12, /*bLength */ + USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ + 0x00, /*bcdUSB */ + 0x02, + 0x02, /*bDeviceClass*/ + 0x02, /*bDeviceSubClass*/ + 0x00, /*bDeviceProtocol*/ + USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ + LOBYTE(USBD_VID), /*idVendor*/ + HIBYTE(USBD_VID), /*idVendor*/ + LOBYTE(USBD_PID), /*idVendor*/ + HIBYTE(USBD_PID), /*idVendor*/ + 0x00, /*bcdDevice rel. 2.00*/ + 0x02, + USBD_IDX_MFC_STR, /*Index of manufacturer string*/ + USBD_IDX_PRODUCT_STR, /*Index of product string*/ + USBD_IDX_SERIAL_STR, /*Index of serial number string*/ + USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ + } ; + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = +{ + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING), +}; + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +uint8_t * USBD_VCP_DeviceDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + *length = sizeof(hUSBDDeviceDesc); + return hUSBDDeviceDesc; +} + +uint8_t * USBD_VCP_LangIDStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + +uint8_t * USBD_VCP_ProductStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + USBD_GetString ((uint8_t *)USBD_PRODUCT_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +uint8_t * USBD_VCP_ManufacturerStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + USBD_GetString ((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +uint8_t * USBD_VCP_SerialStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + USBD_GetString ((uint8_t *)USBD_SERIALNUMBER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +uint8_t * USBD_VCP_ConfigStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + USBD_GetString ((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +uint8_t * USBD_VCP_InterfaceStrDescriptor( USBD_SpeedTypeDef speed , uint16_t *length) +{ + USBD_GetString ((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} diff --git a/aprinter/platform/stm32f2/usbd_desc.h b/aprinter/platform/stm32f2/usbd_desc.h new file mode 100755 index 00000000..1ce7b987 --- /dev/null +++ b/aprinter/platform/stm32f2/usbd_desc.h @@ -0,0 +1,43 @@ +/** + ****************************************************************************** + * @file usbd_desc.h + * @author MCD Application Team + * @version V1.2.0 + * @date 26-December-2014 + * @brief header file for the usbd_desc.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +#ifndef __USB_DESC_H +#define __USB_DESC_H + +#include "usbd_def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern USBD_DescriptorsTypeDef VCP_Desc; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/config_system/generator/generate.py b/config_system/generator/generate.py index c5b6a59c..7f8a2261 100644 --- a/config_system/generator/generate.py +++ b/config_system/generator/generate.py @@ -436,6 +436,13 @@ def option(platform_name, platform): gen.add_platform_include('aprinter/platform/avr/avr_support.h') gen.add_init_call(-3, 'sei();') + @platform_sel.option('Stm32f2') + def option(platform): + gen.add_platform_include('aprinter/platform/stm32f2/stm32f2_support.h') + gen.add_init_call(-1, 'platform_init();') + gen.add_final_init_call(-1, 'platform_init_final();') + gen.register_singleton_object('checksum_src_file', arm_checksum_src_file) + @platform_sel.option('Stm32f4') def option(platform): gen.add_platform_include('aprinter/platform/stm32f4/stm32f4_support.h') @@ -607,6 +614,16 @@ def option(mode): timer_config.do_selection('Mode', mode_sel), ]) +def Stm32f2ClockDef(x): + x.INCLUDE = 'hal/stm32/Stm32f2Clock.h' + x.CLOCK_SERVICE = lambda config: TemplateExpr('Stm32f2ClockService', [config.get_int_constant('prescaler')]) + x.TIMER_RE = '\\ATIM([0-9]{1,2})\\Z' + x.CHANNEL_RE = '\\ATIM([0-9]{1,2})_([1-4])\\Z' + x.INTERRUPT_TIMER_EXPR = lambda it, clearance: 'Stm32f2ClockInterruptTimerService'.format(it['tc'], it['channel'], clearance) + x.INTERRUPT_TIMER_ISR = lambda it, user: 'AMBRO_STM32F2_CLOCK_INTERRUPT_TIMER_GLOBAL(Stm32f2ClockTIM{}, Stm32f2ClockComp{}, {}, Context())'.format(it['tc'], it['channel'], user) + x.TIMER_EXPR = lambda tc: 'Stm32f2ClockTIM{}'.format(tc) + x.TIMER_ISR = lambda my_clock, tc: 'AMBRO_STM32F2_CLOCK_TC_GLOBAL({}, {}, Context())'.format(tc, my_clock) + def Stm32f4ClockDef(x): x.INCLUDE = 'hal/stm32/Stm32f4Clock.h' x.CLOCK_SERVICE = lambda config: TemplateExpr('Stm32f4ClockService', [config.get_int_constant('prescaler')]) @@ -651,6 +668,10 @@ def option(clock): def option(clock): return CommonClock(gen, clock, clock_name, priority, AvrClockDef) + @clock_sel.option('Stm32f2Clock') + def option(clock): + return CommonClock(gen, clock, clock_name, priority, Stm32f2ClockDef) + @clock_sel.option('Stm32f4Clock') def option(clock): return CommonClock(gen, clock, clock_name, priority, Stm32f4ClockDef) @@ -704,6 +725,12 @@ def options(pin_config): pin_regexes.append('\\AAvrPin\\Z') return TemplateLiteral('AvrPinsService') + @pins_sel.option('Stm32f2Pins') + def options(pin_config): + gen.add_aprinter_include('hal/stm32/Stm32f2Pins.h') + pin_regexes.append('\\AStm32f2Pin\\Z') + return TemplateLiteral('Stm32f2PinsService') + @pins_sel.option('Stm32f4Pins') def options(pin_config): gen.add_aprinter_include('hal/stm32/Stm32f4Pins.h') @@ -758,6 +785,14 @@ def option(watchdog): gen.add_isr('AMBRO_AVR_WATCHDOG_GLOBAL') return TemplateExpr('AvrWatchdogService', [wdto]) + @watchdog_sel.option('Stm32f2Watchdog') + def option(watchdog): + gen.add_aprinter_include('hal/stm32/Stm32f2Watchdog.h') + return TemplateExpr('Stm32f2WatchdogService', [ + watchdog.get_int('Divider'), + watchdog.get_int('Reload'), + ]) + @watchdog_sel.option('Stm32f4Watchdog') def option(watchdog): gen.add_aprinter_include('hal/stm32/Stm32f4Watchdog.h') @@ -842,6 +877,19 @@ def option(adc_config): 'pin_func': lambda pin: pin } + @adc_sel.option('Stm32f2Adc') + def option(adc_config): + gen.add_aprinter_include('hal/stm32/Stm32f2Adc.h') + gen.add_isr('APRINTER_STM32F2_ADC_GLOBAL(MyAdc, Context())') + + return { + 'service_expr': TemplateExpr('Stm32f2AdcService', [ + adc_config.get_int('ClockDivider'), + adc_config.get_int('SampleTimeSelection'), + ]), + 'pin_func': lambda pin: pin + } + @adc_sel.option('Stm32f4Adc') def option(adc_config): gen.add_aprinter_include('hal/stm32/Stm32f4Adc.h') @@ -901,6 +949,12 @@ def option(im_config): im_config.do_enum('PullMode', {'Normal': 'At91SamPinPullModeNormal', 'Pull-up': 'At91SamPinPullModePullUp'}), ]) + @im_sel.option('Stm32f2PinInputMode') + def option(im_config): + return TemplateExpr('Stm32f2PinInputMode', [ + im_config.do_enum('PullMode', {'Normal': 'Stm32f2PinPullModeNone', 'Pull-up': 'Stm32f2PinPullModePullUp', 'Pull-down': 'Stm32f2PinPullModePullDown'}), + ]) + @im_sel.option('Stm32f4PinInputMode') def option(im_config): return TemplateExpr('Stm32f4PinInputMode', [ @@ -1047,6 +1101,16 @@ def option(spi_config): def use_sdio (gen, config, key, user): sdio_sel = selection.Selection() + @sdio_sel.option('Stm32f2Sdio') + def option(sdio_config): + gen.add_aprinter_include('hal/stm32/Stm32f2Sdio.h') + gen.add_isr('APRINTER_STM32F2_SDIO_GLOBAL({}, Context())'.format(user)) + return TemplateExpr('Stm32f2SdioService', [ + sdio_config.get_bool('IsWideMode'), + sdio_config.get_int('DataTimeoutBusClocks'), + sdio_config.get_int('SdClockPrescaler'), + ]) + @sdio_sel.option('Stm32f4Sdio') def option(sdio_config): gen.add_aprinter_include('hal/stm32/Stm32f4Sdio.h') @@ -1167,6 +1231,11 @@ def option(serial_service): gen.add_init_call(-2, 'aprinter_init_avr_debug_write();') return TemplateExpr('AvrSerialService', [serial_service.get_bool('DoubleSpeed')]) + @serial_sel.option('Stm32f2UsbSerial') + def option(serial_service): + gen.add_aprinter_include('hal/stm32/Stm32f2UsbSerial.h') + return 'Stm32f2UsbSerialService' + @serial_sel.option('Stm32f4UsbSerial') def option(serial_service): gen.add_aprinter_include('hal/stm32/Stm32f4UsbSerial.h') diff --git a/config_system/gui/aprinter_config_editor.py b/config_system/gui/aprinter_config_editor.py index 325ee3c7..06651901 100644 --- a/config_system/gui/aprinter_config_editor.py +++ b/config_system/gui/aprinter_config_editor.py @@ -47,6 +47,9 @@ def input_mode_choice(context, **kwargs): ce.Compound('At91SamPinInputMode', attrs=[ ce.String(key='PullMode', title='Pull mode', enum=['Normal', 'Pull-up']), ]), + ce.Compound('Stm32f2PinInputMode', attrs=[ + ce.String(key='PullMode', title='Pull mode', enum=['Normal', 'Pull-up', 'Pull-down']), + ]), ce.Compound('Stm32f4PinInputMode', attrs=[ ce.String(key='PullMode', title='Pull mode', enum=['Normal', 'Pull-up', 'Pull-down']), ]), @@ -84,6 +87,11 @@ def spi_choice(**kwargs): def sdio_choice(**kwargs): return ce.OneOf(choices=[ + ce.Compound('Stm32f2Sdio', attrs=[ + ce.Boolean(key='IsWideMode', title='Data bus width', false_title='1-bit', true_title='4-bit', default=False), + ce.Integer(key='DataTimeoutBusClocks', title='Data timeout (in SDIO bus clocks)', default=0x20000000), + ce.Integer(key='SdClockPrescaler', title='SD clock prescaler for transfer', default=0), + ]), ce.Compound('Stm32f4Sdio', attrs=[ ce.Boolean(key='IsWideMode', title='Data bus width', false_title='1-bit', true_title='4-bit', default=False), ce.Integer(key='DataTimeoutBusClocks', title='Data timeout (in SDIO bus clocks)', default=0x20000000), @@ -270,6 +278,37 @@ def platform_Avr(variant): ]), ]) +def platform_Stm32f2(): + return ce.Compound('Stm32f2', attrs=[ + ce.Compound('Stm32f2Clock', key='clock', title='Clock', collapsable=True, attrs=[ + ce.Integer(key='prescaler', title='Prescaler'), + ce.String(key='primary_timer', title='Primary timer'), + ce.Constant(key='avail_oc_units', value=[ + { + 'value': 'TIM{}_{}'.format(n, m) + } for n in [2,3,4,5,12,13,14] for m in [1,2,3,4] + ]) + ]), + ce.Compound('Stm32f2Adc', key='adc', title='ADC', collapsable=True, attrs=[ + ce.Integer(key='ClockDivider'), + ce.Integer(key='SampleTimeSelection'), + ]), + ce.Compound('Stm32f2Watchdog', key='watchdog', title='Watchdog', collapsable=True, attrs=[ + ce.Integer(key='Divider', title='Divider'), + ce.Integer(key='Reload', title='Reload'), + ]), + ce.Compound('Stm32f2Pins', key='pins', title='Pins', collapsable=True, attrs=[ + ce.Constant(key='input_mode_type', value='Stm32f2PinInputMode'), + ]), + ce.OneOf(key='fast_clock', title='Fast clock', choices=[ + ce.Compound('NoClock', title='Disabled', attrs=[]), + ce.Compound('Stm32f2Clock', key='clock', title='Enabled', attrs=[ + ce.Integer(key='prescaler', title='Prescaler'), + ce.String(key='primary_timer', title='Timer'), + ]), + ]), + ]) + def platform_Stm32f4(): return ce.Compound('Stm32f4', attrs=[ ce.Compound('Stm32f4Clock', key='clock', title='Clock', collapsable=True, attrs=[ @@ -718,6 +757,7 @@ def editor(): platform_Teensy3(), platform_Avr('ATmega2560'), platform_Avr('ATmega1284p'), + platform_Stm32f2(), platform_Stm32f4(), platform_Linux(), ]), @@ -778,6 +818,7 @@ def editor(): ce.Compound('AvrSerial', title='AVR UART', attrs=[ ce.Boolean(key='DoubleSpeed'), ]), + ce.Compound('Stm32f2UsbSerial', title='STM32F2 USB', attrs=[]), ce.Compound('Stm32f4UsbSerial', title='STM32F4 USB', attrs=[]), ce.Compound('LinuxStdInOutSerial', title='Linux stdin/stdout', attrs=[]), ce.Compound('NullSerial', title='Null serial driver', attrs=[]), diff --git a/config_system/gui/init.js b/config_system/gui/init.js index 3ce40517..263fc1b0 100644 --- a/config_system/gui/init.js +++ b/config_system/gui/init.js @@ -168,6 +168,9 @@ function fixup_config(config) { "Mk20PinInputModePullDown": {"_compoundName": "Mk20PinInputMode", "PullMode": "Pull-down"}, "AvrPinInputModeNormal": {"_compoundName": "AvrPinInputMode", "PullMode": "Normal"}, "AvrPinInputModePullUp": {"_compoundName": "AvrPinInputMode", "PullMode": "Pull-up"}, + "Stm32f2PinInputModeNormal": {"_compoundName": "Stm32f2PinInputMode", "PullMode": "Normal"}, + "Stm32f2PinInputModePullUp": {"_compoundName": "Stm32f2PinInputMode", "PullMode": "Pull-up"}, + "Stm32f2PinInputModePullDown": {"_compoundName": "Stm32f2PinInputMode", "PullMode": "Pull-down"}, "Stm32f4PinInputModeNormal": {"_compoundName": "Stm32f4PinInputMode", "PullMode": "Normal"}, "Stm32f4PinInputModePullUp": {"_compoundName": "Stm32f4PinInputMode", "PullMode": "Pull-up"}, "Stm32f4PinInputModePullDown": {"_compoundName": "Stm32f4PinInputMode", "PullMode": "Pull-down"} diff --git a/flash.py b/flash.py index 7fc5bff8..91205cf0 100644 --- a/flash.py +++ b/flash.py @@ -65,6 +65,14 @@ def flash_cmds(self, opts): report_error('port specification is not supported by teensy-loader-cli') return [['teensy-loader-cli', '-mmcu=mk20dx256', opts['image_file']]] +class Stm32f2Type(object): + SUPPORTED_EXTENSIONS = ['.elf', '.bin'] + + def flash_cmds(self, opts): + program_file_arg = opts['image_file'] + address_arg = ' 0x08000000' if opts['extension'] == '.bin' else '' + return [['openocd', '-f', 'interface/stlink-v2.cfg', '-f', 'target/stm32f2x_stlink.cfg', '-c', 'program "{}" verify{}'.format(program_file_arg, address_arg), '-c', 'reset']] + class Stm32f4Type(object): SUPPORTED_EXTENSIONS = ['.elf', '.bin'] @@ -80,6 +88,7 @@ def flash_cmds(self, opts): 'arduino_due': ArduinoDueType, 'duet': DuetType, 'teensy3': Teensy3Type, + 'stm32f2': Stm32f2Type, 'stm32f4': Stm32f4Type, } diff --git a/nix/aprinter.nix b/nix/aprinter.nix index 6ab41fe2..2bcf5a17 100644 --- a/nix/aprinter.nix +++ b/nix/aprinter.nix @@ -23,7 +23,7 @@ */ { stdenv, writeText, bash, gcc-arm-embedded, clang-arm-embedded, avrgcclibc -, clang, asf, stm32cubef4, teensyCores +, clang, asf, stm32cubef2, stm32cubef4, teensyCores , aprinterSource, buildVars, extraSources , extraIncludePaths, defines, linkerSymbols , mainText, boardName, buildName, desiredOutputs @@ -68,12 +68,14 @@ let isAvr = board.platform == "avr"; - isArm = builtins.elem board.platform [ "sam3x" "teensy" "stm32f4" ]; + isArm = builtins.elem board.platform [ "sam3x" "teensy" "stm32f2" "stm32f4" ]; isLinux = board.platform == "linux"; needAsf = board.platform == "sam3x"; + needStm32CubeF2 = board.platform == "stm32f2"; + needStm32CubeF4 = board.platform == "stm32f4"; needTeensyCores = board.platform == "teensy"; @@ -84,6 +86,7 @@ let ${stdenv.lib.optionalString buildWithClang "BUILD_WITH_CLANG=1"} ${stdenv.lib.optionalString (buildWithClang && isArm) "CLANG_ARM_EMBEDDED=${clang-arm-embedded}/bin/"} ${stdenv.lib.optionalString needAsf "ASF_DIR=${asf}"} + ${stdenv.lib.optionalString needStm32CubeF2 "STM32CUBEF2_DIR=${stm32cubef2}"} ${stdenv.lib.optionalString needStm32CubeF4 "STM32CUBEF4_DIR=${stm32cubef4}"} ${stdenv.lib.optionalString needTeensyCores "TEENSY_CORES=${teensyCores}"} @@ -105,6 +108,7 @@ assert buildWithClang -> isArm || isLinux; assert buildWithClang && isArm -> clang-arm-embedded != null; assert buildWithClang && isLinux -> clang != null; assert needAsf -> asf != null; +assert needStm32CubeF2 -> stm32cubef2 != null; assert needStm32CubeF4 -> stm32cubef4 != null; assert needTeensyCores -> teensyCores != null; diff --git a/nix/boards.nix b/nix/boards.nix index 125b9719..13ecdf8b 100644 --- a/nix/boards.nix +++ b/nix/boards.nix @@ -90,6 +90,22 @@ rec { }; }; + stm32f205 = { + platform = "stm32f2"; + targetVars = { + STM_CHIP = "stm32f205"; + HSE_VALUE = "16000000"; + PLL_N_VALUE = "240"; + PLL_M_VALUE = "16"; + PLL_P_DIV_VALUE = "2"; + PLL_Q_DIV_VALUE = "5"; + APB1_PRESC_DIV = "4"; + APB2_PRESC_DIV = "2"; + USB_MODE = "FS"; + ENABLE_SDCARD = "YES"; + }; + }; + stm32f429 = { platform = "stm32f4"; targetVars = { diff --git a/nix/default.nix b/nix/default.nix index bd5932e6..4f83bc24 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -53,6 +53,10 @@ rec { /* Atmel Software Framework (chip support for Atmel ARM chips). */ asf = pkgs.callPackage ./asf.nix {}; + /* STM32CubeF2 (chip support for STM32F2). */ + stm32cubef2 = pkgs.callPackage ./stm32cubef2.nix {}; + /* stm32cubef2 = stdenv.lib.cleanSource /home/ambro/cube/STM32Cube_FW_F2_V1.7.0; */ + /* STM32CubeF4 (chip support for STM32F4). */ stm32cubef4 = pkgs.callPackage ./stm32cubef4.nix {}; /* stm32cubef4 = stdenv.lib.cleanSource /home/ambro/cube/STM32Cube_FW_F4_V1.5.0; */ @@ -63,7 +67,7 @@ rec { /* The primary APrinter build function. */ aprinterFunc = aprinterConfig@{ optimizeLibcForSize, ... }: pkgs.callPackage ./aprinter.nix ( { - inherit aprinterSource avrgcclibc asf stm32cubef4 teensyCores; + inherit aprinterSource avrgcclibc asf stm32cubef2 stm32cubef4 teensyCores; gcc-arm-embedded = if optimizeLibcForSize then gcc-arm-embedded-fromsrc-optsize else gcc-arm-embedded-fromsrc; clang-arm-embedded = if optimizeLibcForSize then clang-arm-embedded-optize else clang-arm-embedded; } // (removeAttrs aprinterConfig ["optimizeLibcForSize"]) @@ -96,6 +100,7 @@ rec { asf ]; buildDepsArmUncommon = [ + stm32cubef2 stm32cubef4 teensyCores gcc-arm-embedded-fromsrc-optsize diff --git a/nix/stm32cubef2.nix b/nix/stm32cubef2.nix new file mode 100644 index 00000000..e5ec422f --- /dev/null +++ b/nix/stm32cubef2.nix @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 Ambroz Bizjak + * Copyright (c) 2018 BOBAH + * All rights reserved. + * + * 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. + * + * 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 AUTHOR 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. + */ + +{ stdenv, fetchurl, unzip }: +let + source = fetchurl { + url = http://www.st.com/resource/en/firmware2/stm32cube_fw_f2_v170.zip; + sha256 = "2F7A2822BAF14150B662C9649ECD9F8333667A86C7AE1C924349C68AB58D58FE"; + }; + patchFiles = [ ../patches/stm32cubef2.patch ../patches/stm32cubef2-warnings.patch ]; +in +stdenv.mkDerivation rec { + name = "stm32cubef2"; + + unpackPhase = "true"; + + nativeBuildInputs = [ unzip ]; + + installPhase = '' + mkdir -p "$out"/EXTRACT + unzip -q ${source} -d "$out"/EXTRACT + mv "$out"/EXTRACT/STM32Cube*/* "$out"/ + rm -rf "$out"/EXTRACT + ${stdenv.lib.concatStrings (map (patchFile: "patch -d \"$out\" -p1 < ${patchFile}\n") patchFiles)} + ''; + + dontStrip = true; + dontPatchELF = true; + dontPatchShebangs = true; +} diff --git a/patches/stm32cubef2-warnings.patch b/patches/stm32cubef2-warnings.patch new file mode 100755 index 00000000..a2b87f61 --- /dev/null +++ b/patches/stm32cubef2-warnings.patch @@ -0,0 +1,603 @@ +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2c.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2c.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2c.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2c.h +@@ -432,7 +432,7 @@ typedef struct + */ + #define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_addr = 0x00U; \ ++ uint32_t tmpreg_addr = 0x00U; \ + tmpreg_addr = (__HANDLE__)->Instance->SR1; \ + tmpreg_addr = (__HANDLE__)->Instance->SR2; \ + UNUSED(tmpreg_addr); \ +@@ -445,7 +445,7 @@ typedef struct + */ + #define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_stop = 0x00U; \ ++ uint32_t tmpreg_stop = 0x00U; \ + tmpreg_stop = (__HANDLE__)->Instance->SR1; \ + (__HANDLE__)->Instance->CR1 |= I2C_CR1_PE; \ + UNUSED(tmpreg_stop); \ +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2s.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2s.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2s.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_i2s.h +@@ -328,7 +328,7 @@ typedef struct + */ + #define __HAL_I2S_CLEAR_OVRFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_ovr = 0x00U; \ ++ uint32_t tmpreg_ovr = 0x00U; \ + tmpreg_ovr = (__HANDLE__)->Instance->DR; \ + tmpreg_ovr = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_ovr ); \ +@@ -340,7 +340,7 @@ typedef struct + */ + #define __HAL_I2S_CLEAR_UDRFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_udr = 0x00U; \ ++ uint32_t tmpreg_udr = 0x00U; \ + tmpreg_udr = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_udr); \ + } while(0) +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_irda.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_irda.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_irda.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_irda.h +@@ -357,7 +357,7 @@ typedef struct + */ + #define __HAL_IRDA_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_pe = 0x00U; \ ++ uint32_t tmpreg_pe = 0x00U; \ + tmpreg_pe = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_pe); \ + } while(0) +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc.h +@@ -424,105 +424,105 @@ typedef struct + * @{ + */ + #define __HAL_RCC_GPIOA_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOAEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOB_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOBEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOC_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOD_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOE_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOEEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOEEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOF_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOFEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOFEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOG_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOGEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOGEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOH_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOHEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_GPIOI_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOIEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOIEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_CRC_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_BKPSRAM_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_BKPSRAMEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_BKPSRAMEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_DMA1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_DMA2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_USB_OTG_HS_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_OTGHSEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_OTGHSEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_OTGHSULPIEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_OTGHSULPIEN);\ +@@ -599,7 +599,7 @@ typedef struct + __HAL_RCC_SYSCFG_CLK_ENABLE();\ + }while(0) + #define __HAL_RCC_RNG_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN);\ +@@ -636,7 +636,7 @@ typedef struct + * @{ + */ + #define __HAL_RCC_FSMC_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);\ +@@ -668,161 +668,161 @@ typedef struct + * @{ + */ + #define __HAL_RCC_TIM2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM3_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM3EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM3EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM4_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM4EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM4EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM5_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM5EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM5EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM6_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM6EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM6EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM7_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM7EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM7EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM12_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM12EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM12EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM13_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM13EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM13EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM14_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM14EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM14EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_WWDG_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_WWDGEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_WWDGEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_SPI2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_SPI2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_SPI2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_SPI3_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_SPI3EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_SPI3EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_USART2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_USART2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_USART2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_USART3_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_USART3EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_USART3EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_UART4_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_UART4EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_UART4EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_UART5_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_UART5EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_UART5EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_I2C1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_I2C2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_I2C3_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C3EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_CAN1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_CAN1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_CAN1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_CAN2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_CAN2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_CAN2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_PWR_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_DAC_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB1ENR, RCC_APB1ENR_DACEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_DACEN);\ +@@ -922,70 +922,70 @@ typedef struct + * @{ + */ + #define __HAL_RCC_TIM1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM8_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_USART1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_USART6_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART6EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART6EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_ADC1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_ADC2_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC2EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC2EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_ADC3_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC3EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC3EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_SDIO_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SDIOEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDIOEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_SPI1_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_SYSCFG_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN);\ +@@ -993,21 +993,21 @@ typedef struct + } while(0) + + #define __HAL_RCC_TIM9_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM9EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM9EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM10_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM10EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM10EN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_TIM11_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00U; \ ++ uint32_t tmpreg = 0x00U; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM11EN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM11EN);\ +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc_ex.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc_ex.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc_ex.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_rcc_ex.h +@@ -137,28 +137,28 @@ typedef struct + */ + #if defined(STM32F207xx) || defined(STM32F217xx) + #define __HAL_RCC_ETHMAC_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_ETHMACTX_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACTXEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACTXEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_ETHMACRX_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACRXEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACRXEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_ETHMACPTP_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACPTPEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ETHMACPTPEN);\ +@@ -225,7 +225,7 @@ typedef struct + */ + #if defined(STM32F207xx) || defined(STM32F217xx) + #define __HAL_RCC_DCMI_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN);\ +@@ -237,14 +237,14 @@ typedef struct + + #if defined(STM32F215xx) || defined(STM32F217xx) + #define __HAL_RCC_CRYP_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_CRYPEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_CRYPEN);\ + UNUSED(tmpreg); \ + } while(0) + #define __HAL_RCC_HASH_CLK_ENABLE() do { \ +- __IO uint32_t tmpreg = 0x00; \ ++ uint32_t tmpreg = 0x00; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN);\ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN);\ +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_smartcard.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_smartcard.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_smartcard.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_smartcard.h +@@ -442,7 +442,7 @@ typedef struct + */ + #define __HAL_SMARTCARD_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_pe = 0x00U; \ ++ uint32_t tmpreg_pe = 0x00U; \ + tmpreg_pe = (__HANDLE__)->Instance->SR; \ + tmpreg_pe = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg_pe); \ +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_spi.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_spi.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_spi.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_spi.h +@@ -367,7 +367,7 @@ typedef struct __SPI_HandleTypeDef + */ + #define __HAL_SPI_CLEAR_MODFFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_modf = 0x00U; \ ++ uint32_t tmpreg_modf = 0x00U; \ + tmpreg_modf = (__HANDLE__)->Instance->SR; \ + (__HANDLE__)->Instance->CR1 &= (~SPI_CR1_SPE); \ + UNUSED(tmpreg_modf); \ +@@ -380,7 +380,7 @@ typedef struct __SPI_HandleTypeDef + */ + #define __HAL_SPI_CLEAR_OVRFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_ovr = 0x00U; \ ++ uint32_t tmpreg_ovr = 0x00U; \ + tmpreg_ovr = (__HANDLE__)->Instance->DR; \ + tmpreg_ovr = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_ovr); \ +@@ -393,7 +393,7 @@ typedef struct __SPI_HandleTypeDef + */ + #define __HAL_SPI_CLEAR_FREFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_fre = 0x00U; \ ++ uint32_t tmpreg_fre = 0x00U; \ + tmpreg_fre = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_fre); \ + }while(0) +diff -ruNp a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_uart.h b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_uart.h +--- a/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_uart.h ++++ b/Drivers/STM32F2xx_HAL_Driver/Inc/stm32f2xx_hal_uart.h +@@ -419,7 +419,7 @@ typedef struct + */ + #define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ +- __IO uint32_t tmpreg_pe = 0x00U; \ ++ uint32_t tmpreg_pe = 0x00U; \ + tmpreg_pe = (__HANDLE__)->Instance->SR; \ + tmpreg_pe = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg_pe); \ diff --git a/patches/stm32cubef2.patch b/patches/stm32cubef2.patch new file mode 100755 index 00000000..7a988bb5 --- /dev/null +++ b/patches/stm32cubef2.patch @@ -0,0 +1,103 @@ +diff --git a/Drivers/CMSIS/Include/cmsis_gcc.h b/Drivers/CMSIS/Include/cmsis_gcc.h +--- a/Drivers/CMSIS/Include/cmsis_gcc.h ++++ b/Drivers/CMSIS/Include/cmsis_gcc.h +@@ -337,7 +337,11 @@ + #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); ++#ifdef __clang__ ++ __builtin_arm_set_fpscr(fpscr); ++#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); ++#endif + __ASM volatile (""); + #endif + } +diff --git a/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_usb.c b/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_usb.c +--- a/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_usb.c ++++ b/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_ll_usb.c +@@ -55,6 +55,7 @@ + + /* Includes ------------------------------------------------------------------*/ + #include "stm32f2xx_hal.h" ++#include + + /** @addtogroup STM32F2xx_LL_USB_DRIVER + * @{ +@@ -766,7 +767,9 @@ + count32b = (len + 3U) / 4U; + for (i = 0U; i < count32b; i++, src += 4U) + { +- USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src); ++ uint32_t val; ++ memcpy(&val, src, sizeof(val)); ++ USBx_DFIFO(ch_ep_num) = val; + } + } + return HAL_OK; +@@ -792,8 +795,8 @@ + + for ( i = 0U; i < count32b; i++, dest += 4U ) + { +- *(__packed uint32_t *)dest = USBx_DFIFO(0U); +- ++ uint32_t val = USBx_DFIFO(0U); ++ memcpy(dest, &val, sizeof(val)); + } + return ((void *)dest); + } +diff --git a/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h b/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h +--- a/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h ++++ b/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h +@@ -104,7 +104,7 @@ + int8_t (* DeInit) (void); + int8_t (* Control) (uint8_t, uint8_t * , uint16_t); + int8_t (* Receive) (uint8_t *, uint32_t *); +- ++ void (* TxCompleted) (void); + }USBD_CDC_ItfTypeDef; + + +@@ -159,6 +159,8 @@ + uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev); + + uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev); ++ ++uint8_t USBD_CDC_CheckTxBusy (USBD_HandleTypeDef *pdev); + /** + * @} + */ +diff --git a/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +--- a/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c ++++ b/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +@@ -669,6 +669,8 @@ + { + + hcdc->TxState = 0; ++ ++ ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->TxCompleted(); + + return USBD_OK; + } +@@ -869,6 +871,21 @@ + } + else + { ++ return USBD_FAIL; ++ } ++} ++ ++ ++uint8_t USBD_CDC_CheckTxBusy(USBD_HandleTypeDef *pdev) ++{ ++ USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; ++ ++ if(pdev->pClassData != NULL) ++ { ++ return hcdc->TxState == 0 ? USBD_OK : USBD_BUSY; ++ } ++ else ++ { + return USBD_FAIL; + } + } diff --git a/scripts/build-arm-stm32f2.sh b/scripts/build-arm-stm32f2.sh new file mode 100755 index 00000000..6e068206 --- /dev/null +++ b/scripts/build-arm-stm32f2.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2014 Bernard `Guyzmo` Pratz +# Copyright (c) 2017 Ambroz Bizjak +# Copyright (c) 2018 BOBAH +# All rights reserved. +# +# 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. +# +# 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 AUTHOR 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. +# +##################################################################################### +# STM32F2 SPECIFIC STUFF + +configure_stm32f2() { + CMSIS_DIR=${STM32CUBEF2_DIR}/Drivers/CMSIS/Device/ST/STM32F2xx + TEMPLATES_DIR=${CMSIS_DIR}/Source/Templates + HAL_DIR=${STM32CUBEF2_DIR}/Drivers/STM32F2xx_HAL_Driver + USB_DIR=${STM32CUBEF2_DIR}/Middlewares/ST/STM32_USB_Device_Library + + ARM_CPU=cortex-m3 + + if [[ $STM_CHIP = "stm32f205" ]]; then + CHIP_FLAGS=( -DSTM32F205xx ) + STARTUP_ASM_FILE=startup_stm32f205xx.s + else + fail "Unsupported STM_CHIP (${STM_CHIP})" + fi + + LINKER_SCRIPT=${ROOT}/aprinter/platform/stm32f2/${STM_CHIP}.ld + + configure_arm + + USB_FLAGS=() + USB_C_SOURCES=() + if [[ -n $USB_MODE ]]; then + USB_FLAGS=( -DAPRINTER_ENABLE_USB ) + USB_C_SOURCES=( + "${HAL_DIR}/Src/stm32f2xx_hal_pcd.c" + "${HAL_DIR}/Src/stm32f2xx_hal_pcd_ex.c" + "${HAL_DIR}/Src/stm32f2xx_ll_usb.c" + "${USB_DIR}/Core/Src/usbd_core.c" + "${USB_DIR}/Core/Src/usbd_ctlreq.c" + "${USB_DIR}/Core/Src/usbd_ioreq.c" + "${USB_DIR}/Class/CDC/Src/usbd_cdc.c" + "${ROOT}/aprinter/platform/stm32f2/usbd_conf.c" + "${ROOT}/aprinter/platform/stm32f2/usbd_desc.c" + ) + + if [[ $USB_MODE = "FS" ]]; then + USB_FLAGS=( "${USB_FLAGS[@]}" -DUSE_USB_FS ) + elif [[ $USB_MODE = "HS" ]]; then + USB_FLAGS=( "${USB_FLAGS[@]}" -DUSE_USB_HS ) + elif [[ $USB_MODE = "HS-in-FS" ]]; then + USB_FLAGS=( "${USB_FLAGS[@]}" -DUSE_USB_HS -DUSE_USB_HS_IN_FS ) + else + fail "Invalid USB_MODE" + fi + fi + + SDCARD_C_SOURCES=() + if [[ -n $ENABLE_SDCARD ]]; then + SDCARD_C_SOURCES=( + "${HAL_DIR}/Src/stm32f2xx_hal_sd.c" + "${HAL_DIR}/Src/stm32f2xx_ll_sdmmc.c" + ) + fi + + FLAGS_C_CXX_LD+=( + #-mfpu=fpv4-sp-d16 -mfloat-abi=soft + ) + FLAGS_C_CXX+=( + "${CHIP_FLAGS[@]}" + -DUSE_HAL_DRIVER -DHEAP_SIZE=16384 + -DHSE_VALUE=${HSE_VALUE} -DPLL_N_VALUE=${PLL_N_VALUE} -DPLL_M_VALUE=${PLL_M_VALUE} + -DPLL_P_DIV_VALUE=${PLL_P_DIV_VALUE} -DPLL_Q_DIV_VALUE=${PLL_Q_DIV_VALUE} + -DAPB1_PRESC_DIV=${APB1_PRESC_DIV} -DAPB2_PRESC_DIV=${APB2_PRESC_DIV} + "${USB_FLAGS[@]}" + -I "${ROOT}/aprinter/platform/stm32f2" + -I "${CMSIS_DIR}/Include" + -I "${STM32CUBEF2_DIR}/Drivers/CMSIS/Include" + -I "${HAL_DIR}/Inc" + -I "${USB_DIR}/Core/Inc" + -I "${USB_DIR}/Class/CDC/Inc" + ) + + CXX_SOURCES+=( + "${ROOT}/aprinter/platform/stm32f2/stm32f2_support.cpp" + ) + C_SOURCES+=( + "${TEMPLATES_DIR}/system_stm32f2xx.c" + "${HAL_DIR}/Src/stm32f2xx_hal.c" + "${HAL_DIR}/Src/stm32f2xx_hal_cortex.c" + "${HAL_DIR}/Src/stm32f2xx_hal_rcc.c" + "${HAL_DIR}/Src/stm32f2xx_hal_iwdg.c" + "${HAL_DIR}/Src/stm32f2xx_hal_gpio.c" + "${HAL_DIR}/Src/stm32f2xx_hal_dma.c" + "${ROOT}/aprinter/platform/newlib_common.c" + "${USB_C_SOURCES[@]}" "${SDCARD_C_SOURCES[@]}" + ) + ASM_SOURCES+=( + "${TEMPLATES_DIR}/gcc/${STARTUP_ASM_FILE}" + ) + + # define target functions + RUNBUILD=build_stm32f2 + CHECK=check_depends_stm32f2 +} + +build_stm32f2() { + build_arm +} + +check_depends_stm32f2() { + check_depends_arm + [ -d "${STM32CUBEF2_DIR}" ] || fail "STM32F2 framework missing in dependences" +} diff --git a/test-commands.txt b/test-commands.txt index 14e3078d..7ce82ee9 100644 --- a/test-commands.txt +++ b/test-commands.txt @@ -12,6 +12,7 @@ nix-build nix/ -A aprinterWebif -o ~/aprinter-webif python -B flash.py -f ~/aprinter-build/aprinter.bin -t duet python -B flash.py -f ~/aprinter-build/aprinter.bin -t arduino_due python -B flash.py -f ~/aprinter-build/aprinter.hex -t arduino_mega +python -B flash.py -f ~/aprinter-build/aprinter.elf -t stm32f2 python -B flash.py -f ~/aprinter-build/aprinter.elf -t stm32f4 python -B flash.py -f ~/aprinter-build/aprinter.hex -t teensy3 python -B flash.py -f ~/aprinter-build/aprinter.hex -t melzi_programmer @@ -19,6 +20,8 @@ python -B flash.py -f ~/aprinter-build/aprinter.hex -t melzi_programmer # OpenOCD # Note, if using SWO, need to actually read it. # For SWO you first need this: "mkfifo ~/swo". +# STM32F2-CNC: +openocd -f interface/stlink-v2.cfg -f target/stm32f2x_stlink.cfg -c 'tpiu config internal /home/ambro/swo uart off 168000000' # STM32F4-Discovery: openocd -f interface/stlink-v2.cfg -f target/stm32f4x_stlink.cfg -c 'tpiu config internal /home/ambro/swo uart off 168000000' # Teensy3 with Discovery: