This follows the same protocol as the lora code, so the same server should just work.main
@@ -16,4 +16,35 @@ Projects | |||||
[RS-485 USB HID KVM](RS485HID.md): USB Keyboard over RS-485 | [RS-485 USB HID KVM](RS485HID.md): USB Keyboard over RS-485 | ||||
File Layout | |||||
----------- | |||||
Note that things are a mess as they stand right now. The first project | |||||
was based upon the SemTech reference code which implemented their own | |||||
HAL on top of ST's HAL which is partly implemented on top of ARM's HAL, | |||||
and in some cases bypasses them. It was also originally written not | |||||
expecting to be used for another board. | |||||
loramac/ - SemTech reference code. Has reference code for LoRa and the | |||||
Node151 based board. | |||||
mk/ - Files supporting the build infrastructure. | |||||
rs485hid/ - Files relating to the RS-485 HID project | |||||
stm32/ - This is the HAL for ST based parts. It comtains the ARM CMSIS | |||||
HAL as well, for the parts the ST chose to use. | |||||
strobe/ - Crypto code that form the basis of the protocol. | |||||
Options | |||||
------- | |||||
Default on: | |||||
STROBE - This contains all the cryptography parts. | |||||
SYSINIT - This contains the initalization frmae work, similar to FreeBSD. | |||||
Default off: | |||||
NODE151 - Code necessary for the Heltech Node151 module. | |||||
RS485FRAME - Code implementing framing tx/rx over RS-485. | |||||
STM32F103 - Code for a STM32F103 based board. | |||||
SX1276 - Code necessary for the LoRa Radio. | |||||
USB_CDC - Code for implementing a USB CDC Endpoint. | |||||
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> | <!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> |
@@ -22,6 +22,9 @@ These are the device that are under conideration for the project: | |||||
Currently looking at USART3, B0 for DE, B1 for RE. | Currently looking at USART3, B0 for DE, B1 for RE. | ||||
TIM2_CH4 can be mapped to PB11 (UART3 RX). This is to do break detection. | |||||
Table 45 says TIM2_REMAP, either full or partial (value 1x). | |||||
Table 5 pin definitions of stm32f103c8.pdf | Table 5 pin definitions of stm32f103c8.pdf | ||||
(all can be remapped) | (all can be remapped) | ||||
@@ -52,15 +52,19 @@ ARMTARGET?= -mcpu=cortex-m3 -mthumb | |||||
LINKER_SCRIPT=$(STM32)/f103c8t6/STM32F103C8T6_FLASH.ld | LINKER_SCRIPT=$(STM32)/f103c8t6/STM32F103C8T6_FLASH.ld | ||||
SRCS+= \ | SRCS+= \ | ||||
misc.c \ | |||||
hal_generic.c \ | hal_generic.c \ | ||||
startup_stm32f103xb.s \ | startup_stm32f103xb.s \ | ||||
stm32f1xx_hal.c \ | stm32f1xx_hal.c \ | ||||
stm32f1xx_hal_cortex.c \ | stm32f1xx_hal_cortex.c \ | ||||
stm32f1xx_hal_dma.c \ | |||||
stm32f1xx_hal_gpio.c \ | stm32f1xx_hal_gpio.c \ | ||||
stm32f1xx_hal_pcd.c \ | stm32f1xx_hal_pcd.c \ | ||||
stm32f1xx_hal_pcd_ex.c \ | stm32f1xx_hal_pcd_ex.c \ | ||||
stm32f1xx_hal_pwr.c \ | |||||
stm32f1xx_hal_rcc.c \ | stm32f1xx_hal_rcc.c \ | ||||
stm32f1xx_hal_rcc_ex.c \ | stm32f1xx_hal_rcc_ex.c \ | ||||
stm32f1xx_hal_uart.c \ | |||||
stm32f1xx_ll_usb.c \ | stm32f1xx_ll_usb.c \ | ||||
system_stm32f1xx.c | system_stm32f1xx.c | ||||
@@ -108,6 +112,14 @@ CFLAGS+= -I$(STM32)/l151ccux | |||||
CFLAGS+= -DSTM32L151xC | CFLAGS+= -DSTM32L151xC | ||||
.endif | .endif | ||||
# RS485 Framing | |||||
.if ${MK_RS485FRAME} == "yes" | |||||
SRCS+= \ | |||||
rs485frame.c | |||||
CFLAGS+= -I$(SRCTOP)/rs485hid | |||||
.endif | |||||
# USB CDC | # USB CDC | ||||
.if ${MK_USB_CDC} == "yes" | .if ${MK_USB_CDC} == "yes" | ||||
.PATH: $(STM32)/usb | .PATH: $(STM32)/usb | ||||
@@ -8,6 +8,7 @@ __DEFAULT_YES_OPTIONS = STROBE \ | |||||
__DEFAULT_NO_OPTIONS = \ | __DEFAULT_NO_OPTIONS = \ | ||||
NODE151 \ | NODE151 \ | ||||
RS485FRAME \ | |||||
STM32F103 \ | STM32F103 \ | ||||
SX1276 \ | SX1276 \ | ||||
USB_CDC | USB_CDC | ||||
@@ -1,3 +1,31 @@ | |||||
# Copyright 2022 John-Mark Gurney. | |||||
# | |||||
# 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 AUTHOR 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 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. | |||||
# | |||||
.if $(.OBJDIR) == $(.CURDIR) | |||||
.error Need to set MAKEOBJDIR. | |||||
.endif | |||||
.MAIN: all | .MAIN: all | ||||
.PHONY: all | .PHONY: all | ||||
@@ -34,6 +34,7 @@ CFLAGS += -I$(.CURDIR)/.. | |||||
WITH_STM32F103 = yes | WITH_STM32F103 = yes | ||||
WITH_USB_CDC = yes | WITH_USB_CDC = yes | ||||
WITH_RS485FRAME = yes | |||||
.include <../mk/boards.mk> | .include <../mk/boards.mk> | ||||
@@ -0,0 +1,243 @@ | |||||
/* | |||||
* Code to TX/RX RS-485 frames. | |||||
* | |||||
*/ | |||||
#include <stdbool.h> | |||||
#include <sysinit.h> | |||||
#include <stm32f103xb.h> | |||||
#include <stm32f1xx_hal.h> | |||||
#include <stm32f1xx_hal_cortex.h> | |||||
#include <stm32f1xx_hal_dma.h> | |||||
#include <stm32f1xx_hal_rcc.h> | |||||
#include <stm32f1xx_hal_gpio.h> | |||||
#include <stm32f1xx_hal_uart.h> | |||||
#include <rs485frame.h> | |||||
const char *rs485err = NULL; | |||||
static uint8_t rxbuf[1024]; | |||||
static txdone_fn_t txdone; | |||||
static rxdone_fn_t rxdone; | |||||
static txdone_fn_t errcb; | |||||
static int doingrx = 0; | |||||
static int doingtx = 0; | |||||
static UART_HandleTypeDef rs485uart; | |||||
/* | |||||
* Notes: | |||||
HAL_UARTEx_RxEventCallback rx evnts | |||||
* HAL_UART_TxCpltCallback tx_it completed | |||||
* HAL_UART_RxCpltCallback rx_it completed | |||||
* HAL_UART_ErrorCallback for errors | |||||
*/ | |||||
void | |||||
USART3_IRQHandler(void) | |||||
{ | |||||
HAL_UART_IRQHandler(&rs485uart); | |||||
} | |||||
void | |||||
rs485_register(txdone_fn_t txf, rxdone_fn_t rxf, txdone_fn_t errf) | |||||
{ | |||||
txdone = txf; | |||||
rxdone = rxf; | |||||
errcb = errf; | |||||
} | |||||
static void | |||||
settx(bool tx) | |||||
{ | |||||
GPIO_PinState s; | |||||
if (tx) | |||||
s = GPIO_PIN_SET; | |||||
else | |||||
s = GPIO_PIN_RESET; | |||||
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, s); | |||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, s); | |||||
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, s); | |||||
} | |||||
void | |||||
rs485_starttx(uint8_t *pkt, size_t len) | |||||
{ | |||||
/* XXX - make sure not tx'ing */ | |||||
/* XXX - make sure line is idle */ | |||||
if (doingrx) { | |||||
HAL_UART_AbortReceive_IT(&rs485uart); | |||||
} | |||||
settx(true); | |||||
HAL_UART_Transmit_IT(&rs485uart, pkt, len); | |||||
} | |||||
void | |||||
HAL_UART_ErrorCallback(UART_HandleTypeDef *phuart) | |||||
{ | |||||
settx(false); | |||||
doingtx = 0; | |||||
doingrx = 0; | |||||
errcb(); | |||||
} | |||||
void | |||||
HAL_UART_TxCpltCallback(UART_HandleTypeDef *phuart) | |||||
{ | |||||
if (phuart != &rs485uart || txdone == NULL) | |||||
return; | |||||
settx(false); | |||||
doingtx = 0; | |||||
txdone(); | |||||
} | |||||
void | |||||
HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) | |||||
{ | |||||
if (huart != &rs485uart || rxdone == NULL) | |||||
return; | |||||
doingrx = 0; | |||||
rxdone(rxbuf, Size); | |||||
} | |||||
/* | |||||
* Called when the buffer has been completed, i.e. it likely | |||||
* overflowed. | |||||
*/ | |||||
void | |||||
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) | |||||
{ | |||||
if (huart != &rs485uart || rxdone == NULL) | |||||
return; | |||||
doingrx = 0; | |||||
rxdone(NULL, 0); | |||||
} | |||||
/* USE_HAL_UART_REGISTER_CALLBACKS defaults to 0, so use this */ | |||||
void | |||||
HAL_UART_MspInit(UART_HandleTypeDef *huart) | |||||
{ | |||||
GPIO_InitTypeDef GPIO_InitStruct; | |||||
/* UM1850 § 38.1.2 Page 550 */ | |||||
/* 2.a */ | |||||
__HAL_RCC_USART3_FORCE_RESET( ); | |||||
__HAL_RCC_USART3_RELEASE_RESET( ); | |||||
__HAL_RCC_USART3_CLK_ENABLE(); | |||||
/* 2.b */ | |||||
__HAL_RCC_GPIOB_CLK_ENABLE(); | |||||
/* TX pin */ | |||||
GPIO_InitStruct = (GPIO_InitTypeDef){ | |||||
.Pin = GPIO_PIN_10, | |||||
.Mode = GPIO_MODE_AF_PP, | |||||
.Pull = GPIO_NOPULL, | |||||
.Speed = GPIO_SPEED_FREQ_LOW, | |||||
}; | |||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); | |||||
/* RX pin */ | |||||
GPIO_InitStruct = (GPIO_InitTypeDef){ | |||||
.Pin = GPIO_PIN_11, | |||||
.Mode = GPIO_MODE_AF_INPUT, | |||||
.Pull = GPIO_NOPULL, | |||||
.Speed = GPIO_SPEED_FREQ_LOW, | |||||
}; | |||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); | |||||
/* 2.c */ | |||||
HAL_NVIC_SetPriority(USART3_IRQn, 1, 0); | |||||
HAL_NVIC_EnableIRQ(USART3_IRQn); | |||||
/* 2.d */ | |||||
/* DMA unused */ | |||||
} | |||||
const char * | |||||
statustostr(HAL_StatusTypeDef r) | |||||
{ | |||||
switch (r) { | |||||
case HAL_OK: | |||||
return "ok"; | |||||
case HAL_ERROR: | |||||
return "error"; | |||||
case HAL_BUSY: | |||||
return "busy"; | |||||
default: | |||||
return "unknown"; | |||||
} | |||||
} | |||||
int | |||||
rs485_startrx() | |||||
{ | |||||
HAL_StatusTypeDef r; | |||||
if (doingtx) { | |||||
rs485err = "doingtx"; | |||||
return 0; | |||||
} | |||||
r = HAL_UARTEx_ReceiveToIdle_IT(&rs485uart, rxbuf, sizeof rxbuf); | |||||
if (r == HAL_BUSY) { | |||||
HAL_UART_AbortReceive_IT(&rs485uart); | |||||
r = HAL_UARTEx_ReceiveToIdle_IT(&rs485uart, rxbuf, sizeof rxbuf); | |||||
} | |||||
rs485err = statustostr(r); | |||||
return r == HAL_OK; | |||||
} | |||||
static void | |||||
rs485frame_init(const void *v) | |||||
{ | |||||
GPIO_InitTypeDef GPIO_InitStruct; | |||||
/* setup DE/RE */ | |||||
GPIO_InitStruct = (GPIO_InitTypeDef){ | |||||
.Pin = GPIO_PIN_0|GPIO_PIN_1, | |||||
.Mode = GPIO_MODE_OUTPUT_OD, | |||||
.Pull = GPIO_NOPULL, | |||||
.Speed = GPIO_SPEED_FREQ_LOW, /* 2 MHz */ | |||||
}; | |||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); | |||||
/* switch to RX */ | |||||
settx(false); | |||||
/* UM1850 § 38.1.2 Page 550 */ | |||||
/* 3 */ | |||||
rs485uart = (UART_HandleTypeDef){ | |||||
.Init.BaudRate = 230400, | |||||
.Init.WordLength = UART_WORDLENGTH_8B, | |||||
.Init.StopBits = UART_STOPBITS_1, | |||||
.Init.Parity = UART_PARITY_NONE, | |||||
.Init.HwFlowCtl = UART_HWCONTROL_NONE, | |||||
.Init.Mode = UART_MODE_TX_RX, | |||||
.Instance = USART3, | |||||
}; | |||||
/* 4 */ | |||||
HAL_UART_Init(&rs485uart); | |||||
} | |||||
SYSINIT(rs485frame_init, SI_SUB_STANDARD, SI_ORDER_FIRST, rs485frame_init, NULL); |
@@ -0,0 +1,35 @@ | |||||
/*- | |||||
* Copyright 2022 John-Mark Gurney. | |||||
* | |||||
* 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 AUTHOR 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 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. | |||||
* | |||||
*/ | |||||
extern const char *rs485err; | |||||
typedef void (*txdone_fn_t)(void); | |||||
typedef void (*rxdone_fn_t)(const uint8_t *pkt, size_t len); | |||||
void rs485_register(txdone_fn_t, rxdone_fn_t, txdone_fn_t errcb); | |||||
void rs485_starttx(uint8_t *pkt, size_t len); | |||||
int rs485_startrx(); |
@@ -26,6 +26,8 @@ | |||||
#include <si_usb.h> | #include <si_usb.h> | ||||
#include <rs485frame.h> | |||||
#include <misc.h> | #include <misc.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
@@ -36,6 +38,14 @@ | |||||
SYSINIT(hal_init, SI_SUB_HAL, SI_ORDER_FIRST, (void (*)(const void *))HAL_Init, NULL); | SYSINIT(hal_init, SI_SUB_HAL, SI_ORDER_FIRST, (void (*)(const void *))HAL_Init, NULL); | ||||
static int dorx = 0; | |||||
static uint8_t rxbuf[128]; | |||||
static int gotrxdone = 0; | |||||
static int gottxdone = 0; | |||||
static int goterr = 0; | |||||
static int rxbufsize = 0; | |||||
static int rxbuftrunc = 0; | |||||
static void | static void | ||||
c13led(const void *none) | c13led(const void *none) | ||||
{ | { | ||||
@@ -56,6 +66,11 @@ c13led(const void *none) | |||||
} | } | ||||
SYSINIT(c13led, SI_SUB_HAL, SI_ORDER_SECOND, c13led, NULL); | SYSINIT(c13led, SI_SUB_HAL, SI_ORDER_SECOND, c13led, NULL); | ||||
#if 0 | |||||
#undef usb_printf | |||||
#define usb_printf debug_printf | |||||
#endif | |||||
/* | /* | ||||
* Referenced from: | * Referenced from: | ||||
* Projects/STM32F103RB-Nucleo/Applications/USB_Device/HID_Standalone/Src/main.c | * Projects/STM32F103RB-Nucleo/Applications/USB_Device/HID_Standalone/Src/main.c | ||||
@@ -128,24 +143,28 @@ void | |||||
txdone(void) | txdone(void) | ||||
{ | { | ||||
usb_printf("txdone\r\n"); | |||||
//Radio.Rx(0); | |||||
gottxdone = 1; | |||||
} | } | ||||
void | void | ||||
txtimeout(void) | |||||
errfunc(void) | |||||
{ | { | ||||
usb_printf("txtimeout\r\n"); | |||||
goterr = 1; | |||||
} | } | ||||
void | void | ||||
rxdone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) | |||||
rxdone(const uint8_t *payload, size_t size) | |||||
{ | { | ||||
usb_printf("rxdone: size: %hu, rssi: %hd, snr: %d\r\ndata: ", size, rssi, snr); | |||||
hexdump(payload, size); | |||||
usb_printf("\r\n"); | |||||
if (size > sizeof rxbuf) { | |||||
size = sizeof rxbuf; | |||||
rxbuftrunc = 1; | |||||
} | |||||
memcpy(rxbuf, payload, size); | |||||
rxbufsize = size; | |||||
gotrxdone = 1; | |||||
} | } | ||||
void | void | ||||
@@ -235,20 +254,29 @@ process_line(char *start, char *end) | |||||
usb_printf("invalid pkt\r\n"); | usb_printf("invalid pkt\r\n"); | ||||
return; | return; | ||||
} | } | ||||
//Radio.Send(pktbuf, len / 2); | |||||
rs485_starttx(pktbuf, len / 2); | |||||
return; | return; | ||||
} | } | ||||
usb_printf("line: %.*s", end - start, start); | usb_printf("line: %.*s", end - start, start); | ||||
fflush(vcp_usb); | fflush(vcp_usb); | ||||
} | } | ||||
static void | |||||
WaitForIRQ() | |||||
{ | |||||
__disable_irq(); | |||||
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); | |||||
__enable_irq( ); | |||||
} | |||||
int | int | ||||
main(void) | main(void) | ||||
{ | { | ||||
sysinit_run(); | sysinit_run(); | ||||
//debug_printf("starting...\n"); | |||||
debug_printf("starting...\n"); | |||||
#if 1 | #if 1 | ||||
int i; | int i; | ||||
@@ -281,8 +309,66 @@ main(void) | |||||
int inpbufpos = 0; | int inpbufpos = 0; | ||||
int cpylen; | int cpylen; | ||||
rs485_register(txdone, rxdone, errfunc); | |||||
rs485_startrx(); | |||||
unsigned lasttick = -1; | |||||
uint32_t gt; | |||||
loop: | loop: | ||||
//BoardLowPowerHandler(); | |||||
/* | |||||
* This is disabled as when it's enabled, it causes a hang | |||||
* when sending USB data. The USB CDC end point never becomes | |||||
* unbusy to allow the next send to progress. | |||||
*/ | |||||
#if 0 | |||||
/* | |||||
* A ms delay isn't a big deal, so no special locking is | |||||
* used to make sure we don't got to sleep w/ data pending. | |||||
*/ | |||||
WaitForIRQ(); | |||||
#else | |||||
(void)WaitForIRQ; | |||||
#endif | |||||
gt = HAL_GetTick(); | |||||
if (lasttick != gt / 1000) { | |||||
lasttick = gt / 1000; | |||||
//usb_printf("tick: %u\r\n", lasttick); | |||||
} | |||||
if (goterr) { | |||||
//usb_printf("error\r\n"); | |||||
goterr = 0; | |||||
dorx = 1; | |||||
} | |||||
if (gottxdone) { | |||||
usb_printf("txdone\r\n"); | |||||
dorx = 1; | |||||
gottxdone = 0; | |||||
} | |||||
if (gotrxdone) { | |||||
if (rxbuftrunc) { | |||||
rxbuftrunc = 0; | |||||
//usb_printf("rxdone: buffer overflow\r\n"); | |||||
} else { | |||||
usb_printf("rxdone: size: %u\r\ndata: ", rxbufsize); | |||||
hexdump(rxbuf, rxbufsize); | |||||
usb_printf("\r\n"); | |||||
} | |||||
dorx = 1; | |||||
gotrxdone = 0; | |||||
} | |||||
if (dorx) { | |||||
//usb_printf("dorx\r\n"); | |||||
rs485_startrx(); | |||||
//usb_printf("startrx res: %s\r\n", rs485err); | |||||
dorx = 0; | |||||
} | |||||
/* while we have data */ | /* while we have data */ | ||||
while (CDC_RX_LEN) { | while (CDC_RX_LEN) { | ||||
@@ -4,11 +4,34 @@ | |||||
#include <sysinit.h> | #include <sysinit.h> | ||||
#include <stm32f1xx_hal_gpio.h> | |||||
#include <stm32f1xx_hal_pcd.h> | |||||
#include <usb_device.h> | #include <usb_device.h> | ||||
static void | static void | ||||
usb_cdc_init(const void *foo) | usb_cdc_init(const void *foo) | ||||
{ | { | ||||
/* | |||||
* pretend that the device was newly plugged in | |||||
* see: https://stackoverflow.com/a/67336535 | |||||
*/ | |||||
GPIO_InitTypeDef GPIO_InitStructure; | |||||
GPIO_InitStructure = (GPIO_InitTypeDef){ | |||||
.Pin = GPIO_PIN_11|GPIO_PIN_12, | |||||
.Mode = GPIO_MODE_OUTPUT_PP, | |||||
.Pull = GPIO_PULLDOWN, | |||||
.Speed = GPIO_SPEED_HIGH, | |||||
}; | |||||
__HAL_RCC_GPIOA_CLK_ENABLE(); | |||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); | |||||
//HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_RESET); | |||||
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); | |||||
HAL_Delay(10); | |||||
MX_USB_DEVICE_Init(); | MX_USB_DEVICE_Init(); | ||||
} | } | ||||
@@ -14,12 +14,14 @@ f103c8t6/stm32f1xx_hal_adc.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f | |||||
f103c8t6/stm32f1xx_hal_adc_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h | f103c8t6/stm32f1xx_hal_adc_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_adc_ex.h | ||||
f103c8t6/stm32f1xx_hal_cortex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_cortex.h | f103c8t6/stm32f1xx_hal_cortex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_cortex.h | ||||
f103c8t6/stm32f1xx_hal_def.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h | f103c8t6/stm32f1xx_hal_def.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_def.h | ||||
f103c8t6/stm32f1xx_hal_dma.c STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c | |||||
f103c8t6/stm32f1xx_hal_dma.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma.h | f103c8t6/stm32f1xx_hal_dma.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma.h | ||||
f103c8t6/stm32f1xx_hal_dma_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma_ex.h | f103c8t6/stm32f1xx_hal_dma_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_dma_ex.h | ||||
f103c8t6/stm32f1xx_hal_flash.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash.h | f103c8t6/stm32f1xx_hal_flash.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash.h | ||||
f103c8t6/stm32f1xx_hal_flash_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash_ex.h | f103c8t6/stm32f1xx_hal_flash_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_flash_ex.h | ||||
f103c8t6/stm32f1xx_hal_gpio.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h | f103c8t6/stm32f1xx_hal_gpio.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h | ||||
f103c8t6/stm32f1xx_hal_gpio_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio_ex.h | f103c8t6/stm32f1xx_hal_gpio_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio_ex.h | ||||
f103c8t6/stm32f1xx_hal_pwr.c STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c | |||||
f103c8t6/stm32f1xx_hal_pwr.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pwr.h | f103c8t6/stm32f1xx_hal_pwr.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pwr.h | ||||
f103c8t6/stm32f1xx_hal_pcd.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pcd.h | f103c8t6/stm32f1xx_hal_pcd.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pcd.h | ||||
f103c8t6/stm32f1xx_hal_pcd_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pcd_ex.h | f103c8t6/stm32f1xx_hal_pcd_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_pcd_ex.h | ||||
@@ -29,5 +31,6 @@ f103c8t6/stm32f1xx_hal_rcc_ex.c STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Src/stm | |||||
f103c8t6/stm32f1xx_hal_rcc_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc_ex.h | f103c8t6/stm32f1xx_hal_rcc_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rcc_ex.h | ||||
f103c8t6/stm32f1xx_hal_rtc.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rtc.h | f103c8t6/stm32f1xx_hal_rtc.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rtc.h | ||||
f103c8t6/stm32f1xx_hal_rtc_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rtc_ex.h | f103c8t6/stm32f1xx_hal_rtc_ex.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_rtc_ex.h | ||||
f103c8t6/stm32f1xx_hal_uart.c STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c | |||||
f103c8t6/stm32f1xx_hal_uart.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h | f103c8t6/stm32f1xx_hal_uart.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h | ||||
f103c8t6/stm32f1xx_ll_usb.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usb.h | f103c8t6/stm32f1xx_ll_usb.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usb.h |
@@ -3,4 +3,6 @@ | |||||
#include "stm32f1xx_hal.h" | #include "stm32f1xx_hal.h" | ||||
void Error_Handler(void); | |||||
#endif /* _MAIN_H_ */ | #endif /* _MAIN_H_ */ |
@@ -0,0 +1,899 @@ | |||||
/** | |||||
****************************************************************************** | |||||
* @file stm32f1xx_hal_dma.c | |||||
* @author MCD Application Team | |||||
* @brief DMA HAL module driver. | |||||
* This file provides firmware functions to manage the following | |||||
* functionalities of the Direct Memory Access (DMA) peripheral: | |||||
* + Initialization and de-initialization functions | |||||
* + IO operation functions | |||||
* + Peripheral State and errors functions | |||||
@verbatim | |||||
============================================================================== | |||||
##### How to use this driver ##### | |||||
============================================================================== | |||||
[..] | |||||
(#) Enable and configure the peripheral to be connected to the DMA Channel | |||||
(except for internal SRAM / FLASH memories: no initialization is | |||||
necessary). Please refer to the Reference manual for connection between peripherals | |||||
and DMA requests. | |||||
(#) For a given Channel, program the required configuration through the following parameters: | |||||
Channel request, Transfer Direction, Source and Destination data formats, | |||||
Circular or Normal mode, Channel Priority level, Source and Destination Increment mode | |||||
using HAL_DMA_Init() function. | |||||
(#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error | |||||
detection. | |||||
(#) Use HAL_DMA_Abort() function to abort the current transfer | |||||
-@- In Memory-to-Memory transfer mode, Circular mode is not allowed. | |||||
*** Polling mode IO operation *** | |||||
================================= | |||||
[..] | |||||
(+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source | |||||
address and destination address and the Length of data to be transferred | |||||
(+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this | |||||
case a fixed Timeout can be configured by User depending from his application. | |||||
*** Interrupt mode IO operation *** | |||||
=================================== | |||||
[..] | |||||
(+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority() | |||||
(+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ() | |||||
(+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of | |||||
Source address and destination address and the Length of data to be transferred. | |||||
In this case the DMA interrupt is configured | |||||
(+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine | |||||
(+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can | |||||
add his own function by customization of function pointer XferCpltCallback and | |||||
XferErrorCallback (i.e. a member of DMA handle structure). | |||||
*** DMA HAL driver macros list *** | |||||
============================================= | |||||
[..] | |||||
Below the list of most used macros in DMA HAL driver. | |||||
(+) __HAL_DMA_ENABLE: Enable the specified DMA Channel. | |||||
(+) __HAL_DMA_DISABLE: Disable the specified DMA Channel. | |||||
(+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags. | |||||
(+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags. | |||||
(+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts. | |||||
(+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts. | |||||
(+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not. | |||||
[..] | |||||
(@) You can refer to the DMA HAL driver header file for more useful macros | |||||
@endverbatim | |||||
****************************************************************************** | |||||
* @attention | |||||
* | |||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics. | |||||
* All rights reserved.</center></h2> | |||||
* | |||||
* This software component is licensed by ST under BSD 3-Clause license, | |||||
* the "License"; You may not use this file except in compliance with the | |||||
* License. You may obtain a copy of the License at: | |||||
* opensource.org/licenses/BSD-3-Clause | |||||
* | |||||
****************************************************************************** | |||||
*/ | |||||
/* Includes ------------------------------------------------------------------*/ | |||||
#include "stm32f1xx_hal.h" | |||||
/** @addtogroup STM32F1xx_HAL_Driver | |||||
* @{ | |||||
*/ | |||||
/** @defgroup DMA DMA | |||||
* @brief DMA HAL module driver | |||||
* @{ | |||||
*/ | |||||
#ifdef HAL_DMA_MODULE_ENABLED | |||||
/* Private typedef -----------------------------------------------------------*/ | |||||
/* Private define ------------------------------------------------------------*/ | |||||
/* Private macro -------------------------------------------------------------*/ | |||||
/* Private variables ---------------------------------------------------------*/ | |||||
/* Private function prototypes -----------------------------------------------*/ | |||||
/** @defgroup DMA_Private_Functions DMA Private Functions | |||||
* @{ | |||||
*/ | |||||
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); | |||||
/** | |||||
* @} | |||||
*/ | |||||
/* Exported functions ---------------------------------------------------------*/ | |||||
/** @defgroup DMA_Exported_Functions DMA Exported Functions | |||||
* @{ | |||||
*/ | |||||
/** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions | |||||
* @brief Initialization and de-initialization functions | |||||
* | |||||
@verbatim | |||||
=============================================================================== | |||||
##### Initialization and de-initialization functions ##### | |||||
=============================================================================== | |||||
[..] | |||||
This section provides functions allowing to initialize the DMA Channel source | |||||
and destination addresses, incrementation and data sizes, transfer direction, | |||||
circular/normal mode selection, memory-to-memory mode selection and Channel priority value. | |||||
[..] | |||||
The HAL_DMA_Init() function follows the DMA configuration procedures as described in | |||||
reference manual. | |||||
@endverbatim | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @brief Initialize the DMA according to the specified | |||||
* parameters in the DMA_InitTypeDef and initialize the associated handle. | |||||
* @param hdma: Pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
uint32_t tmp = 0U; | |||||
/* Check the DMA handle allocation */ | |||||
if(hdma == NULL) | |||||
{ | |||||
return HAL_ERROR; | |||||
} | |||||
/* Check the parameters */ | |||||
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); | |||||
assert_param(IS_DMA_DIRECTION(hdma->Init.Direction)); | |||||
assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc)); | |||||
assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc)); | |||||
assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment)); | |||||
assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment)); | |||||
assert_param(IS_DMA_MODE(hdma->Init.Mode)); | |||||
assert_param(IS_DMA_PRIORITY(hdma->Init.Priority)); | |||||
#if defined (DMA2) | |||||
/* calculation of the channel index */ | |||||
if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) | |||||
{ | |||||
/* DMA1 */ | |||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; | |||||
hdma->DmaBaseAddress = DMA1; | |||||
} | |||||
else | |||||
{ | |||||
/* DMA2 */ | |||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2; | |||||
hdma->DmaBaseAddress = DMA2; | |||||
} | |||||
#else | |||||
/* DMA1 */ | |||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; | |||||
hdma->DmaBaseAddress = DMA1; | |||||
#endif /* DMA2 */ | |||||
/* Change DMA peripheral state */ | |||||
hdma->State = HAL_DMA_STATE_BUSY; | |||||
/* Get the CR register value */ | |||||
tmp = hdma->Instance->CCR; | |||||
/* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ | |||||
tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \ | |||||
DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \ | |||||
DMA_CCR_DIR)); | |||||
/* Prepare the DMA Channel configuration */ | |||||
tmp |= hdma->Init.Direction | | |||||
hdma->Init.PeriphInc | hdma->Init.MemInc | | |||||
hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | | |||||
hdma->Init.Mode | hdma->Init.Priority; | |||||
/* Write to DMA Channel CR register */ | |||||
hdma->Instance->CCR = tmp; | |||||
/* Initialise the error code */ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE; | |||||
/* Initialize the DMA state*/ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
/* Allocate lock resource and initialize it */ | |||||
hdma->Lock = HAL_UNLOCKED; | |||||
return HAL_OK; | |||||
} | |||||
/** | |||||
* @brief DeInitialize the DMA peripheral. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
/* Check the DMA handle allocation */ | |||||
if(hdma == NULL) | |||||
{ | |||||
return HAL_ERROR; | |||||
} | |||||
/* Check the parameters */ | |||||
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); | |||||
/* Disable the selected DMA Channelx */ | |||||
__HAL_DMA_DISABLE(hdma); | |||||
/* Reset DMA Channel control register */ | |||||
hdma->Instance->CCR = 0U; | |||||
/* Reset DMA Channel Number of Data to Transfer register */ | |||||
hdma->Instance->CNDTR = 0U; | |||||
/* Reset DMA Channel peripheral address register */ | |||||
hdma->Instance->CPAR = 0U; | |||||
/* Reset DMA Channel memory address register */ | |||||
hdma->Instance->CMAR = 0U; | |||||
#if defined (DMA2) | |||||
/* calculation of the channel index */ | |||||
if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) | |||||
{ | |||||
/* DMA1 */ | |||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; | |||||
hdma->DmaBaseAddress = DMA1; | |||||
} | |||||
else | |||||
{ | |||||
/* DMA2 */ | |||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2; | |||||
hdma->DmaBaseAddress = DMA2; | |||||
} | |||||
#else | |||||
/* DMA1 */ | |||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; | |||||
hdma->DmaBaseAddress = DMA1; | |||||
#endif /* DMA2 */ | |||||
/* Clear all flags */ | |||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex)); | |||||
/* Clean all callbacks */ | |||||
hdma->XferCpltCallback = NULL; | |||||
hdma->XferHalfCpltCallback = NULL; | |||||
hdma->XferErrorCallback = NULL; | |||||
hdma->XferAbortCallback = NULL; | |||||
/* Reset the error code */ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE; | |||||
/* Reset the DMA state */ | |||||
hdma->State = HAL_DMA_STATE_RESET; | |||||
/* Release Lock */ | |||||
__HAL_UNLOCK(hdma); | |||||
return HAL_OK; | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions | |||||
* @brief Input and Output operation functions | |||||
* | |||||
@verbatim | |||||
=============================================================================== | |||||
##### IO operation functions ##### | |||||
=============================================================================== | |||||
[..] This section provides functions allowing to: | |||||
(+) Configure the source, destination address and data length and Start DMA transfer | |||||
(+) Configure the source, destination address and data length and | |||||
Start DMA transfer with interrupt | |||||
(+) Abort DMA transfer | |||||
(+) Poll for transfer complete | |||||
(+) Handle DMA interrupt request | |||||
@endverbatim | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @brief Start the DMA Transfer. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @param SrcAddress: The source memory Buffer address | |||||
* @param DstAddress: The destination memory Buffer address | |||||
* @param DataLength: The length of data to be transferred from source to destination | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) | |||||
{ | |||||
HAL_StatusTypeDef status = HAL_OK; | |||||
/* Check the parameters */ | |||||
assert_param(IS_DMA_BUFFER_SIZE(DataLength)); | |||||
/* Process locked */ | |||||
__HAL_LOCK(hdma); | |||||
if(HAL_DMA_STATE_READY == hdma->State) | |||||
{ | |||||
/* Change DMA peripheral state */ | |||||
hdma->State = HAL_DMA_STATE_BUSY; | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE; | |||||
/* Disable the peripheral */ | |||||
__HAL_DMA_DISABLE(hdma); | |||||
/* Configure the source, destination address and the data length & clear flags*/ | |||||
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); | |||||
/* Enable the Peripheral */ | |||||
__HAL_DMA_ENABLE(hdma); | |||||
} | |||||
else | |||||
{ | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
status = HAL_BUSY; | |||||
} | |||||
return status; | |||||
} | |||||
/** | |||||
* @brief Start the DMA Transfer with interrupt enabled. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @param SrcAddress: The source memory Buffer address | |||||
* @param DstAddress: The destination memory Buffer address | |||||
* @param DataLength: The length of data to be transferred from source to destination | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) | |||||
{ | |||||
HAL_StatusTypeDef status = HAL_OK; | |||||
/* Check the parameters */ | |||||
assert_param(IS_DMA_BUFFER_SIZE(DataLength)); | |||||
/* Process locked */ | |||||
__HAL_LOCK(hdma); | |||||
if(HAL_DMA_STATE_READY == hdma->State) | |||||
{ | |||||
/* Change DMA peripheral state */ | |||||
hdma->State = HAL_DMA_STATE_BUSY; | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE; | |||||
/* Disable the peripheral */ | |||||
__HAL_DMA_DISABLE(hdma); | |||||
/* Configure the source, destination address and the data length & clear flags*/ | |||||
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); | |||||
/* Enable the transfer complete interrupt */ | |||||
/* Enable the transfer Error interrupt */ | |||||
if(NULL != hdma->XferHalfCpltCallback) | |||||
{ | |||||
/* Enable the Half transfer complete interrupt as well */ | |||||
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); | |||||
} | |||||
else | |||||
{ | |||||
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); | |||||
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE)); | |||||
} | |||||
/* Enable the Peripheral */ | |||||
__HAL_DMA_ENABLE(hdma); | |||||
} | |||||
else | |||||
{ | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
/* Remain BUSY */ | |||||
status = HAL_BUSY; | |||||
} | |||||
return status; | |||||
} | |||||
/** | |||||
* @brief Abort the DMA Transfer. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
HAL_StatusTypeDef status = HAL_OK; | |||||
if(hdma->State != HAL_DMA_STATE_BUSY) | |||||
{ | |||||
/* no transfer ongoing */ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
return HAL_ERROR; | |||||
} | |||||
else | |||||
{ | |||||
/* Disable DMA IT */ | |||||
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); | |||||
/* Disable the channel */ | |||||
__HAL_DMA_DISABLE(hdma); | |||||
/* Clear all flags */ | |||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); | |||||
} | |||||
/* Change the DMA state */ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
return status; | |||||
} | |||||
/** | |||||
* @brief Aborts the DMA Transfer in Interrupt mode. | |||||
* @param hdma : pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
HAL_StatusTypeDef status = HAL_OK; | |||||
if(HAL_DMA_STATE_BUSY != hdma->State) | |||||
{ | |||||
/* no transfer ongoing */ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; | |||||
status = HAL_ERROR; | |||||
} | |||||
else | |||||
{ | |||||
/* Disable DMA IT */ | |||||
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); | |||||
/* Disable the channel */ | |||||
__HAL_DMA_DISABLE(hdma); | |||||
/* Clear all flags */ | |||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_GI_FLAG_INDEX(hdma)); | |||||
/* Change the DMA state */ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
/* Call User Abort callback */ | |||||
if(hdma->XferAbortCallback != NULL) | |||||
{ | |||||
hdma->XferAbortCallback(hdma); | |||||
} | |||||
} | |||||
return status; | |||||
} | |||||
/** | |||||
* @brief Polling for transfer complete. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @param CompleteLevel: Specifies the DMA level complete. | |||||
* @param Timeout: Timeout duration. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout) | |||||
{ | |||||
uint32_t temp; | |||||
uint32_t tickstart = 0U; | |||||
if(HAL_DMA_STATE_BUSY != hdma->State) | |||||
{ | |||||
/* no transfer ongoing */ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; | |||||
__HAL_UNLOCK(hdma); | |||||
return HAL_ERROR; | |||||
} | |||||
/* Polling mode not supported in circular mode */ | |||||
if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC)) | |||||
{ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; | |||||
return HAL_ERROR; | |||||
} | |||||
/* Get the level transfer complete flag */ | |||||
if(CompleteLevel == HAL_DMA_FULL_TRANSFER) | |||||
{ | |||||
/* Transfer Complete flag */ | |||||
temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma); | |||||
} | |||||
else | |||||
{ | |||||
/* Half Transfer Complete flag */ | |||||
temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma); | |||||
} | |||||
/* Get tick */ | |||||
tickstart = HAL_GetTick(); | |||||
while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET) | |||||
{ | |||||
if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)) | |||||
{ | |||||
/* When a DMA transfer error occurs */ | |||||
/* A hardware clear of its EN bits is performed */ | |||||
/* Clear all flags */ | |||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); | |||||
/* Update error code */ | |||||
SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE); | |||||
/* Change the DMA state */ | |||||
hdma->State= HAL_DMA_STATE_READY; | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
return HAL_ERROR; | |||||
} | |||||
/* Check for the Timeout */ | |||||
if(Timeout != HAL_MAX_DELAY) | |||||
{ | |||||
if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) | |||||
{ | |||||
/* Update error code */ | |||||
SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT); | |||||
/* Change the DMA state */ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
return HAL_ERROR; | |||||
} | |||||
} | |||||
} | |||||
if(CompleteLevel == HAL_DMA_FULL_TRANSFER) | |||||
{ | |||||
/* Clear the transfer complete flag */ | |||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); | |||||
/* The selected Channelx EN bit is cleared (DMA is disabled and | |||||
all transfers are complete) */ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
} | |||||
else | |||||
{ | |||||
/* Clear the half transfer complete flag */ | |||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); | |||||
} | |||||
/* Process unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
return HAL_OK; | |||||
} | |||||
/** | |||||
* @brief Handles DMA interrupt request. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval None | |||||
*/ | |||||
void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
uint32_t flag_it = hdma->DmaBaseAddress->ISR; | |||||
uint32_t source_it = hdma->Instance->CCR; | |||||
/* Half Transfer Complete Interrupt management ******************************/ | |||||
if (((flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_HT) != RESET)) | |||||
{ | |||||
/* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ | |||||
if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) | |||||
{ | |||||
/* Disable the half transfer interrupt */ | |||||
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); | |||||
} | |||||
/* Clear the half transfer complete flag */ | |||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); | |||||
/* DMA peripheral state is not updated in Half Transfer */ | |||||
/* but in Transfer Complete case */ | |||||
if(hdma->XferHalfCpltCallback != NULL) | |||||
{ | |||||
/* Half transfer callback */ | |||||
hdma->XferHalfCpltCallback(hdma); | |||||
} | |||||
} | |||||
/* Transfer Complete Interrupt management ***********************************/ | |||||
else if (((flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_TC) != RESET)) | |||||
{ | |||||
if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) | |||||
{ | |||||
/* Disable the transfer complete and error interrupt */ | |||||
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC); | |||||
/* Change the DMA state */ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
} | |||||
/* Clear the transfer complete flag */ | |||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
if(hdma->XferCpltCallback != NULL) | |||||
{ | |||||
/* Transfer complete callback */ | |||||
hdma->XferCpltCallback(hdma); | |||||
} | |||||
} | |||||
/* Transfer Error Interrupt management **************************************/ | |||||
else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE))) | |||||
{ | |||||
/* When a DMA transfer error occurs */ | |||||
/* A hardware clear of its EN bits is performed */ | |||||
/* Disable ALL DMA IT */ | |||||
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); | |||||
/* Clear all flags */ | |||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); | |||||
/* Update error code */ | |||||
hdma->ErrorCode = HAL_DMA_ERROR_TE; | |||||
/* Change the DMA state */ | |||||
hdma->State = HAL_DMA_STATE_READY; | |||||
/* Process Unlocked */ | |||||
__HAL_UNLOCK(hdma); | |||||
if (hdma->XferErrorCallback != NULL) | |||||
{ | |||||
/* Transfer error callback */ | |||||
hdma->XferErrorCallback(hdma); | |||||
} | |||||
} | |||||
return; | |||||
} | |||||
/** | |||||
* @brief Register callbacks | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @param CallbackID: User Callback identifer | |||||
* a HAL_DMA_CallbackIDTypeDef ENUM as parameter. | |||||
* @param pCallback: pointer to private callbacsk function which has pointer to | |||||
* a DMA_HandleTypeDef structure as parameter. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma)) | |||||
{ | |||||
HAL_StatusTypeDef status = HAL_OK; | |||||
/* Process locked */ | |||||
__HAL_LOCK(hdma); | |||||
if(HAL_DMA_STATE_READY == hdma->State) | |||||
{ | |||||
switch (CallbackID) | |||||
{ | |||||
case HAL_DMA_XFER_CPLT_CB_ID: | |||||
hdma->XferCpltCallback = pCallback; | |||||
break; | |||||
case HAL_DMA_XFER_HALFCPLT_CB_ID: | |||||
hdma->XferHalfCpltCallback = pCallback; | |||||
break; | |||||
case HAL_DMA_XFER_ERROR_CB_ID: | |||||
hdma->XferErrorCallback = pCallback; | |||||
break; | |||||
case HAL_DMA_XFER_ABORT_CB_ID: | |||||
hdma->XferAbortCallback = pCallback; | |||||
break; | |||||
default: | |||||
status = HAL_ERROR; | |||||
break; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
status = HAL_ERROR; | |||||
} | |||||
/* Release Lock */ | |||||
__HAL_UNLOCK(hdma); | |||||
return status; | |||||
} | |||||
/** | |||||
* @brief UnRegister callbacks | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @param CallbackID: User Callback identifer | |||||
* a HAL_DMA_CallbackIDTypeDef ENUM as parameter. | |||||
* @retval HAL status | |||||
*/ | |||||
HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID) | |||||
{ | |||||
HAL_StatusTypeDef status = HAL_OK; | |||||
/* Process locked */ | |||||
__HAL_LOCK(hdma); | |||||
if(HAL_DMA_STATE_READY == hdma->State) | |||||
{ | |||||
switch (CallbackID) | |||||
{ | |||||
case HAL_DMA_XFER_CPLT_CB_ID: | |||||
hdma->XferCpltCallback = NULL; | |||||
break; | |||||
case HAL_DMA_XFER_HALFCPLT_CB_ID: | |||||
hdma->XferHalfCpltCallback = NULL; | |||||
break; | |||||
case HAL_DMA_XFER_ERROR_CB_ID: | |||||
hdma->XferErrorCallback = NULL; | |||||
break; | |||||
case HAL_DMA_XFER_ABORT_CB_ID: | |||||
hdma->XferAbortCallback = NULL; | |||||
break; | |||||
case HAL_DMA_XFER_ALL_CB_ID: | |||||
hdma->XferCpltCallback = NULL; | |||||
hdma->XferHalfCpltCallback = NULL; | |||||
hdma->XferErrorCallback = NULL; | |||||
hdma->XferAbortCallback = NULL; | |||||
break; | |||||
default: | |||||
status = HAL_ERROR; | |||||
break; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
status = HAL_ERROR; | |||||
} | |||||
/* Release Lock */ | |||||
__HAL_UNLOCK(hdma); | |||||
return status; | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions | |||||
* @brief Peripheral State and Errors functions | |||||
* | |||||
@verbatim | |||||
=============================================================================== | |||||
##### Peripheral State and Errors functions ##### | |||||
=============================================================================== | |||||
[..] | |||||
This subsection provides functions allowing to | |||||
(+) Check the DMA state | |||||
(+) Get error code | |||||
@endverbatim | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @brief Return the DMA hande state. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval HAL state | |||||
*/ | |||||
HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
/* Return DMA handle state */ | |||||
return hdma->State; | |||||
} | |||||
/** | |||||
* @brief Return the DMA error code. | |||||
* @param hdma : pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @retval DMA Error Code | |||||
*/ | |||||
uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma) | |||||
{ | |||||
return hdma->ErrorCode; | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @addtogroup DMA_Private_Functions | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @brief Sets the DMA Transfer parameter. | |||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains | |||||
* the configuration information for the specified DMA Channel. | |||||
* @param SrcAddress: The source memory Buffer address | |||||
* @param DstAddress: The destination memory Buffer address | |||||
* @param DataLength: The length of data to be transferred from source to destination | |||||
* @retval HAL status | |||||
*/ | |||||
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) | |||||
{ | |||||
/* Clear all flags */ | |||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); | |||||
/* Configure DMA Channel data length */ | |||||
hdma->Instance->CNDTR = DataLength; | |||||
/* Memory to Peripheral */ | |||||
if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) | |||||
{ | |||||
/* Configure DMA Channel destination address */ | |||||
hdma->Instance->CPAR = DstAddress; | |||||
/* Configure DMA Channel source address */ | |||||
hdma->Instance->CMAR = SrcAddress; | |||||
} | |||||
/* Peripheral to Memory */ | |||||
else | |||||
{ | |||||
/* Configure DMA Channel source address */ | |||||
hdma->Instance->CPAR = SrcAddress; | |||||
/* Configure DMA Channel destination address */ | |||||
hdma->Instance->CMAR = DstAddress; | |||||
} | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
#endif /* HAL_DMA_MODULE_ENABLED */ | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** | |||||
* @} | |||||
*/ | |||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
@@ -0,0 +1,621 @@ | |||||
/** | |||||
****************************************************************************** | |||||
* @file stm32f1xx_hal_pwr.c | |||||
* @author MCD Application Team | |||||
* @brief PWR HAL module driver. | |||||
* | |||||
* This file provides firmware functions to manage the following | |||||
* functionalities of the Power Controller (PWR) peripheral: | |||||
* + Initialization/de-initialization functions | |||||
* + Peripheral Control functions | |||||
* | |||||
****************************************************************************** | |||||
* @attention | |||||
* | |||||
* <h2><center>© Copyright (c) 2016 STMicroelectronics. | |||||
* All rights reserved.</center></h2> | |||||
* | |||||
* This software component is licensed by ST under BSD 3-Clause license, | |||||
* the "License"; You may not use this file except in compliance with the | |||||
* License. You may obtain a copy of the License at: | |||||
* opensource.org/licenses/BSD-3-Clause | |||||
* | |||||
****************************************************************************** | |||||
*/ | |||||
/* Includes ------------------------------------------------------------------*/ | |||||
#include "stm32f1xx_hal.h" | |||||
/** @addtogroup STM32F1xx_HAL_Driver | |||||
* @{ | |||||
*/ | |||||
/** @defgroup PWR PWR | |||||
* @brief PWR HAL module driver | |||||
* @{ | |||||
*/ | |||||
#ifdef HAL_PWR_MODULE_ENABLED | |||||
/* Private typedef -----------------------------------------------------------*/ | |||||
/* Private define ------------------------------------------------------------*/ | |||||
/** @defgroup PWR_Private_Constants PWR Private Constants | |||||
* @{ | |||||
*/ | |||||
/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask | |||||
* @{ | |||||
*/ | |||||
#define PVD_MODE_IT 0x00010000U | |||||
#define PVD_MODE_EVT 0x00020000U | |||||
#define PVD_RISING_EDGE 0x00000001U | |||||
#define PVD_FALLING_EDGE 0x00000002U | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup PWR_register_alias_address PWR Register alias address | |||||
* @{ | |||||
*/ | |||||
/* ------------- PWR registers bit address in the alias region ---------------*/ | |||||
#define PWR_OFFSET (PWR_BASE - PERIPH_BASE) | |||||
#define PWR_CR_OFFSET 0x00U | |||||
#define PWR_CSR_OFFSET 0x04U | |||||
#define PWR_CR_OFFSET_BB (PWR_OFFSET + PWR_CR_OFFSET) | |||||
#define PWR_CSR_OFFSET_BB (PWR_OFFSET + PWR_CSR_OFFSET) | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup PWR_CR_register_alias PWR CR Register alias address | |||||
* @{ | |||||
*/ | |||||
/* --- CR Register ---*/ | |||||
/* Alias word address of LPSDSR bit */ | |||||
#define LPSDSR_BIT_NUMBER PWR_CR_LPDS_Pos | |||||
#define CR_LPSDSR_BB ((uint32_t)(PERIPH_BB_BASE + (PWR_CR_OFFSET_BB * 32U) + (LPSDSR_BIT_NUMBER * 4U))) | |||||
/* Alias word address of DBP bit */ | |||||
#define DBP_BIT_NUMBER PWR_CR_DBP_Pos | |||||
#define CR_DBP_BB ((uint32_t)(PERIPH_BB_BASE + (PWR_CR_OFFSET_BB * 32U) + (DBP_BIT_NUMBER * 4U))) | |||||
/* Alias word address of PVDE bit */ | |||||
#define PVDE_BIT_NUMBER PWR_CR_PVDE_Pos | |||||
#define CR_PVDE_BB ((uint32_t)(PERIPH_BB_BASE + (PWR_CR_OFFSET_BB * 32U) + (PVDE_BIT_NUMBER * 4U))) | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup PWR_CSR_register_alias PWR CSR Register alias address | |||||
* @{ | |||||
*/ | |||||
/* --- CSR Register ---*/ | |||||
/* Alias word address of EWUP1 bit */ | |||||
#define CSR_EWUP_BB(VAL) ((uint32_t)(PERIPH_BB_BASE + (PWR_CSR_OFFSET_BB * 32U) + (POSITION_VAL(VAL) * 4U))) | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** | |||||
* @} | |||||
*/ | |||||
/* Private variables ---------------------------------------------------------*/ | |||||
/* Private function prototypes -----------------------------------------------*/ | |||||
/** @defgroup PWR_Private_Functions PWR Private Functions | |||||
* brief WFE cortex command overloaded for HAL_PWR_EnterSTOPMode usage only (see Workaround section) | |||||
* @{ | |||||
*/ | |||||
static void PWR_OverloadWfe(void); | |||||
/* Private functions ---------------------------------------------------------*/ | |||||
__NOINLINE | |||||
static void PWR_OverloadWfe(void) | |||||
{ | |||||
__asm volatile( "wfe" ); | |||||
__asm volatile( "nop" ); | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup PWR_Exported_Functions PWR Exported Functions | |||||
* @{ | |||||
*/ | |||||
/** @defgroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions | |||||
* @brief Initialization and de-initialization functions | |||||
* | |||||
@verbatim | |||||
=============================================================================== | |||||
##### Initialization and de-initialization functions ##### | |||||
=============================================================================== | |||||
[..] | |||||
After reset, the backup domain (RTC registers, RTC backup data | |||||
registers) is protected against possible unwanted | |||||
write accesses. | |||||
To enable access to the RTC Domain and RTC registers, proceed as follows: | |||||
(+) Enable the Power Controller (PWR) APB1 interface clock using the | |||||
__HAL_RCC_PWR_CLK_ENABLE() macro. | |||||
(+) Enable access to RTC domain using the HAL_PWR_EnableBkUpAccess() function. | |||||
@endverbatim | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @brief Deinitializes the PWR peripheral registers to their default reset values. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_DeInit(void) | |||||
{ | |||||
__HAL_RCC_PWR_FORCE_RESET(); | |||||
__HAL_RCC_PWR_RELEASE_RESET(); | |||||
} | |||||
/** | |||||
* @brief Enables access to the backup domain (RTC registers, RTC | |||||
* backup data registers ). | |||||
* @note If the HSE divided by 128 is used as the RTC clock, the | |||||
* Backup Domain Access should be kept enabled. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnableBkUpAccess(void) | |||||
{ | |||||
/* Enable access to RTC and backup registers */ | |||||
*(__IO uint32_t *) CR_DBP_BB = (uint32_t)ENABLE; | |||||
} | |||||
/** | |||||
* @brief Disables access to the backup domain (RTC registers, RTC | |||||
* backup data registers). | |||||
* @note If the HSE divided by 128 is used as the RTC clock, the | |||||
* Backup Domain Access should be kept enabled. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_DisableBkUpAccess(void) | |||||
{ | |||||
/* Disable access to RTC and backup registers */ | |||||
*(__IO uint32_t *) CR_DBP_BB = (uint32_t)DISABLE; | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** @defgroup PWR_Exported_Functions_Group2 Peripheral Control functions | |||||
* @brief Low Power modes configuration functions | |||||
* | |||||
@verbatim | |||||
=============================================================================== | |||||
##### Peripheral Control functions ##### | |||||
=============================================================================== | |||||
*** PVD configuration *** | |||||
========================= | |||||
[..] | |||||
(+) The PVD is used to monitor the VDD power supply by comparing it to a | |||||
threshold selected by the PVD Level (PLS[2:0] bits in the PWR_CR). | |||||
(+) A PVDO flag is available to indicate if VDD/VDDA is higher or lower | |||||
than the PVD threshold. This event is internally connected to the EXTI | |||||
line16 and can generate an interrupt if enabled. This is done through | |||||
__HAL_PVD_EXTI_ENABLE_IT() macro. | |||||
(+) The PVD is stopped in Standby mode. | |||||
*** WakeUp pin configuration *** | |||||
================================ | |||||
[..] | |||||
(+) WakeUp pin is used to wake up the system from Standby mode. This pin is | |||||
forced in input pull-down configuration and is active on rising edges. | |||||
(+) There is one WakeUp pin: | |||||
WakeUp Pin 1 on PA.00. | |||||
[..] | |||||
*** Low Power modes configuration *** | |||||
===================================== | |||||
[..] | |||||
The device features 3 low-power modes: | |||||
(+) Sleep mode: CPU clock off, all peripherals including Cortex-M3 core peripherals like | |||||
NVIC, SysTick, etc. are kept running | |||||
(+) Stop mode: All clocks are stopped | |||||
(+) Standby mode: 1.8V domain powered off | |||||
*** Sleep mode *** | |||||
================== | |||||
[..] | |||||
(+) Entry: | |||||
The Sleep mode is entered by using the HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFx) | |||||
functions with | |||||
(++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction | |||||
(++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction | |||||
(+) Exit: | |||||
(++) WFI entry mode, Any peripheral interrupt acknowledged by the nested vectored interrupt | |||||
controller (NVIC) can wake up the device from Sleep mode. | |||||
(++) WFE entry mode, Any wakeup event can wake up the device from Sleep mode. | |||||
(+++) Any peripheral interrupt w/o NVIC configuration & SEVONPEND bit set in the Cortex (HAL_PWR_EnableSEVOnPend) | |||||
(+++) Any EXTI Line (Internal or External) configured in Event mode | |||||
*** Stop mode *** | |||||
================= | |||||
[..] | |||||
The Stop mode is based on the Cortex-M3 deepsleep mode combined with peripheral | |||||
clock gating. The voltage regulator can be configured either in normal or low-power mode. | |||||
In Stop mode, all clocks in the 1.8 V domain are stopped, the PLL, the HSI and the HSE RC | |||||
oscillators are disabled. SRAM and register contents are preserved. | |||||
In Stop mode, all I/O pins keep the same state as in Run mode. | |||||
(+) Entry: | |||||
The Stop mode is entered using the HAL_PWR_EnterSTOPMode(PWR_REGULATOR_VALUE, PWR_SLEEPENTRY_WFx ) | |||||
function with: | |||||
(++) PWR_REGULATOR_VALUE= PWR_MAINREGULATOR_ON: Main regulator ON. | |||||
(++) PWR_REGULATOR_VALUE= PWR_LOWPOWERREGULATOR_ON: Low Power regulator ON. | |||||
(++) PWR_SLEEPENTRY_WFx= PWR_SLEEPENTRY_WFI: enter STOP mode with WFI instruction | |||||
(++) PWR_SLEEPENTRY_WFx= PWR_SLEEPENTRY_WFE: enter STOP mode with WFE instruction | |||||
(+) Exit: | |||||
(++) WFI entry mode, Any EXTI Line (Internal or External) configured in Interrupt mode with NVIC configured | |||||
(++) WFE entry mode, Any EXTI Line (Internal or External) configured in Event mode. | |||||
*** Standby mode *** | |||||
==================== | |||||
[..] | |||||
The Standby mode allows to achieve the lowest power consumption. It is based on the | |||||
Cortex-M3 deepsleep mode, with the voltage regulator disabled. The 1.8 V domain is | |||||
consequently powered off. The PLL, the HSI oscillator and the HSE oscillator are also | |||||
switched off. SRAM and register contents are lost except for registers in the Backup domain | |||||
and Standby circuitry | |||||
(+) Entry: | |||||
(++) The Standby mode is entered using the HAL_PWR_EnterSTANDBYMode() function. | |||||
(+) Exit: | |||||
(++) WKUP pin rising edge, RTC alarm event rising edge, external Reset in | |||||
NRSTpin, IWDG Reset | |||||
*** Auto-wakeup (AWU) from low-power mode *** | |||||
============================================= | |||||
[..] | |||||
(+) The MCU can be woken up from low-power mode by an RTC Alarm event, | |||||
without depending on an external interrupt (Auto-wakeup mode). | |||||
(+) RTC auto-wakeup (AWU) from the Stop and Standby modes | |||||
(++) To wake up from the Stop mode with an RTC alarm event, it is necessary to | |||||
configure the RTC to generate the RTC alarm using the HAL_RTC_SetAlarm_IT() function. | |||||
*** PWR Workarounds linked to Silicon Limitation *** | |||||
==================================================== | |||||
[..] | |||||
Below the list of all silicon limitations known on STM32F1xx prouct. | |||||
(#)Workarounds Implemented inside PWR HAL Driver | |||||
(##)Debugging Stop mode with WFE entry - overloaded the WFE by an internal function | |||||
@endverbatim | |||||
* @{ | |||||
*/ | |||||
/** | |||||
* @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD). | |||||
* @param sConfigPVD: pointer to an PWR_PVDTypeDef structure that contains the configuration | |||||
* information for the PVD. | |||||
* @note Refer to the electrical characteristics of your device datasheet for | |||||
* more details about the voltage threshold corresponding to each | |||||
* detection level. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD) | |||||
{ | |||||
/* Check the parameters */ | |||||
assert_param(IS_PWR_PVD_LEVEL(sConfigPVD->PVDLevel)); | |||||
assert_param(IS_PWR_PVD_MODE(sConfigPVD->Mode)); | |||||
/* Set PLS[7:5] bits according to PVDLevel value */ | |||||
MODIFY_REG(PWR->CR, PWR_CR_PLS, sConfigPVD->PVDLevel); | |||||
/* Clear any previous config. Keep it clear if no event or IT mode is selected */ | |||||
__HAL_PWR_PVD_EXTI_DISABLE_EVENT(); | |||||
__HAL_PWR_PVD_EXTI_DISABLE_IT(); | |||||
__HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); | |||||
__HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE(); | |||||
/* Configure interrupt mode */ | |||||
if((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT) | |||||
{ | |||||
__HAL_PWR_PVD_EXTI_ENABLE_IT(); | |||||
} | |||||
/* Configure event mode */ | |||||
if((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT) | |||||
{ | |||||
__HAL_PWR_PVD_EXTI_ENABLE_EVENT(); | |||||
} | |||||
/* Configure the edge */ | |||||
if((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE) | |||||
{ | |||||
__HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE(); | |||||
} | |||||
if((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE) | |||||
{ | |||||
__HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE(); | |||||
} | |||||
} | |||||
/** | |||||
* @brief Enables the Power Voltage Detector(PVD). | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnablePVD(void) | |||||
{ | |||||
/* Enable the power voltage detector */ | |||||
*(__IO uint32_t *) CR_PVDE_BB = (uint32_t)ENABLE; | |||||
} | |||||
/** | |||||
* @brief Disables the Power Voltage Detector(PVD). | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_DisablePVD(void) | |||||
{ | |||||
/* Disable the power voltage detector */ | |||||
*(__IO uint32_t *) CR_PVDE_BB = (uint32_t)DISABLE; | |||||
} | |||||
/** | |||||
* @brief Enables the WakeUp PINx functionality. | |||||
* @param WakeUpPinx: Specifies the Power Wake-Up pin to enable. | |||||
* This parameter can be one of the following values: | |||||
* @arg PWR_WAKEUP_PIN1 | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinx) | |||||
{ | |||||
/* Check the parameter */ | |||||
assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx)); | |||||
/* Enable the EWUPx pin */ | |||||
*(__IO uint32_t *) CSR_EWUP_BB(WakeUpPinx) = (uint32_t)ENABLE; | |||||
} | |||||
/** | |||||
* @brief Disables the WakeUp PINx functionality. | |||||
* @param WakeUpPinx: Specifies the Power Wake-Up pin to disable. | |||||
* This parameter can be one of the following values: | |||||
* @arg PWR_WAKEUP_PIN1 | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx) | |||||
{ | |||||
/* Check the parameter */ | |||||
assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx)); | |||||
/* Disable the EWUPx pin */ | |||||
*(__IO uint32_t *) CSR_EWUP_BB(WakeUpPinx) = (uint32_t)DISABLE; | |||||
} | |||||
/** | |||||
* @brief Enters Sleep mode. | |||||
* @note In Sleep mode, all I/O pins keep the same state as in Run mode. | |||||
* @param Regulator: Regulator state as no effect in SLEEP mode - allows to support portability from legacy software | |||||
* @param SLEEPEntry: Specifies if SLEEP mode is entered with WFI or WFE instruction. | |||||
* When WFI entry is used, tick interrupt have to be disabled if not desired as | |||||
* the interrupt wake up source. | |||||
* This parameter can be one of the following values: | |||||
* @arg PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction | |||||
* @arg PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry) | |||||
{ | |||||
/* Check the parameters */ | |||||
/* No check on Regulator because parameter not used in SLEEP mode */ | |||||
/* Prevent unused argument(s) compilation warning */ | |||||
UNUSED(Regulator); | |||||
assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry)); | |||||
/* Clear SLEEPDEEP bit of Cortex System Control Register */ | |||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); | |||||
/* Select SLEEP mode entry -------------------------------------------------*/ | |||||
if(SLEEPEntry == PWR_SLEEPENTRY_WFI) | |||||
{ | |||||
/* Request Wait For Interrupt */ | |||||
__WFI(); | |||||
} | |||||
else | |||||
{ | |||||
/* Request Wait For Event */ | |||||
__SEV(); | |||||
__WFE(); | |||||
__WFE(); | |||||
} | |||||
} | |||||
/** | |||||
* @brief Enters Stop mode. | |||||
* @note In Stop mode, all I/O pins keep the same state as in Run mode. | |||||
* @note When exiting Stop mode by using an interrupt or a wakeup event, | |||||
* HSI RC oscillator is selected as system clock. | |||||
* @note When the voltage regulator operates in low power mode, an additional | |||||
* startup delay is incurred when waking up from Stop mode. | |||||
* By keeping the internal regulator ON during Stop mode, the consumption | |||||
* is higher although the startup time is reduced. | |||||
* @param Regulator: Specifies the regulator state in Stop mode. | |||||
* This parameter can be one of the following values: | |||||
* @arg PWR_MAINREGULATOR_ON: Stop mode with regulator ON | |||||
* @arg PWR_LOWPOWERREGULATOR_ON: Stop mode with low power regulator ON | |||||
* @param STOPEntry: Specifies if Stop mode in entered with WFI or WFE instruction. | |||||
* This parameter can be one of the following values: | |||||
* @arg PWR_STOPENTRY_WFI: Enter Stop mode with WFI instruction | |||||
* @arg PWR_STOPENTRY_WFE: Enter Stop mode with WFE instruction | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry) | |||||
{ | |||||
/* Check the parameters */ | |||||
assert_param(IS_PWR_REGULATOR(Regulator)); | |||||
assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); | |||||
/* Clear PDDS bit in PWR register to specify entering in STOP mode when CPU enter in Deepsleep */ | |||||
CLEAR_BIT(PWR->CR, PWR_CR_PDDS); | |||||
/* Select the voltage regulator mode by setting LPDS bit in PWR register according to Regulator parameter value */ | |||||
MODIFY_REG(PWR->CR, PWR_CR_LPDS, Regulator); | |||||
/* Set SLEEPDEEP bit of Cortex System Control Register */ | |||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); | |||||
/* Select Stop mode entry --------------------------------------------------*/ | |||||
if(STOPEntry == PWR_STOPENTRY_WFI) | |||||
{ | |||||
/* Request Wait For Interrupt */ | |||||
__WFI(); | |||||
} | |||||
else | |||||
{ | |||||
/* Request Wait For Event */ | |||||
__SEV(); | |||||
PWR_OverloadWfe(); /* WFE redefine locally */ | |||||
PWR_OverloadWfe(); /* WFE redefine locally */ | |||||
} | |||||
/* Reset SLEEPDEEP bit of Cortex System Control Register */ | |||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); | |||||
} | |||||
/** | |||||
* @brief Enters Standby mode. | |||||
* @note In Standby mode, all I/O pins are high impedance except for: | |||||
* - Reset pad (still available) | |||||
* - TAMPER pin if configured for tamper or calibration out. | |||||
* - WKUP pin (PA0) if enabled. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnterSTANDBYMode(void) | |||||
{ | |||||
/* Select Standby mode */ | |||||
SET_BIT(PWR->CR, PWR_CR_PDDS); | |||||
/* Set SLEEPDEEP bit of Cortex System Control Register */ | |||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); | |||||
/* This option is used to ensure that store operations are completed */ | |||||
#if defined ( __CC_ARM) | |||||
__force_stores(); | |||||
#endif | |||||
/* Request Wait For Interrupt */ | |||||
__WFI(); | |||||
} | |||||
/** | |||||
* @brief Indicates Sleep-On-Exit when returning from Handler mode to Thread mode. | |||||
* @note Set SLEEPONEXIT bit of SCR register. When this bit is set, the processor | |||||
* re-enters SLEEP mode when an interruption handling is over. | |||||
* Setting this bit is useful when the processor is expected to run only on | |||||
* interruptions handling. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnableSleepOnExit(void) | |||||
{ | |||||
/* Set SLEEPONEXIT bit of Cortex System Control Register */ | |||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); | |||||
} | |||||
/** | |||||
* @brief Disables Sleep-On-Exit feature when returning from Handler mode to Thread mode. | |||||
* @note Clears SLEEPONEXIT bit of SCR register. When this bit is set, the processor | |||||
* re-enters SLEEP mode when an interruption handling is over. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_DisableSleepOnExit(void) | |||||
{ | |||||
/* Clear SLEEPONEXIT bit of Cortex System Control Register */ | |||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); | |||||
} | |||||
/** | |||||
* @brief Enables CORTEX M3 SEVONPEND bit. | |||||
* @note Sets SEVONPEND bit of SCR register. When this bit is set, this causes | |||||
* WFE to wake up when an interrupt moves from inactive to pended. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_EnableSEVOnPend(void) | |||||
{ | |||||
/* Set SEVONPEND bit of Cortex System Control Register */ | |||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); | |||||
} | |||||
/** | |||||
* @brief Disables CORTEX M3 SEVONPEND bit. | |||||
* @note Clears SEVONPEND bit of SCR register. When this bit is set, this causes | |||||
* WFE to wake up when an interrupt moves from inactive to pended. | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_DisableSEVOnPend(void) | |||||
{ | |||||
/* Clear SEVONPEND bit of Cortex System Control Register */ | |||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); | |||||
} | |||||
/** | |||||
* @brief This function handles the PWR PVD interrupt request. | |||||
* @note This API should be called under the PVD_IRQHandler(). | |||||
* @retval None | |||||
*/ | |||||
void HAL_PWR_PVD_IRQHandler(void) | |||||
{ | |||||
/* Check PWR exti flag */ | |||||
if(__HAL_PWR_PVD_EXTI_GET_FLAG() != RESET) | |||||
{ | |||||
/* PWR PVD interrupt user callback */ | |||||
HAL_PWR_PVDCallback(); | |||||
/* Clear PWR Exti pending bit */ | |||||
__HAL_PWR_PVD_EXTI_CLEAR_FLAG(); | |||||
} | |||||
} | |||||
/** | |||||
* @brief PWR PVD interrupt callback | |||||
* @retval None | |||||
*/ | |||||
__weak void HAL_PWR_PVDCallback(void) | |||||
{ | |||||
/* NOTE : This function Should not be modified, when the callback is needed, | |||||
the HAL_PWR_PVDCallback could be implemented in the user file | |||||
*/ | |||||
} | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** | |||||
* @} | |||||
*/ | |||||
#endif /* HAL_PWR_MODULE_ENABLED */ | |||||
/** | |||||
* @} | |||||
*/ | |||||
/** | |||||
* @} | |||||
*/ | |||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |