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****/ | |||