aboutsummaryrefslogtreecommitdiff
path: root/src/entropy
diff options
context:
space:
mode:
authorFredrik Thulin <fredrik@thulin.net>2015-01-15 17:04:03 +0100
committerFredrik Thulin <fredrik@thulin.net>2015-01-15 17:04:03 +0100
commit39cac7918987fc603dc54886e107af026583592e (patch)
treeacb95e5cebc2f410840659cc7e6d1a74331e3985 /src/entropy
parent3347165e2927ec73014eafdfc0c650904a4b67d4 (diff)
init
Diffstat (limited to 'src/entropy')
-rw-r--r--src/entropy/Makefile51
-rw-r--r--src/entropy/main.c369
-rw-r--r--src/entropy/main.h4
-rw-r--r--src/entropy/stm32f4xx_hal_msp.c97
-rw-r--r--src/entropy/stm32f4xx_it.c200
-rw-r--r--src/entropy/stm32f4xx_it.h70
-rw-r--r--src/entropy/stm_init.c311
-rw-r--r--src/entropy/stm_init.h17
-rw-r--r--src/entropy/system_stm32f4xx.c270
9 files changed, 1389 insertions, 0 deletions
diff --git a/src/entropy/Makefile b/src/entropy/Makefile
new file mode 100644
index 0000000..b4c02b3
--- /dev/null
+++ b/src/entropy/Makefile
@@ -0,0 +1,51 @@
+# put your *.o targets here, make should handle the rest!
+SRCS = main.c stm_init.c system_stm32f4xx.c stm32f4xx_it.c stm32f4xx_hal_msp.c
+
+# all the files will be generated with this name
+PROJ_NAME=entropy
+
+TOPLEVEL=../..
+include $(TOPLEVEL)/common.mk
+
+
+OBJS = $(SRCS:.c=.o)
+
+###################################################
+
+.PHONY: lib proj
+
+all: lib proj
+
+lib:
+ $(MAKE) -C $(STD_PERIPH_LIB) STDPERIPH_SETTINGS="$(STDPERIPH_SETTINGS)"
+
+
+proj: $(PROJ_NAME).elf
+
+$(PROJ_NAME).elf: $(SRCS)
+ $(CC) $(CFLAGS) $^ -o $@ -L$(STD_PERIPH_LIB) -lstmf4 -L$(LDSCRIPT_INC) -T$(MCU_LINKSCRIPT) -g
+ $(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex
+ $(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
+ $(OBJDUMP) -St $(PROJ_NAME).elf >$(PROJ_NAME).lst
+ $(SIZE) $(PROJ_NAME).elf
+
+clean:
+ find ./ -name '*~' | xargs rm -f
+ rm -f *.o
+ rm -f $(PROJ_NAME).elf
+ rm -f $(PROJ_NAME).hex
+ rm -f $(PROJ_NAME).bin
+ rm -f $(PROJ_NAME).map
+ rm -f $(PROJ_NAME).lst
+
+really-clean: clean
+ $(MAKE) -C $(STD_PERIPH_LIB) clean
+
+debug:
+ $(GDB) -ex "target remote localhost:3333" \
+ -ex "set remote hardware-breakpoint-limit 6" \
+ -ex "set remote hardware-watchpoint-limit 4" $(PROJ_NAME).elf
+
+flash-target:
+ $(OPENOCD) -f $(OPENOCD_BOARD_DIR)/$(OPENOCD_PROC_FILE) \
+ -c "program $(PROJ_NAME).elf verify reset"
diff --git a/src/entropy/main.c b/src/entropy/main.c
new file mode 100644
index 0000000..e29e00c
--- /dev/null
+++ b/src/entropy/main.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2014, 2015 NORDUnet A/S
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the NORDUnet nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDER 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.
+ */
+#include <string.h>
+
+#include "main.h"
+#include "stm_init.h"
+
+#define MODE_DELTAS 1
+#define MODE_ENTROPY 2
+
+#define UART_RANDOM_BYTES_PER_CHUNK 8
+#define UART_DELTA_WORDS_PER_CHUNK 32
+
+extern DMA_HandleTypeDef hdma_tim;
+
+__IO ITStatus UartReady = RESET;
+
+static union {
+ uint8_t rnd[257]; /* 256 bytes + 1 for use in the POST */
+ uint32_t rnd32[64];
+} buf;
+
+/* First DMA value (DMA_counters[0]) is unreliable, leftover in DMA FIFO perhaps? */
+#define FIRST_DMA_IDX_USED 3
+
+/*
+ * Number of counters used to produce 8 bits of entropy is:
+ * 8 * 4 - four flanks are used to produce two (hopefully) uncorrelated bits (a and b)
+ * * 2 - von Neumann will on average discard 1/2 of the bits 'a' and 'b'
+ */
+#define DMA_COUNTERS_NUM ((UART_RANDOM_BYTES_PER_CHUNK * 8 * 4 * 2) + FIRST_DMA_IDX_USED + 1)
+struct DMA_params {
+ volatile uint32_t buf0[DMA_COUNTERS_NUM];
+ volatile uint32_t buf1[DMA_COUNTERS_NUM];
+ volatile uint32_t write_buf;
+};
+
+static struct DMA_params DMA = {
+ {},
+ {},
+ 0,
+};
+
+
+/* The main work horse functions */
+void get_entropy32(uint32_t num_bytes, uint32_t buf_idx);
+void perform_delta32(uint32_t count, const uint32_t start);
+/* Various support functions */
+inline uint32_t get_one_bit(void) __attribute__((__always_inline__));
+volatile uint32_t *restart_DMA(void);
+inline volatile uint32_t *get_DMA_read_buf(void);
+inline uint32_t safe_get_counter(volatile uint32_t *dmabuf, const uint32_t dmabuf_idx);
+/* static void Error_Handler(void); */
+
+
+
+int
+main()
+{
+ uint32_t count = 0, send_bytes, idx = 255, send_sync_bytes_in = 0, i;
+ uint32_t mode = MODE_ENTROPY;
+
+ /* Initialize buffers */
+ memset(buf.rnd, 0, sizeof(buf.rnd));
+ for (i = 0; i < DMA_COUNTERS_NUM; i++) {
+ DMA.buf0[i] = 0xffff0000 + i;
+ DMA.buf1[i] = 0xffff0100 + i;
+ }
+
+ stm_init((uint32_t *) &DMA.buf0, DMA_COUNTERS_NUM);
+ /* Ensure there is actual Timer IC counters in both DMA buffers. */
+ restart_DMA();
+ restart_DMA();
+
+ /* Toggle GREEN LED to show we've initialized */
+ {
+ for (i = 0; i < 10; i++) {
+ HAL_GPIO_TogglePin(LED_PORT, LED_GREEN);
+ HAL_Delay(125);
+ }
+ }
+
+ if (mode == MODE_ENTROPY) {
+ /* Initialize buffer with the first round of entropy */
+ idx = 0;
+ send_bytes = UART_RANDOM_BYTES_PER_CHUNK;
+ get_entropy32(send_bytes / 4, idx);
+ }
+
+ /*
+ * Main loop
+ */
+ while (1) {
+ if (! (count % 1000)) {
+ HAL_GPIO_TogglePin(LED_PORT, LED_YELLOW);
+ }
+
+ switch (mode)
+ {
+ case MODE_DELTAS:
+ if (! send_sync_bytes_in) {
+ /* Send 128 bits of sync-bytes every 1024 bytes */
+ send_sync_bytes_in = 1024;
+ memset(buf.rnd, 0xf0, sizeof(buf.rnd));
+ send_bytes = 16;
+ } else {
+ perform_delta32(UART_DELTA_WORDS_PER_CHUNK, 0);
+ send_bytes = UART_DELTA_WORDS_PER_CHUNK * 4;
+ send_sync_bytes_in -= send_bytes;
+ }
+ idx = 0;
+ break;;
+ case MODE_ENTROPY:
+ break;;
+ }
+
+ /* Send buf on UART (non blocking interrupt driven send). */
+ if (HAL_UART_Transmit_IT(&huart1, (uint8_t *) buf.rnd + idx, (uint16_t) send_bytes) == HAL_OK) {
+
+ if (mode == MODE_ENTROPY) {
+ /* Flip-flop idx between the value 0 and the value BYTES_PER_CHUNK.
+ * This enables collecting of BYTES_PER_CHUNK bytes of entropy at the same
+ * time as the USART sends the previous BYTES_PER_CHUNK using interrupts.
+ */
+ idx = idx ? 0 : UART_RANDOM_BYTES_PER_CHUNK;
+ get_entropy32(send_bytes / 4, idx / 4);
+ }
+
+ while (UartReady != SET) { ; }
+ UartReady = RESET;
+ } else {
+ /* Turn on RED LED for one second */
+ HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+ HAL_Delay(1000);
+ HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_RESET);
+ }
+
+ count++;
+ }
+
+}
+
+/**
+ * @brief Fill a buffer (buf.rnd32) with Timer IC counter values.
+ * Each value is 16 bits, but this function packs two counters
+ * into a 32 bit word so (2 * count) timer values are collected.
+ * @param count: Number of 32 bit words to collect.
+ * @param start: Start index value into buf.rnd32.
+ * @retval None
+ */
+void perform_delta32(uint32_t count, const uint32_t start)
+{
+ /* Start at end of buffer so restart_DMA() is called. */
+ static uint32_t dmabuf_idx = DMA_COUNTERS_NUM - 1;
+ volatile uint32_t *dmabuf;
+ uint32_t i, buf_idx;
+
+ dmabuf = get_DMA_read_buf();
+ buf_idx = start;
+
+ do {
+ if (dmabuf_idx > DMA_COUNTERS_NUM - 1 - 2) {
+ /* If there are less than two counters available in the dmabuf,
+ * we need to get a fresh DMA buffer first.
+ */
+ dmabuf = restart_DMA();
+ dmabuf_idx = FIRST_DMA_IDX_USED;
+ }
+
+ i = safe_get_counter(dmabuf, dmabuf_idx++) << 16;
+ i |= safe_get_counter(dmabuf, dmabuf_idx++);
+
+ /* Store the 32 bits in output buffer */
+ buf.rnd32[buf_idx++] = i;
+ } while (--count);
+}
+
+
+/**
+ * @brief Collect `count' times 32 bits of entropy.
+ * @param count: Number of 32 bit words to collect.
+ * @param start: Start index value into buf.rnd32.
+ * @retval None
+ */
+inline void get_entropy32(uint32_t count, const uint32_t start)
+{
+ uint32_t i, bits, buf_idx;
+
+ buf_idx = start;
+
+ do {
+ bits = 0;
+ /* Get 32 bits of entropy.
+ */
+ for (i = 32; i; i--) {
+ bits <<= 1;
+ bits += get_one_bit();
+ }
+
+ /* Store the 32 bits in output buffer */
+ buf.rnd32[buf_idx++] = bits;
+ } while (--count);
+}
+
+/**
+ * @brief Return one bit of entropy.
+ * @param None
+ * @retval One bit, in the LSB of an uint32_t since this is a 32 bit MCU.
+ */
+inline uint32_t get_one_bit()
+{
+ register uint32_t a, b, temp;
+ /* Start at end of buffer so restart_DMA() is called. */
+ static uint32_t dmabuf_idx = DMA_COUNTERS_NUM - 1;
+ volatile uint32_t *dmabuf;
+
+ dmabuf = get_DMA_read_buf();
+
+ do {
+ if (dmabuf_idx > DMA_COUNTERS_NUM - 1 - 4) {
+ /* If there are less than four counters available in the dmabuf,
+ * we need to get a fresh DMA buffer first.
+ */
+ dmabuf = restart_DMA();
+ dmabuf_idx = FIRST_DMA_IDX_USED;
+ }
+
+ /* Get one bit from two subsequent counter values */
+ a = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+ temp = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+ a ^= temp;
+
+ /* Get another bit from two other counter values. Getting
+ * two bits from two unrelated [1] pairs of counters is
+ * supposed to help against phase correlations between the
+ * frequency of the noise and the MCU sampling rate.
+ *
+ * [1] This is how it is done in the ARRGH board, although
+ * since this is a faster MCU and DMA is used the two
+ * pairs are more likely to still be related since they
+ * are more likely to be directly subsequent diode
+ * breakdowns. Have to evaluate if this is enough.
+ */
+ b = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+ temp = safe_get_counter(dmabuf, dmabuf_idx++) & 1;
+ b ^= temp;
+
+ /* Do von Neumann extraction of a and b to eliminate bias
+ * (only eliminates bias if a and b are uncorrelated)
+ */
+ } while (a == b);
+
+ return a;
+}
+
+/**
+ * @brief Return a pointer to the DMA.buf NOT currently being written to
+ * @param None
+ * @retval Pointer to buffer currently being read from.
+ */
+inline volatile uint32_t *get_DMA_read_buf(void)
+{
+ return DMA.write_buf ? DMA.buf0 : DMA.buf1;
+}
+
+/**
+ * @brief Return a pointer to the DMA.buf currently being written to
+ * @param None
+ * @retval Pointer to buffer currently being written to.
+ */
+inline volatile uint32_t *get_DMA_write_buf(void)
+{
+ return DMA.write_buf ? DMA.buf1 : DMA.buf0;
+}
+
+/**
+ * @brief Initiate DMA collection of another buffer of Timer IC values.
+ * @param None
+ * @retval Pointer to buffer full of Timer IC values ready to be consumed.
+ */
+volatile uint32_t *restart_DMA(void)
+{
+ /* Wait for transfer complete flag to become SET. Trying to change the
+ * M0AR register while the DMA is running is a no-no.
+ */
+ while(__HAL_DMA_GET_FLAG(&hdma_tim, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_tim)) == RESET) { ; }
+
+ /* Switch buffer being written to */
+ DMA.write_buf ^= 1;
+ hdma_tim.Instance->M0AR = (uint32_t) get_DMA_write_buf();
+
+ /* Start at 0 to help manual inspection */
+ TIM2->CNT = 0;
+
+ /* Clear the transfer complete flag before re-enabling DMA */
+ __HAL_DMA_CLEAR_FLAG(&hdma_tim, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_tim));
+ __HAL_DMA_ENABLE(&hdma_tim);
+
+ return get_DMA_read_buf();
+}
+
+/**
+ * @brief Get one counter value, guaranteed to not have been used before.
+ * @param dmabuf: Pointer to the current DMA read buffer.
+ * @param dmabuf_idx: Word index into `dmabuf'.
+ * @retval One Timer IC counter value.
+ */
+inline uint32_t safe_get_counter(volatile uint32_t *dmabuf, const uint32_t dmabuf_idx) {
+ register uint32_t a;
+ /* Prevent re-use of values. DMA stored values are <= 0xffff. */
+ do {
+ a = dmabuf[dmabuf_idx];
+ } while (a > 0xffff);
+ dmabuf[dmabuf_idx] = 0xffff0000;
+ return a;
+}
+
+/* UART transmit complete callback */
+void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UH)
+{
+ if (UH->Instance == USART1) {
+ /* Signal UART transmit complete to the code in the main loop. */
+ UartReady = SET;
+ }
+}
+
+/**
+ * @brief This function is executed in case of error occurrence.
+ * @param None
+ * @retval None
+ */
+/* Currently unused function */
+#if 0
+static void Error_Handler(void)
+{
+ /* Turn on RED LED and then loop indefinitely */
+ HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+ while(1) { ; }
+}
+#endif
diff --git a/src/entropy/main.h b/src/entropy/main.h
new file mode 100644
index 0000000..902ecf4
--- /dev/null
+++ b/src/entropy/main.h
@@ -0,0 +1,4 @@
+#ifndef __MAIN_H
+#define __MAIN_H
+
+#endif /* __MAIN_H */
diff --git a/src/entropy/stm32f4xx_hal_msp.c b/src/entropy/stm32f4xx_hal_msp.c
new file mode 100644
index 0000000..cf59a07
--- /dev/null
+++ b/src/entropy/stm32f4xx_hal_msp.c
@@ -0,0 +1,97 @@
+#include "stm_init.h"
+#include "stm32f4xx_hal.h"
+
+static void Error_Handler(void);
+extern void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma);
+
+void HAL_TIM_IC_MspInit(TIM_HandleTypeDef* htim)
+{
+ if (htim->Instance == TIM2) {
+ /* Configure DMA input capturing.
+ *
+ * Amplified avalanche noise is present at pin PA1,
+ * which has Alternate Function TIM2_CH2.
+ *
+ * TIM2_CH2 is DMA1 stream 6, channel 3 according to Table 28
+ * (DMA1 request mapping) in the reference manual (RM0368).
+ */
+ __DMA1_CLK_ENABLE();
+ __TIM2_CLK_ENABLE();
+ __GPIOA_CLK_ENABLE();
+
+ hdma_tim.Instance = DMA1_Stream6;
+
+ hdma_tim.Init.Channel = DMA_CHANNEL_3;
+ hdma_tim.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
+ hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
+ hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+ hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
+ hdma_tim.Init.Mode = DMA_NORMAL;
+ hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
+ hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
+ hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
+ hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
+
+ /* Link hdma_tim to hdma[2] (channel3) */
+ __HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC2], hdma_tim);
+
+ /* Initialize TIMx DMA handle */
+ if (HAL_DMA_Init(&hdma_tim) != HAL_OK) {
+ Error_Handler();
+ }
+ }
+}
+
+void HAL_UART_MspInit(UART_HandleTypeDef* huart)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ if (huart->Instance == USART1) {
+ /* Peripheral clock enable */
+ __USART1_CLK_ENABLE();
+
+ /**USART1 GPIO Configuration
+ PA9 ------> USART1_TX
+ PA10 ------> USART1_RX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ /* NVIC for interrupt mode */
+ HAL_NVIC_SetPriority(USART1_IRQn, 0, 1);
+ HAL_NVIC_EnableIRQ(USART1_IRQn);
+ }
+}
+
+void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
+{
+ if (huart->Instance == USART1) {
+ /* Peripheral clock disable */
+ __USART1_CLK_DISABLE();
+
+ /**USART1 GPIO Configuration
+ PA9 ------> USART1_TX
+ PA10 ------> USART1_RX
+ */
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
+ }
+}
+
+/**
+ * @brief This function is executed in case of error occurrence.
+ * @param None
+ * @retval None
+ */
+static void Error_Handler(void)
+{
+ /* Turn on RED LED and then loop indefinitely */
+ HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+
+ while (1) { ; }
+}
diff --git a/src/entropy/stm32f4xx_it.c b/src/entropy/stm32f4xx_it.c
new file mode 100644
index 0000000..17a7cf9
--- /dev/null
+++ b/src/entropy/stm32f4xx_it.c
@@ -0,0 +1,200 @@
+/**
+ ******************************************************************************
+ * @file GPIO/GPIO_IOToggle/Src/stm32f4xx_it.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 26-February-2014
+ * @brief Main Interrupt Service Routines.
+ * This file provides template for all exceptions handler and
+ * peripherals interrupt service routine.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+ *
+ * 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.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_it.h"
+#include "stm_init.h"
+
+extern TIM_HandleTypeDef htim2;
+
+/** @addtogroup STM32F4xx_HAL_Examples
+ * @{
+ */
+
+/** @addtogroup GPIO_IOToggle
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/******************************************************************************/
+/* Cortex-M4 Processor Exceptions Handlers */
+/******************************************************************************/
+
+/**
+ * @brief This function handles NMI exception.
+ * @param None
+ * @retval None
+ */
+void NMI_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles Hard Fault exception.
+ * @param None
+ * @retval None
+ */
+void HardFault_Handler(void)
+{
+ /* Go to infinite loop when Hard Fault exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles Memory Manage exception.
+ * @param None
+ * @retval None
+ */
+void MemManage_Handler(void)
+{
+ /* Go to infinite loop when Memory Manage exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles Bus Fault exception.
+ * @param None
+ * @retval None
+ */
+void BusFault_Handler(void)
+{
+ /* Go to infinite loop when Bus Fault exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles Usage Fault exception.
+ * @param None
+ * @retval None
+ */
+void UsageFault_Handler(void)
+{
+ /* Go to infinite loop when Usage Fault exception occurs */
+ while (1)
+ {
+ }
+}
+
+/**
+ * @brief This function handles SVCall exception.
+ * @param None
+ * @retval None
+ */
+void SVC_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles Debug Monitor exception.
+ * @param None
+ * @retval None
+ */
+void DebugMon_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles PendSVC exception.
+ * @param None
+ * @retval None
+ */
+void PendSV_Handler(void)
+{
+}
+
+/**
+ * @brief This function handles SysTick Handler.
+ * @param None
+ * @retval None
+ */
+void SysTick_Handler(void)
+{
+ HAL_IncTick();
+}
+
+/******************************************************************************/
+/* STM32F4xx Peripherals Interrupt Handlers */
+/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
+/* available peripheral interrupt handler's name please refer to the startup */
+/* file (startup_stm32f4xx.s). */
+/******************************************************************************/
+
+/**
+ * @brief This function handles UART interrupt request.
+ * @param None
+ * @retval None
+ * @Note This function is redefined in "main.h" and related to DMA stream
+ * used for USART data transmission
+ */
+void USART1_IRQHandler(void)
+{
+ HAL_UART_IRQHandler(&huart1);
+}
+
+/**
+ * @brief This function handles DMA1 Stream 6 interrupt request.
+ * @param None
+ * @retval None
+ */
+void DMA1_Stream6_IRQHandler(void)
+{
+ HAL_DMA_IRQHandler(&hdma_tim);
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/entropy/stm32f4xx_it.h b/src/entropy/stm32f4xx_it.h
new file mode 100644
index 0000000..04c5a36
--- /dev/null
+++ b/src/entropy/stm32f4xx_it.h
@@ -0,0 +1,70 @@
+/**
+ ******************************************************************************
+ * @file GPIO/GPIO_IOToggle/Inc/stm32f4xx_it.h
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 26-February-2014
+ * @brief This file contains the headers of the interrupt handlers.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+ *
+ * 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.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_IT_H
+#define __STM32F4xx_IT_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "main.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+void NMI_Handler(void);
+void HardFault_Handler(void);
+void MemManage_Handler(void);
+void BusFault_Handler(void);
+void UsageFault_Handler(void);
+void SVC_Handler(void);
+void DebugMon_Handler(void);
+void PendSV_Handler(void);
+void SysTick_Handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4xx_IT_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/entropy/stm_init.c b/src/entropy/stm_init.c
new file mode 100644
index 0000000..4bf35b5
--- /dev/null
+++ b/src/entropy/stm_init.c
@@ -0,0 +1,311 @@
+/**
+ ******************************************************************************
+ * @file GPIO/GPIO_IOToggle/Src/main.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 26-February-2014
+ * @brief This example describes how to configure and use GPIOs through
+ * the STM32F4xx HAL API.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+ *
+ * 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.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm_init.h"
+//#include "stm32f4xx_hal.h"
+//#include "stm32f4xx_hal_rcc.h"
+
+
+/** @addtogroup STM32F4xx_HAL_Examples
+ * @{
+ */
+
+/** @addtogroup GPIO_IOToggle
+ * @{
+ */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+#define UART1_BAUD_RATE 460800
+
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+static GPIO_InitTypeDef GPIO_InitStruct;
+TIM_HandleTypeDef htim2;
+UART_HandleTypeDef huart1;
+DMA_HandleTypeDef hdma_tim;
+
+/* Private function prototypes -----------------------------------------------*/
+static void SystemClock_Config(void);
+static void Error_Handler(void);
+static void MX_GPIO_Init(void);
+static void MX_TIM2_Init(uint32_t *counters_buf, uint16_t counters);
+static void MX_USART1_UART_Init(void);
+/* Private functions ---------------------------------------------------------*/
+
+/**
+ * @brief Main program
+ * @param None
+ * @retval None
+ */
+void stm_init(uint32_t *buf0, uint16_t counters)
+{
+ /* Generic STM32 initialization.
+
+ To proceed, 3 steps are required: */
+
+ /* STM32F4xx HAL library initialization:
+ - Configure the Flash prefetch, instruction and Data caches
+ - Configure the Systick to generate an interrupt each 1 msec
+ - Set NVIC Group Priority to 4
+ - Global MSP (MCU Support Package) initialization
+ */
+ HAL_Init();
+
+ /* Configure the system clock */
+ SystemClock_Config();
+
+ /* System interrupt init*/
+ /* Sets the priority grouping field */
+ HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
+ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
+
+ /* Initialize all configured peripherals */
+ MX_GPIO_Init();
+ MX_TIM2_Init(buf0, counters);
+ MX_USART1_UART_Init();
+}
+
+
+/**
+ * @brief System Clock Configuration
+ * The system Clock is configured as follow :
+ * System Clock source = PLL (HSE)
+ * SYSCLK(Hz) = 42000000
+ * HCLK(Hz) = 42000000
+ * AHB Prescaler = 1
+ * APB1 Prescaler = 1
+ * APB2 Prescaler = 1
+ * HSI Frequency(Hz) = 16000000
+ * PLL_M = 8
+ * PLL_N = 336
+ * PLL_P = 8
+ * PLL_Q = 7 (unused)
+ * VDD(V) = 3.3
+ * Main regulator output voltage = Scale2 mode
+ * Flash Latency(WS) = 1
+ * @param None
+ * @retval None
+ */
+static void SystemClock_Config(void)
+{
+ RCC_ClkInitTypeDef RCC_ClkInitStruct;
+ RCC_OscInitTypeDef RCC_OscInitStruct;
+
+ /* Enable Power Control clock */
+ __PWR_CLK_ENABLE();
+
+ /* The voltage scaling allows optimizing the power consumption when the device is
+ clocked below the maximum system frequency, to update the voltage scaling value
+ regarding system frequency refer to product datasheet. */
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
+
+ /* Enable HSE Oscillator and activate PLL with HSE as source.
+ *
+ * With 8 MHz HSE oscillator, M=/8, N=*336, P=/8 gives 42 MHz SYSCLK.
+ * Divider Q is unused in this configuration.
+ */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+ RCC_OscInitStruct.PLL.PLLM = 8;
+ RCC_OscInitStruct.PLL.PLLN = 336;
+ RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8;
+ RCC_OscInitStruct.PLL.PLLQ = 7;
+
+ if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
+ Error_Handler();
+ }
+
+ /* Select PLL as system clock source */
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; /* AHB prescaler */
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; /* APB1 prescaler /1 gives 42 MHz APB1 */
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; /* APB2 prescaler /1 gives 42 MHz APB2 */
+ if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
+ Error_Handler();
+ }
+
+}
+
+
+/** Configure pins as
+
+ PB12 ------> GREEN LED
+ PB13 ------> YELLOW LED
+ PB14 ------> GREEN lED
+ PB15 ------> BLUE LED
+ PA1 ------> TIM2_CH2 (Avalanche noise)
+*/
+void MX_GPIO_Init(void)
+{
+ /* GPIO Ports Clock Enable */
+ __GPIOA_CLK_ENABLE();
+ __GPIOB_CLK_ENABLE();
+ __GPIOC_CLK_ENABLE();
+
+ /*Configure LED GPIO pins PB12==red, PB13==yellow, PB14==green, PB15==blue */
+ GPIO_InitStruct.Pin = LED_RED | LED_YELLOW | LED_GREEN | LED_BLUE;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
+
+ /* Configure PA1 (TIM2_Channel2) (Avalanche noise trigger) */
+ GPIO_InitStruct.Pin = GPIO_PIN_1;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+}
+
+/* TIM2 init function.
+ * TIM2 is used in capture mode, triggered off the avalanche noise pin PA1.
+ */
+void MX_TIM2_Init(uint32_t *counters_buf, uint16_t counters)
+{
+ TIM_IC_InitTypeDef sICConfig;
+
+ __DMA1_CLK_ENABLE();
+ __TIM2_CLK_ENABLE();
+ __GPIOA_CLK_ENABLE();
+
+ htim2.Instance = TIM2;
+ htim2.Init.Prescaler = 0;
+ htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
+ htim2.Init.Period = 0xffff;
+ htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+ htim2.Init.RepetitionCounter = 0;
+
+ /* Configure the Input Capture of channel 2.
+ * Trigger on rising edge. ICFilter = 0 means trigger on every event.
+ */
+ sICConfig.ICPolarity = TIM_ICPOLARITY_RISING;
+ sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
+ sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
+ sICConfig.ICFilter = 0; /* If set - Ignore additional state changes for a short while */
+
+ if (HAL_TIM_IC_Init(&htim2) != HAL_OK) {
+ /* Initialization Error */
+ Error_Handler();
+ }
+
+ if (HAL_TIM_IC_ConfigChannel(&htim2, &sICConfig, TIM_CHANNEL_2) != HAL_OK) {
+ /* Initialization Error */
+ Error_Handler();
+ }
+
+ /* Start the TIM input capture operation */
+ if (HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_2, counters_buf, counters) != HAL_OK) {
+ /* Starting Error */
+ Error_Handler();
+ }
+}
+
+
+/* USART1 init function
+ *
+ * USART1 uses PA9 and PA10.
+ */
+void MX_USART1_UART_Init(void)
+{
+
+ huart1.Instance = USART1;
+ huart1.Init.BaudRate = UART1_BAUD_RATE;
+ huart1.Init.WordLength = UART_WORDLENGTH_8B;
+ huart1.Init.StopBits = UART_STOPBITS_1;
+ huart1.Init.Parity = UART_PARITY_NONE;
+ huart1.Init.Mode = UART_MODE_TX; /* Only Transmit */
+ huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart1.Init.OverSampling = UART_OVERSAMPLING_16;
+
+ if (HAL_UART_Init(&huart1) != HAL_OK) {
+ /* Initialization Error */
+ Error_Handler();
+ }
+}
+
+
+/**
+ * @brief This function is executed in case of error occurrence.
+ * @param None
+ * @retval None
+ */
+static void Error_Handler(void)
+{
+ HAL_GPIO_WritePin(LED_PORT, LED_RED, GPIO_PIN_SET);
+ while(1) { ; }
+}
+
+#ifdef USE_FULL_ASSERT
+
+/**
+ * @brief Reports the name of the source file and the source line number
+ * where the assert_param error has occurred.
+ * @param file: pointer to the source file name
+ * @param line: assert_param error line source number
+ * @retval None
+ */
+void assert_failed(uint8_t* file, uint32_t line)
+{
+ /* User can add his own implementation to report the file name and line number,
+ ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+
+ /* Infinite loop */
+ while (1)
+ {
+ }
+}
+#endif
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/src/entropy/stm_init.h b/src/entropy/stm_init.h
new file mode 100644
index 0000000..6a5de19
--- /dev/null
+++ b/src/entropy/stm_init.h
@@ -0,0 +1,17 @@
+#ifndef __STM_INIT_H
+#define __STM_INIT_H
+
+#include "stm32f4xx_hal.h"
+
+#define LED_PORT GPIOB
+#define LED_RED GPIO_PIN_12
+#define LED_YELLOW GPIO_PIN_13
+#define LED_GREEN GPIO_PIN_14
+#define LED_BLUE GPIO_PIN_15
+
+extern UART_HandleTypeDef huart1;
+extern DMA_HandleTypeDef hdma_tim;
+
+extern void stm_init(uint32_t *buf0, uint16_t counters);
+
+#endif /* __STM_INIT_H */
diff --git a/src/entropy/system_stm32f4xx.c b/src/entropy/system_stm32f4xx.c
new file mode 100644
index 0000000..35f79ba
--- /dev/null
+++ b/src/entropy/system_stm32f4xx.c
@@ -0,0 +1,270 @@
+/**
+ ******************************************************************************
+ * @file system_stm32f4xx.c
+ * @author MCD Application Team
+ * @version V1.0.1
+ * @date 26-February-2014
+ * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
+ *
+ * This file provides two functions and one global variable to be called from
+ * user application:
+ * - SystemInit(): This function is called at startup just after reset and
+ * before branch to main program. This call is made inside
+ * the "startup_stm32f4xx.s" file.
+ *
+ * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
+ * by the user application to setup the SysTick
+ * timer or configure other parameters.
+ *
+ * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
+ * be called whenever the core clock is changed
+ * during program execution.
+ *
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * 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.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ ******************************************************************************
+ */
+
+/** @addtogroup CMSIS
+ * @{
+ */
+
+/** @addtogroup stm32f4xx_system
+ * @{
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Includes
+ * @{
+ */
+
+#include "stm32f4xx_hal.h"
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Defines
+ * @{
+ */
+
+/************************* Miscellaneous Configuration ************************/
+
+/*!< Uncomment the following line if you need to relocate your vector Table in
+ Internal SRAM. */
+/* #define VECT_TAB_SRAM */
+#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
+ This value must be a multiple of 0x200. */
+/******************************************************************************/
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Variables
+ * @{
+ */
+ /* This variable is updated in three ways:
+ 1) by calling CMSIS function SystemCoreClockUpdate()
+ 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
+ 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+ Note: If you use this function to configure the system clock; then there
+ is no need to call the 2 first functions listed above, since SystemCoreClock
+ variable is updated automatically.
+ */
+ uint32_t SystemCoreClock = 16000000;
+ __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/** @addtogroup STM32F4xx_System_Private_Functions
+ * @{
+ */
+
+/**
+ * @brief Setup the microcontroller system
+ * Initialize the FPU setting, vector table location and External memory
+ * configuration.
+ * @param None
+ * @retval None
+ */
+void SystemInit(void)
+{
+ /* FPU settings ------------------------------------------------------------*/
+ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
+ #endif
+ /* Reset the RCC clock configuration to the default reset state ------------*/
+ /* Set HSION bit */
+ RCC->CR |= (uint32_t)0x00000001;
+
+ /* Reset CFGR register */
+ RCC->CFGR = 0x00000000;
+
+ /* Reset HSEON, CSSON and PLLON bits */
+ RCC->CR &= (uint32_t)0xFEF6FFFF;
+
+ /* Reset PLLCFGR register */
+ RCC->PLLCFGR = 0x24003010;
+
+ /* Reset HSEBYP bit */
+ RCC->CR &= (uint32_t)0xFFFBFFFF;
+
+ /* Disable all interrupts */
+ RCC->CIR = 0x00000000;
+
+ /* Configure the Vector Table location add offset address ------------------*/
+#ifdef VECT_TAB_SRAM
+ SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+#else
+ SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
+#endif
+}
+
+/**
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
+ * The SystemCoreClock variable contains the core clock (HCLK), it can
+ * be used by the user application to setup the SysTick timer or configure
+ * other parameters.
+ *
+ * @note Each time the core clock (HCLK) changes, this function must be called
+ * to update SystemCoreClock variable value. Otherwise, any configuration
+ * based on this variable will be incorrect.
+ *
+ * @note - The system frequency computed by this function is not the real
+ * frequency in the chip. It is calculated based on the predefined
+ * constant and the selected clock source:
+ *
+ * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
+ *
+ * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
+ *
+ * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.
+ *
+ * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
+ * 16 MHz) but the real value may vary depending on the variations
+ * in voltage and temperature.
+ *
+ * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
+ * depends on the application requirements), user has to ensure that HSE_VALUE
+ * is same as the real frequency of the crystal used. Otherwise, this function
+ * may have wrong result.
+ *
+ * - The result of this function could be not correct when using fractional
+ * value for HSE crystal.
+ *
+ * @param None
+ * @retval None
+ */
+void SystemCoreClockUpdate(void)
+{
+ uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
+
+ /* Get SYSCLK source -------------------------------------------------------*/
+ tmp = RCC->CFGR & RCC_CFGR_SWS;
+
+ switch (tmp)
+ {
+ case 0x00: /* HSI used as system clock source */
+ SystemCoreClock = HSI_VALUE;
+ break;
+ case 0x04: /* HSE used as system clock source */
+ SystemCoreClock = HSE_VALUE;
+ break;
+ case 0x08: /* PLL used as system clock source */
+
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
+ SYSCLK = PLL_VCO / PLL_P
+ */
+ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+ pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
+
+ if (pllsource != 0)
+ {
+ /* HSE used as PLL clock source */
+ pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+ }
+ else
+ {
+ /* HSI used as PLL clock source */
+ pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
+ }
+
+ pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
+ SystemCoreClock = pllvco/pllp;
+ break;
+ default:
+ SystemCoreClock = HSI_VALUE;
+ break;
+ }
+ /* Compute HCLK frequency --------------------------------------------------*/
+ /* Get HCLK prescaler */
+ tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
+ /* HCLK frequency */
+ SystemCoreClock >>= tmp;
+}
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/