--- /dev/null
+/**
+ * |----------------------------------------------------------------------
+ * | Copyright (C) Tilen Majerle, 2015
+ * |
+ * | This program is free software: you can redistribute it and/or modify
+ * | it under the terms of the GNU General Public License as published by
+ * | the Free Software Foundation, either version 3 of the License, or
+ * | any later version.
+ * |
+ * | This program is distributed in the hope that it will be useful,
+ * | but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * | GNU General Public License for more details.
+ * |
+ * | You should have received a copy of the GNU General Public License
+ * | along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * |----------------------------------------------------------------------
+ */
+#include "tm_stm32f4_gpio.h"
+
+/* Private function */
+static uint16_t GPIO_UsedPins[11] = {0,0,0,0,0,0,0,0,0,0,0};
+
+/* Private functions */
+void TM_GPIO_INT_EnableClock(GPIO_TypeDef* GPIOx);
+void TM_GPIO_INT_DisableClock(GPIO_TypeDef* GPIOx);
+void TM_GPIO_INT_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TM_GPIO_Mode_t GPIO_Mode, TM_GPIO_OType_t GPIO_OType, TM_GPIO_PuPd_t GPIO_PuPd, TM_GPIO_Speed_t GPIO_Speed);
+
+void TM_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TM_GPIO_Mode_t GPIO_Mode, TM_GPIO_OType_t GPIO_OType, TM_GPIO_PuPd_t GPIO_PuPd, TM_GPIO_Speed_t GPIO_Speed) {
+ /* Check input */
+ if (GPIO_Pin == 0x00) {
+ return;
+ }
+
+ /* Enable clock for GPIO */
+ TM_GPIO_INT_EnableClock(GPIOx);
+
+ /* Do initialization */
+ TM_GPIO_INT_Init(GPIOx, GPIO_Pin, GPIO_Mode, GPIO_OType, GPIO_PuPd, GPIO_Speed);
+}
+
+void TM_GPIO_InitAlternate(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TM_GPIO_OType_t GPIO_OType, TM_GPIO_PuPd_t GPIO_PuPd, TM_GPIO_Speed_t GPIO_Speed, uint8_t Alternate) {
+ uint32_t pinpos;
+
+ /* Check input */
+ if (GPIO_Pin == 0x00) {
+ return;
+ }
+
+ /* Enable GPIOx clock */
+ TM_GPIO_INT_EnableClock(GPIOx);
+
+ /* Set alternate functions for all pins */
+ for (pinpos = 0; pinpos < 0x10; pinpos++) {
+ /* Check pin */
+ if ((GPIO_Pin & (1 << pinpos)) == 0) {
+ continue;
+ }
+
+ /* Set alternate function */
+ GPIOx->AFR[pinpos >> 0x03] = (GPIOx->AFR[pinpos >> 0x03] & ~(0x0F << (4 * (pinpos & 0x07)))) | (Alternate << (4 * (pinpos & 0x07)));
+ }
+
+ /* Do initialization */
+ TM_GPIO_INT_Init(GPIOx, GPIO_Pin, TM_GPIO_Mode_AF, GPIO_OType, GPIO_PuPd, GPIO_Speed);
+}
+
+void TM_GPIO_DeInit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
+ uint8_t i;
+ uint8_t ptr = TM_GPIO_GetPortSource(GPIOx);
+
+ /* Go through all pins */
+ for (i = 0x00; i < 0x10; i++) {
+ /* Pin is set */
+ if (GPIO_Pin & (1 << i)) {
+ /* Set 11 bits combination for analog mode */
+ GPIOx->MODER |= (0x03 << (2 * i));
+
+ /* Pin is not used */
+ GPIO_UsedPins[ptr] &= ~(1 << i);
+ }
+ }
+}
+
+void TM_GPIO_SetPinAsInput(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
+ uint8_t i;
+ /* Go through all pins */
+ for (i = 0x00; i < 0x10; i++) {
+ /* Pin is set */
+ if (GPIO_Pin & (1 << i)) {
+ /* Set 00 bits combination for input */
+ GPIOx->MODER &= ~(0x03 << (2 * i));
+ }
+ }
+}
+
+void TM_GPIO_SetPinAsOutput(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
+ uint8_t i;
+ /* Go through all pins */
+ for (i = 0x00; i < 0x10; i++) {
+ /* Pin is set */
+ if (GPIO_Pin & (1 << i)) {
+ /* Set 01 bits combination for output */
+ GPIOx->MODER = (GPIOx->MODER & ~(0x03 << (2 * i))) | (0x01 << (2 * i));
+ }
+ }
+}
+
+void TM_GPIO_SetPinAsAnalog(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
+ uint8_t i;
+ /* Go through all pins */
+ for (i = 0x00; i < 0x10; i++) {
+ /* Pin is set */
+ if (GPIO_Pin & (1 << i)) {
+ /* Set 11 bits combination for analog mode */
+ GPIOx->MODER |= (0x03 << (2 * i));
+ }
+ }
+}
+
+void TM_GPIO_SetPinAsAlternate(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
+ uint8_t i;
+
+ /* Set alternate functions for all pins */
+ for (i = 0; i < 0x10; i++) {
+ /* Check pin */
+ if ((GPIO_Pin & (1 << i)) == 0) {
+ continue;
+ }
+
+ /* Set alternate mode */
+ GPIOx->MODER = (GPIOx->MODER & ~(0x03 << (2 * i))) | (0x02 << (2 * i));
+ }
+}
+
+void TM_GPIO_SetPullResistor(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TM_GPIO_PuPd_t GPIO_PuPd) {
+ uint8_t pinpos;
+
+ /* Go through all pins */
+ for (pinpos = 0; pinpos < 0x10; pinpos++) {
+ /* Check if pin available */
+ if ((GPIO_Pin & (1 << pinpos)) == 0) {
+ continue;
+ }
+
+ /* Set GPIO PUPD register */
+ GPIOx->PUPDR = (GPIOx->PUPDR & ~(0x03 << (2 * pinpos))) | ((uint32_t)(GPIO_PuPd << (2 * pinpos)));
+ }
+}
+
+void TM_GPIO_Lock(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
+ uint32_t d;
+
+ /* Set GPIO pin with 16th bit set to 1 */
+ d = 0x00010000 | GPIO_Pin;
+
+ /* Write to LCKR register */
+ GPIOx->LCKR = d;
+ GPIOx->LCKR = GPIO_Pin;
+ GPIOx->LCKR = d;
+
+ /* Read twice */
+ (void)GPIOx->LCKR;
+ (void)GPIOx->LCKR;
+}
+
+uint16_t TM_GPIO_GetPinSource(uint16_t GPIO_Pin) {
+ uint16_t pinsource = 0;
+
+ /* Get pinsource */
+ while (GPIO_Pin > 1) {
+ /* Increase pinsource */
+ pinsource++;
+ /* Shift right */
+ GPIO_Pin >>= 1;
+ }
+
+ /* Return source */
+ return pinsource;
+}
+
+uint16_t TM_GPIO_GetPortSource(GPIO_TypeDef* GPIOx) {
+ /* Get port source number */
+ /* Offset from GPIOA Difference between 2 GPIO addresses */
+ return ((uint32_t)GPIOx - (GPIOA_BASE)) / ((GPIOB_BASE) - (GPIOA_BASE));
+}
+
+/* Private functions */
+void TM_GPIO_INT_EnableClock(GPIO_TypeDef* GPIOx) {
+ /* Set bit according to the 1 << portsourcenumber */
+ RCC->AHB1ENR |= (1 << TM_GPIO_GetPortSource(GPIOx));
+}
+
+void TM_GPIO_INT_DisableClock(GPIO_TypeDef* GPIOx) {
+ /* Clear bit according to the 1 << portsourcenumber */
+ RCC->AHB1ENR &= ~(1 << TM_GPIO_GetPortSource(GPIOx));
+}
+
+void TM_GPIO_INT_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, TM_GPIO_Mode_t GPIO_Mode, TM_GPIO_OType_t GPIO_OType, TM_GPIO_PuPd_t GPIO_PuPd, TM_GPIO_Speed_t GPIO_Speed) {
+ uint8_t pinpos;
+ uint8_t ptr = TM_GPIO_GetPortSource(GPIOx);
+
+ /* Go through all pins */
+ for (pinpos = 0; pinpos < 0x10; pinpos++) {
+ /* Check if pin available */
+ if ((GPIO_Pin & (1 << pinpos)) == 0) {
+ continue;
+ }
+
+ /* Pin is used */
+ GPIO_UsedPins[ptr] |= 1 << pinpos;
+
+ /* Set GPIO PUPD register */
+ GPIOx->PUPDR = (GPIOx->PUPDR & ~(0x03 << (2 * pinpos))) | ((uint32_t)(GPIO_PuPd << (2 * pinpos)));
+
+ /* Set GPIO MODE register */
+ GPIOx->MODER = (GPIOx->MODER & ~((uint32_t)(0x03 << (2 * pinpos)))) | ((uint32_t)(GPIO_Mode << (2 * pinpos)));
+
+ /* Set only if output or alternate functions */
+ if (GPIO_Mode == TM_GPIO_Mode_OUT || GPIO_Mode == TM_GPIO_Mode_AF) {
+ /* Set GPIO OTYPE register */
+ GPIOx->OTYPER = (GPIOx->OTYPER & ~(uint16_t)(0x01 << pinpos)) | ((uint16_t)(GPIO_OType << pinpos));
+
+ /* Set GPIO OSPEED register */
+ GPIOx->OSPEEDR = (GPIOx->OSPEEDR & ~((uint32_t)(0x03 << (2 * pinpos)))) | ((uint32_t)(GPIO_Speed << (2 * pinpos)));
+ }
+ }
+}
+
+uint16_t TM_GPIO_GetUsedPins(GPIO_TypeDef* GPIOx) {
+ /* Return used */
+ return GPIO_UsedPins[TM_GPIO_GetPortSource(GPIOx)];
+}
+
+uint16_t TM_GPIO_GetFreePins(GPIO_TypeDef* GPIOx) {
+ /* Return free pins */
+ return ~GPIO_UsedPins[TM_GPIO_GetPortSource(GPIOx)];
+}
--- /dev/null
+/** \r
+ * |----------------------------------------------------------------------\r
+ * | Copyright (C) Tilen Majerle, 2014\r
+ * | \r
+ * | This program is free software: you can redistribute it and/or modify\r
+ * | it under the terms of the GNU General Public License as published by\r
+ * | the Free Software Foundation, either version 3 of the License, or\r
+ * | any later version.\r
+ * | \r
+ * | This program is distributed in the hope that it will be useful,\r
+ * | but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * | GNU General Public License for more details.\r
+ * | \r
+ * | You should have received a copy of the GNU General Public License\r
+ * | along with this program. If not, see <http://www.gnu.org/licenses/>.\r
+ * |----------------------------------------------------------------------\r
+ */\r
+#include "tm_stm32f4_mco_output.h"\r
+\r
+void TM_MCOOUTPUT_InitMCO1(void) {\r
+ /* Enable PA8 */\r
+ TM_GPIO_Init(GPIOA, GPIO_PIN_8, TM_GPIO_Mode_AF, TM_GPIO_OType_PP, TM_GPIO_PuPd_NOPULL, TM_GPIO_Speed_High);\r
+}\r
+\r
+void TM_MCOOUTPUT_InitMCO2(void) {\r
+ /* Enable PC9 */\r
+ TM_GPIO_Init(GPIOC, GPIO_PIN_9, TM_GPIO_Mode_AF, TM_GPIO_OType_PP, TM_GPIO_PuPd_NOPULL, TM_GPIO_Speed_High);\r
+}\r
+\r
+void TM_MCOOUTPUT_SetOutput1(TM_MCOOUTPUT1_Source_t Source, TM_MCOOUTPUT_Prescaler_t Prescaler) {\r
+ uint32_t presc = 0, src = 0;\r
+ \r
+ /* Get prescaler */\r
+ switch (Prescaler) {\r
+ case TM_MCOOUTPUT_Prescaler_1:\r
+ presc = RCC_MCO1Div_1;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_2:\r
+ presc = RCC_MCO1Div_2;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_3:\r
+ presc = RCC_MCO1Div_3;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_4:\r
+ presc = RCC_MCO1Div_4;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_5:\r
+ presc = RCC_MCO1Div_5;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ \r
+ /* Get source */\r
+ switch (Source) {\r
+ case TM_MCOOUTPUT1_Source_HSE:\r
+ src = RCC_MCO1Source_HSE;\r
+ \r
+ /* Enable RCC HSE oscillator */\r
+ RCC_HSEConfig(RCC_HSE_ON);\r
+ break;\r
+ case TM_MCOOUTPUT1_Source_HSI:\r
+ src = RCC_MCO1Source_HSI;\r
+ break;\r
+ case TM_MCOOUTPUT1_Source_PLLCLK:\r
+ src = RCC_MCO1Source_PLLCLK;\r
+ break;\r
+ case TM_MCOOUTPUT1_Source_LSE: \r
+ src = RCC_MCO1Source_LSE;\r
+ \r
+ /* Start LSE clock if available */\r
+ RCC_LSEConfig(RCC_LSE_ON);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ \r
+ \r
+ /* Set source and prescaler */\r
+ RCC_MCO1Config(src, presc);\r
+}\r
+\r
+void TM_MCOOUTPUT_SetOutput2(TM_MCOOUTPUT2_Source_t Source, TM_MCOOUTPUT_Prescaler_t Prescaler) {\r
+ uint32_t presc, src;\r
+ \r
+ /* Get prescaler */\r
+ switch (Prescaler) {\r
+ case TM_MCOOUTPUT_Prescaler_1:\r
+ presc = RCC_MCO2Div_1;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_2:\r
+ presc = RCC_MCO2Div_2;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_3:\r
+ presc = RCC_MCO2Div_3;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_4:\r
+ presc = RCC_MCO2Div_4;\r
+ break;\r
+ case TM_MCOOUTPUT_Prescaler_5:\r
+ presc = RCC_MCO2Div_5;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ \r
+ /* Get clock source */\r
+ switch (Source) {\r
+ case TM_MCOOUTPUT2_Source_SYSCLK:\r
+ src = RCC_MCO2Source_SYSCLK;\r
+ break;\r
+ case TM_MCOOUTPUT2_Source_PLLI2SCLK:\r
+ src = RCC_MCO2Source_PLLI2SCLK;\r
+ break;\r
+ case TM_MCOOUTPUT2_Source_HSE:\r
+ src = RCC_MCO2Source_HSE;\r
+ break;\r
+ case TM_MCOOUTPUT2_Source_PLLCLK:\r
+ src = RCC_MCO2Source_PLLCLK;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ \r
+ /* Set source and prescaler */\r
+ RCC_MCO2Config(src, presc);\r
+}\r