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 | |||
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> |
@@ -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. | |||
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 | |||
(all can be remapped) | |||
@@ -52,15 +52,19 @@ ARMTARGET?= -mcpu=cortex-m3 -mthumb | |||
LINKER_SCRIPT=$(STM32)/f103c8t6/STM32F103C8T6_FLASH.ld | |||
SRCS+= \ | |||
misc.c \ | |||
hal_generic.c \ | |||
startup_stm32f103xb.s \ | |||
stm32f1xx_hal.c \ | |||
stm32f1xx_hal_cortex.c \ | |||
stm32f1xx_hal_dma.c \ | |||
stm32f1xx_hal_gpio.c \ | |||
stm32f1xx_hal_pcd.c \ | |||
stm32f1xx_hal_pcd_ex.c \ | |||
stm32f1xx_hal_pwr.c \ | |||
stm32f1xx_hal_rcc.c \ | |||
stm32f1xx_hal_rcc_ex.c \ | |||
stm32f1xx_hal_uart.c \ | |||
stm32f1xx_ll_usb.c \ | |||
system_stm32f1xx.c | |||
@@ -108,6 +112,14 @@ CFLAGS+= -I$(STM32)/l151ccux | |||
CFLAGS+= -DSTM32L151xC | |||
.endif | |||
# RS485 Framing | |||
.if ${MK_RS485FRAME} == "yes" | |||
SRCS+= \ | |||
rs485frame.c | |||
CFLAGS+= -I$(SRCTOP)/rs485hid | |||
.endif | |||
# USB CDC | |||
.if ${MK_USB_CDC} == "yes" | |||
.PATH: $(STM32)/usb | |||
@@ -8,6 +8,7 @@ __DEFAULT_YES_OPTIONS = STROBE \ | |||
__DEFAULT_NO_OPTIONS = \ | |||
NODE151 \ | |||
RS485FRAME \ | |||
STM32F103 \ | |||
SX1276 \ | |||
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 | |||
.PHONY: all | |||
@@ -34,6 +34,7 @@ CFLAGS += -I$(.CURDIR)/.. | |||
WITH_STM32F103 = yes | |||
WITH_USB_CDC = yes | |||
WITH_RS485FRAME = yes | |||
.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 <rs485frame.h> | |||
#include <misc.h> | |||
#include <stdbool.h> | |||
@@ -36,6 +38,14 @@ | |||
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 | |||
c13led(const void *none) | |||
{ | |||
@@ -56,6 +66,11 @@ c13led(const void *none) | |||
} | |||
SYSINIT(c13led, SI_SUB_HAL, SI_ORDER_SECOND, c13led, NULL); | |||
#if 0 | |||
#undef usb_printf | |||
#define usb_printf debug_printf | |||
#endif | |||
/* | |||
* Referenced from: | |||
* Projects/STM32F103RB-Nucleo/Applications/USB_Device/HID_Standalone/Src/main.c | |||
@@ -128,24 +143,28 @@ void | |||
txdone(void) | |||
{ | |||
usb_printf("txdone\r\n"); | |||
//Radio.Rx(0); | |||
gottxdone = 1; | |||
} | |||
void | |||
txtimeout(void) | |||
errfunc(void) | |||
{ | |||
usb_printf("txtimeout\r\n"); | |||
goterr = 1; | |||
} | |||
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 | |||
@@ -235,20 +254,29 @@ process_line(char *start, char *end) | |||
usb_printf("invalid pkt\r\n"); | |||
return; | |||
} | |||
//Radio.Send(pktbuf, len / 2); | |||
rs485_starttx(pktbuf, len / 2); | |||
return; | |||
} | |||
usb_printf("line: %.*s", end - start, start); | |||
fflush(vcp_usb); | |||
} | |||
static void | |||
WaitForIRQ() | |||
{ | |||
__disable_irq(); | |||
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); | |||
__enable_irq( ); | |||
} | |||
int | |||
main(void) | |||
{ | |||
sysinit_run(); | |||
//debug_printf("starting...\n"); | |||
debug_printf("starting...\n"); | |||
#if 1 | |||
int i; | |||
@@ -281,8 +309,66 @@ main(void) | |||
int inpbufpos = 0; | |||
int cpylen; | |||
rs485_register(txdone, rxdone, errfunc); | |||
rs485_startrx(); | |||
unsigned lasttick = -1; | |||
uint32_t gt; | |||
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 (CDC_RX_LEN) { | |||
@@ -4,11 +4,34 @@ | |||
#include <sysinit.h> | |||
#include <stm32f1xx_hal_gpio.h> | |||
#include <stm32f1xx_hal_pcd.h> | |||
#include <usb_device.h> | |||
static void | |||
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(); | |||
} | |||
@@ -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_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_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_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_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_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_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 | |||
@@ -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_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_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_ll_usb.h STM32CubeF1 Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_usb.h |
@@ -3,4 +3,6 @@ | |||
#include "stm32f1xx_hal.h" | |||
void Error_Handler(void); | |||
#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****/ |