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