From 13825e068ca3035fd67d16ac8a7d529139659bf8 Mon Sep 17 00:00:00 2001 From: Razvalyaev Date: Thu, 19 Dec 2024 13:57:51 +0300 Subject: [PATCH] =?UTF-8?q?#3=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5?= =?UTF-8?q?=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20=D1=83=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BB?= =?UTF-8?q?=D1=8E=D1=87=D0=B0=D0=BC=D0=B8,=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BD=D0=B0=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B9=D0=BA=D0=B8=20=D0=BF=D0=BE=20=D1=82=D0=B0=D0=B9?= =?UTF-8?q?=D0=BC=D0=B8=D0=BD=D0=B3=D0=B0=D0=BC=20=D0=B2=20tester=5Fconfig?= =?UTF-8?q?.h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit По переключениям: -Теперь для двух ключей одного питания должен быть один порт - Добавлена функция реконнекта питания TESTER_Reconnect_Power(), чтобы быстрее переключать с положительного на отрицательный. А не через отдельные функции TESTER_Disconnect_Power(), TESTER_Connect_Power() - Сделан дефайн USE_HAL_GPIO_FUNCTIONS для испольщования HAL GPIO функций. Его можно убрать и пины будуте переключаться напрямую через BSRR. - Также сделан дефайн ALL_SW_USE_SAME_PORT, чтобы переключать все 4 пина в BSRR в одну комманду Это поможет в случае функции реконнекта, где HAL функции сначала отключают питание, а потом подключат другое. Из-за этого появляются задержки в 580 мкс (SW Timings with HAL GPIO write.sal), Если убрать USE_HAL_GPIO_FUNCTIONS, то сократиться время переключения между питаниями до 160мкс (SW Timings without HAL GPIO write and different ports.sal) А если еще выставить ALL_SW_USE_SAME_PORT, то через BSRR будет выставлятся все 4 пина, и задержек нет (SW Timings without HAL GPIO write.sal). Ну почти, иногда проскакивают 2 мкс (SW Timings without HAL GPIO write 2.sal) --- diode_tester/Core/Src/gpio.c | 11 +++ diode_tester/Core/Tester_main/tester_config.h | 60 ++++++++++-- diode_tester/Core/Tester_main/tester_func.c | 90 ++++++++++++++---- diode_tester/Core/Tester_main/tester_func.h | 12 +-- diode_tester/Core/Tester_main/tester_main.c | 4 +- diode_tester/diode_tester.ioc | 28 ++++-- docs/SW Timings with HAL GPIO write.sal | Bin 0 -> 40613 bytes docs/SW Timings without HAL GPIO write 2.sal | Bin 0 -> 10655 bytes ...out HAL GPIO write and different ports.sal | Bin 0 -> 7309 bytes docs/SW Timings without HAL GPIO write.sal | Bin 0 -> 6335 bytes 10 files changed, 164 insertions(+), 41 deletions(-) create mode 100644 docs/SW Timings with HAL GPIO write.sal create mode 100644 docs/SW Timings without HAL GPIO write 2.sal create mode 100644 docs/SW Timings without HAL GPIO write and different ports.sal create mode 100644 docs/SW Timings without HAL GPIO write.sal diff --git a/diode_tester/Core/Src/gpio.c b/diode_tester/Core/Src/gpio.c index 22e2660..c32177f 100644 --- a/diode_tester/Core/Src/gpio.c +++ b/diode_tester/Core/Src/gpio.c @@ -48,10 +48,14 @@ void MX_GPIO_Init(void) __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11, GPIO_PIN_RESET); + /*Configure GPIO pin : PC13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; @@ -59,6 +63,13 @@ void MX_GPIO_Init(void) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + /*Configure GPIO pins : PB0 PB1 PB10 PB11 */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_10|GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } /* USER CODE BEGIN 2 */ diff --git a/diode_tester/Core/Tester_main/tester_config.h b/diode_tester/Core/Tester_main/tester_config.h index 9f5ff81..e97c5e0 100644 --- a/diode_tester/Core/Tester_main/tester_config.h +++ b/diode_tester/Core/Tester_main/tester_config.h @@ -11,8 +11,50 @@ #ifndef _TESTER_CONFIG_H_ #define _TESTER_CONFIG_H_ + #define TESTER_PULES_EXPETCED_WIDTH 4 ///< Предполагаемая длительность пика в отчетах ацп +/** + * @addtogroup TESTER_SW_TIMINGS_CONFIG Configs for switching timings + * @ingroup TESTER_CONFIGS + * @brief Конфигурации таймингов для ключей питания + @{ + */ + +/** + * @brief Задержка (миллисекундная) для положительного напряжения ПО УМОЛЧАНИЮ + * @details Пока только миллисекунды, т.к. меньше я пока не реализовал, да и как понимаю не требуется + */ +#define DEF_MS_TIME_FOR_POSITIVE 1000 + +/** + * @brief Задержка перед началом тестирования ПО УМОЛЧАНИЮ + * @details Задержка миллисекундная или тики for() @ref TIME_BEFORE_TEST_MS_DELAY + */ +#define DEF_TIME_BEFORE_TEST 500 +#define DEF_TIME_BEFORE_TEST_MS_DELAY 1 ///< включение миллисекундной задержки для @ref TIME_BEFORE_TEST по умолчанию + +/** + * @brief Задержка между включением АЦП и предполагаемым скачком напряжения ПО УМОЛЧАНИЮ + * @details Задержка нужна, чтобы точно поймать его в буфере АЦП. + * + * Задержка миллисекундная или тики for() @ref TIME_BEFORE_TEST_MS_DELAY + * @note Но если миллисекундная, то скорее всего скачок не попадет в буфер АЦП. + * Поэтому желательно только тики for() (@ref TIME_BEFORE_PEAK_MS_DELAY = 0) + */ +#define DEF_TIME_BEFORE_PEAK 5 +#define DEF_TIME_BEFORE_PEAK_MS_DELAY 0 ///< включение миллисекундной задержки для @ref TIME_BEFORE_PEAK(0 - задержка for(), 1 - миллисекундная) + +/** + * @brief Задержка перед окончанием тестирования (отключение питания) ПО УМОЛЧАНИЮ + * @details Задержка миллисекундная или тики for() @ref TIME_BEFORE_DISCONNECT_MS_DELAY + */ +#define DEF_TIME_BEFORE_DISCONNECT 50 +#define DEF_TIME_BEFORE_DISCONNECT_MS_DELAY 1 ///< включение миллисекундной задержки для @ref TIME_BEFORE_DISCONNECT (0 - задержка for(), 1 - миллисекундная) + +/** TESTER_SW_TIMINGS_CONFIG + * @} + */ /** * @addtogroup TESTER_POWER_SW_CONFIG Configs for switches for power @@ -20,28 +62,28 @@ * @brief Конфигурации для ключей питания @{ */ +//#define USE_HAL_GPIO_FUNCTIONS ///< Использовать для переключения пинов HAL функции +//#define ALL_SW_USE_SAME_PORT ///< Дефайн указывающий что все пины будут иметь один порт (для ускорения переключения) /* Состояния ключей для подключения и откючения питания */ #define POWER_CONNECT 1 ///< Питание подключено в данном состоянии пина #define POWER_DISCONNECT 0 ///< Питание отключено в данном состоянии пина /* Ключи для подключения положительного питания к диоду */ -#define SWITCH_DC_POSITIVE_1_Port GPIOC ///< Порт пина первого ключа для положительного питания -#define SWITCH_DC_POSITIVE_1_Pin GPIO_PIN_13 ///< Пин первого ключа для положительного питания -#define SWITCH_DC_POSITIVE_2_Port GPIOA ///< Порт пина второго ключа для положительного питания -#define SWITCH_DC_POSITIVE_2_Pin GPIO_PIN_11 ///< Пин второго ключа для положительного питания +#define SWITCH_DC_POSITIVE_Port GPIOB ///< Порт пина первого ключа для земли положительного источника питания +#define SWITCH_DC_POSITIVE_GND_Pin GPIO_PIN_10 ///< Пин первого ключа для земли положительного источника питания +#define SWITCH_DC_POSITIVE_VDD_Pin GPIO_PIN_11 ///< Пин второго ключа для напряжения положительного источника ппитания /* Ключи для подключения отрицательного питания к диоду */ -#define SWITCH_DC_NEGATIVE_1_Port GPIOC ///< Порт пина первого ключа для отрицательного питания -#define SWITCH_DC_NEGATIVE_1_Pin GPIO_PIN_13 ///< Пин первого ключа для отрицательного питания -#define SWITCH_DC_NEGATIVE_2_Port GPIOA ///< Порт пина второго ключа для отрицательного питания -#define SWITCH_DC_NEGATIVE_2_Pin GPIO_PIN_11 ///< Пин первого ключа для отрицательного питания +#define SWITCH_DC_NEGATIVE_Port GPIOB ///< Порт пина первого ключа для земли отрицательного источника ппитания +#define SWITCH_DC_NEGATIVE_GND_Pin GPIO_PIN_0 ///< Пин первого ключа для земли отрицательного источника ппитания +#define SWITCH_DC_NEGATIVE_VDD_Pin GPIO_PIN_1 ///< Пин первого ключа для напряжения отрицательного источника ппитания /** TESTER_POWER_SW_CONFIG * @} */ - + /** * @addtogroup TESTER_ADC_CONFIG Configs for ADC * @ingroup TESTER_CONFIGS diff --git a/diode_tester/Core/Tester_main/tester_func.c b/diode_tester/Core/Tester_main/tester_func.c index e0c1caf..ec25a09 100644 --- a/diode_tester/Core/Tester_main/tester_func.c +++ b/diode_tester/Core/Tester_main/tester_func.c @@ -7,20 +7,35 @@ TESTER_TestHandleTypeDef hTestDiode; */ void TESTER_HandleInit(TESTER_TestHandleTypeDef *htest) { - htest->adc = &tester_adc; - + /* Настройка структуры АЦП */ + htest->adc = &tester_adc; TESTER_ADC_StructInit(htest->adc); - htest->DCNegSw.SW1_Port = SWITCH_DC_NEGATIVE_1_Port; - htest->DCNegSw.SW2_Port = SWITCH_DC_NEGATIVE_2_Port; - htest->DCNegSw.SW1_Pin = SWITCH_DC_NEGATIVE_1_Pin; - htest->DCNegSw.SW2_Pin = SWITCH_DC_NEGATIVE_2_Pin; + /* Настройка пинов для подключения отрицательного источника */ + htest->DCNegSw.SW_Port = SWITCH_DC_NEGATIVE_Port; + htest->DCNegSw.SwGND_Pin = SWITCH_DC_NEGATIVE_GND_Pin; + htest->DCNegSw.SwVDD_Pin = SWITCH_DC_NEGATIVE_VDD_Pin; + + /* Настройка пинов для подключения положительного источника */ + htest->DCPosSw.SW_Port = SWITCH_DC_POSITIVE_Port; + htest->DCPosSw.SwGND_Pin = SWITCH_DC_POSITIVE_GND_Pin; + htest->DCPosSw.SwVDD_Pin = SWITCH_DC_POSITIVE_VDD_Pin; - htest->DCPosSw.SW1_Port = SWITCH_DC_POSITIVE_1_Port; - htest->DCPosSw.SW2_Port = SWITCH_DC_POSITIVE_2_Port; - htest->DCPosSw.SW1_Pin = SWITCH_DC_POSITIVE_1_Pin; - htest->DCPosSw.SW2_Pin = SWITCH_DC_POSITIVE_2_Pin; + /* Настройка таймингов по умолчанию для тестирования */ + htest->SwTimings.msticks_for_positive_dc = DEF_MS_TIME_FOR_POSITIVE; + + htest->SwTimings.ticks_before_disconnect.ticks = DEF_TIME_BEFORE_DISCONNECT; + htest->SwTimings.ticks_before_disconnect.msdelay = DEF_TIME_BEFORE_DISCONNECT_MS_DELAY; + + htest->SwTimings.ticks_before_go_to_peak.ticks = DEF_TIME_BEFORE_PEAK; + htest->SwTimings.ticks_before_go_to_peak.msdelay = DEF_TIME_BEFORE_PEAK_MS_DELAY; + + htest->SwTimings.ticks_before_test.ticks = DEF_TIME_BEFORE_TEST; + htest->SwTimings.ticks_before_test.msdelay = DEF_TIME_BEFORE_TEST_MS_DELAY; + + + htest->continuous_buff_size = 20; } @@ -109,8 +124,7 @@ void TESTER_TestDiode_PosNegPower(TESTER_TestHandleTypeDef *htest) TESTER_Delay(&htest->SwTimings.ticks_before_go_to_peak); /* Отключение питания от диода */ - TESTER_Disconnect_Power(&htest->DCPosSw); - TESTER_Connect_Power(&htest->DCNegSw); + TESTER_Reconnect_Power(&htest->DCPosSw, &htest->DCNegSw); /* Подключение отрицательного питания на определенное время */ TESTER_Delay(&htest->SwTimings.ticks_before_disconnect); @@ -128,18 +142,62 @@ void TESTER_TestDiode_PosNegPower(TESTER_TestHandleTypeDef *htest) */ void TESTER_Connect_Power(TESTER_PowerSwitchTypeDef *DCSw) { - HAL_GPIO_WritePin(DCSw->SW1_Port, DCSw->SW1_Pin, POWER_CONNECT); - HAL_GPIO_WritePin(DCSw->SW2_Port, DCSw->SW2_Pin, POWER_CONNECT); +#ifdef USE_HAL_GPIO_FUNCTIONS // in tester_config.h + HAL_GPIO_WritePin(DCSw->SW_Port, DCSw->SwGND_Pin | DCSw->SwVDD_Pin, POWER_CONNECT); +#else // USE_HAL_GPIO_FUNCTIONS + #if (POWER_CONNECT == 1) + DCSw->SW_Port->BSRR = DCSw->SwGND_Pin | DCSw->SwVDD_Pin; + #else //POWER_CONNECT == 1 + DCSw->SW_Port->BSRR = (DCSw->SwGND_Pin | DCSw->SwVDD_Pin) << 16; + #endif //POWER_CONNECT == 1 +#endif //USE_HAL_GPIO_FUNCTIONS } /** * @brief Отключить питание с помощью ключей (пинов) в TESTER_PowerSwitchTypeDef */ void TESTER_Disconnect_Power(TESTER_PowerSwitchTypeDef *DCSw) { - HAL_GPIO_WritePin(DCSw->SW1_Port, DCSw->SW1_Pin, POWER_DISCONNECT); - HAL_GPIO_WritePin(DCSw->SW2_Port, DCSw->SW2_Pin, POWER_DISCONNECT); +#ifdef USE_HAL_GPIO_FUNCTIONS + HAL_GPIO_WritePin(DCSw->SW_Port, DCSw->SwGND_Pin | DCSw->SwVDD_Pin, POWER_DISCONNECT); +#else // USE_HAL_GPIO_FUNCTIONS + #if (POWER_DISCONNECT == 0) + DCSw->SW_Port->BSRR = (DCSw->SwGND_Pin | DCSw->SwVDD_Pin) << 16; + #else //POWER_CONNECT == 1 + DCSw->SW_Port->BSRR = DCSw->SwGND_Pin | DCSw->SwVDD_Pin; + #endif //POWER_CONNECT == 1 +#endif //USE_HAL_GPIO_FUNCTIONS } +/** +* @brief Переключить питание с помощью ключей (пинов) в TESTER_PowerSwitchTypeDef + */ +void TESTER_Reconnect_Power(TESTER_PowerSwitchTypeDef *DCPosSw, TESTER_PowerSwitchTypeDef *DCNegSw) +{ +#ifdef USE_HAL_GPIO_FUNCTIONS + HAL_GPIO_WritePin(DCPosSw->SW_Port, DCPosSw->SwGND_Pin | DCPosSw->SwVDD_Pin, POWER_DISCONNECT); + HAL_GPIO_WritePin(DCNegSw->SW_Port, DCNegSw->SwGND_Pin | DCNegSw->SwVDD_Pin, POWER_CONNECT); +#else // USE_HAL_GPIO_FUNCTIONS + #ifdef ALL_SW_USE_SAME_PORT + #if (POWER_CONNECT == 1) && (POWER_DISCONNECT == 0) + DCPosSw->SW_Port->BSRR = ((DCNegSw->SwGND_Pin | DCNegSw->SwVDD_Pin) | ((DCPosSw->SwGND_Pin | DCPosSw->SwVDD_Pin) << 16)); + #elif (POWER_CONNECT == 1) && (POWER_DISCONNECT == 0) + DCPosSw->SW_Port->BSRR = (((DCNegSw->SwGND_Pin | DCNegSw->SwVDD_Pin) << 16)| (DCPosSw->SwGND_Pin | DCPosSw->SwVDD_Pin)); + #endif //POWER_CONNECT && POWER_DISCONNECT + #else //ALL_SW_USE_SAME_PORT + #if (POWER_DISCONNECT == 0) + DCPosSw->SW_Port->BSRR = (DCPosSw->SwGND_Pin | DCPosSw->SwVDD_Pin) << 16; + #else //POWER_DISCONNECT == 1 + DCPosSw->SW_Port->BSRR = DCPosSw->SwGND_Pin | DCPosSw->SwVDD_Pin; + #endif //POWER_DISCONNECT + + #if (POWER_CONNECT == 1) + DCNegSw->SW_Port->BSRR = DCNegSw->SwGND_Pin | DCNegSw->SwVDD_Pin; + #else //POWER_CONNECT == 0 + DCNegSw->SW_Port->BSRR = (DCNegSw->SwGND_Pin | DCNegSw->SwVDD_Pin) << 16; + #endif //POWER_CONNECT + #endif //ALL_SW_USE_SAME_PORT +#endif //USE_HAL_GPIO_FUNCTIONS +} /** * @brief Формирование задержки (в тиках или миллисекундная) */ diff --git a/diode_tester/Core/Tester_main/tester_func.h b/diode_tester/Core/Tester_main/tester_func.h index 1d00537..6d7e14b 100644 --- a/diode_tester/Core/Tester_main/tester_func.h +++ b/diode_tester/Core/Tester_main/tester_func.h @@ -19,11 +19,9 @@ */ typedef struct { - GPIO_TypeDef *SW1_Port; ///< Порт пина первого ключа для питания - uint32_t SW1_Pin; ///< Пин первого ключа для питания - - GPIO_TypeDef *SW2_Port; ///< Порт пина второго ключа для питания - uint32_t SW2_Pin; ///< Пин второго ключа для питания + GPIO_TypeDef *SW_Port; ///< Порт первого ключа для питания + uint32_t SwGND_Pin; ///< Пин первого ключа для питания + uint32_t SwVDD_Pin; ///< Пин второго ключа для питания }TESTER_PowerSwitchTypeDef; @@ -43,8 +41,8 @@ typedef struct { uint32_t msticks_for_positive_dc; ///< миллисекундная задержка для положительного напряжения @ref TESTER_TestDiode_PositivePower TESTER_TicksDelayTypeDef ticks_before_test; ///< задержка перед началом тестирования (мс или тики for()) - TESTER_TicksDelayTypeDef ticks_before_disconnect; ///< задержка перед выключением питания (мс или тики for()) TESTER_TicksDelayTypeDef ticks_before_go_to_peak; ///< задержка между включением АЦП и предполагаемым скачком напряжения, чтобы точно поймать его в буфере АЦП (мс или тики for()) + TESTER_TicksDelayTypeDef ticks_before_disconnect; ///< задержка перед выключением питания (мс или тики for()) }TESTER_SwitchTimingsTypeDef; /** @@ -81,6 +79,8 @@ void TESTER_TestDiode_PosNegPower(TESTER_TestHandleTypeDef *htest); void TESTER_Connect_Power(TESTER_PowerSwitchTypeDef *DCSw); /* Отключить питание с помощью ключей (пинов) в TESTER_PowerSwitchTypeDef */ void TESTER_Disconnect_Power(TESTER_PowerSwitchTypeDef *DCSw); +/* Переключить питание с помощью ключей (пинов) в TESTER_PowerSwitchTypeDef */ +void TESTER_Reconnect_Power(TESTER_PowerSwitchTypeDef *DCPosSw, TESTER_PowerSwitchTypeDef *DCNegSw); /* Формирование задержки перед подключением питания (в тиках или миллисекундная) */ void TESTER_Delay(TESTER_TicksDelayTypeDef *tickdelay); #endif //_TESTER_FUNC_H_ diff --git a/diode_tester/Core/Tester_main/tester_main.c b/diode_tester/Core/Tester_main/tester_main.c index bbfaa31..ee35793 100644 --- a/diode_tester/Core/Tester_main/tester_main.c +++ b/diode_tester/Core/Tester_main/tester_main.c @@ -10,9 +10,9 @@ TESTER_ProjectTypeDef TESTER; void TESTER_Init(TESTER_ProjectTypeDef *tester) { tester->delay = 250; - tester->delay_en = 1; + tester->delay_en = 0; - tester->func.disable_reset_call = 1; + tester->func.disable_reset_call = 0; tester->htest = &hTestDiode; TESTER_HandleInit(tester->htest); } diff --git a/diode_tester/diode_tester.ioc b/diode_tester/diode_tester.ioc index 0562454..cb8431c 100644 --- a/diode_tester/diode_tester.ioc +++ b/diode_tester/diode_tester.ioc @@ -39,16 +39,20 @@ Mcu.Name=STM32F103C(4-6)Tx Mcu.Package=LQFP48 Mcu.Pin0=PC13-TAMPER-RTC Mcu.Pin1=PD0-OSC_IN -Mcu.Pin10=VP_TIM3_VS_ClockSourceINT +Mcu.Pin10=PA13 +Mcu.Pin11=PA14 +Mcu.Pin12=VP_SYS_VS_Systick +Mcu.Pin13=VP_TIM2_VS_ClockSourceINT +Mcu.Pin14=VP_TIM3_VS_ClockSourceINT Mcu.Pin2=PD1-OSC_OUT Mcu.Pin3=PA0-WKUP -Mcu.Pin4=PA9 -Mcu.Pin5=PA10 -Mcu.Pin6=PA13 -Mcu.Pin7=PA14 -Mcu.Pin8=VP_SYS_VS_Systick -Mcu.Pin9=VP_TIM2_VS_ClockSourceINT -Mcu.PinsNb=11 +Mcu.Pin4=PB0 +Mcu.Pin5=PB1 +Mcu.Pin6=PB10 +Mcu.Pin7=PB11 +Mcu.Pin8=PA9 +Mcu.Pin9=PA10 +Mcu.PinsNb=15 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F103C6Tx @@ -78,6 +82,14 @@ PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK PA9.Mode=Asynchronous PA9.Signal=USART1_TX +PB0.Locked=true +PB0.Signal=GPIO_Output +PB1.Locked=true +PB1.Signal=GPIO_Output +PB10.Locked=true +PB10.Signal=GPIO_Output +PB11.Locked=true +PB11.Signal=GPIO_Output PC13-TAMPER-RTC.Locked=true PC13-TAMPER-RTC.Signal=GPIO_Output PD0-OSC_IN.Mode=HSE-External-Oscillator diff --git a/docs/SW Timings with HAL GPIO write.sal b/docs/SW Timings with HAL GPIO write.sal new file mode 100644 index 0000000000000000000000000000000000000000..7449d8a5b11e3863045f582cbeead50e427a120c GIT binary patch literal 40613 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 BuGIhl literal 0 HcmV?d00001 diff --git a/docs/SW Timings without HAL GPIO write 2.sal b/docs/SW Timings without HAL GPIO write 2.sal new file mode 100644 index 0000000000000000000000000000000000000000..265706f48bc4638763622108890d5c8436b53cb9 GIT binary patch literal 10655 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