Pokud programujete mikrokontroléry od firmy STM (STM32F4, STM32F0, STM32L1) pomocí Standard Pheripheral Library, tak se vám možná nelíbí velikost výsledného kódu. Ovšem pokud budete přímo nastavovat registry, mohou se vám objevit různé problémy a hledání příčiny už není tak triviální. Dnes vám popíšu, jak se programuje USART na mikrokontroléru STM32L100, ale protože jde o základní periferii, portování na jiný mikrokontrolér nebude nijak složité.
Článek byl inspirován stránkou joudove.8u.cz.
Jak vypadá základní rámec protokolu UART, si můžete najít kdekoliv. Popisování jednotlivých bitů registrů také nebudu vyjmenovávat (a překládat), protože jako programátoři byste měli minimálně anglickému datasheetu rozumět. Jenom upozorním, na „záludné“ registry, kde jsem dělal (nebo i vy) chyby.
//—PIN pro USART1—//
RCC->AHBENR |= RCC_AHBENR_GPIOAEN; //povoleni clocku pro GPIOA
RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST; //reset GPIOA
RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOARST;
GPIOA->MODER |= (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); //alternativni fuknce PIN 9 a 10
GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR9_1 | GPIO_OSPEEDER_OSPEEDR10_1); //rychlost 50MHz
GPIOA->AFR[1] |= 0x00000770; //nastaveni alternativnich funkci
První moje chyba byla:
GPIOA->MODER = (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); //alternativni fuknce PIN 9 a 10
tedy chybějící znak |
To znamená, že přímo nastavujete tyto piny. Smůla ovšem je, že na stejném portu se nachází programovací rozhraní SWD.
Vývojové prostředí Keil vám oznámí po nahrání programu v terminálu:
Internal command error
A pokud chcete nahrát program, nahrávání skončí s hláškou: No target connected a poté Error: Flash Download failed – Target DLL has been cancelled
Pokud se podíváte do Flash -> Configure Flash Tools -> Debug -> Settings (u výběru programátoru) -> Vypíše hlášku v okně SW Device: No Cortex-M SW Device Found
V tomto okamžiku už s tím nic neuděláte a budete to muset opravit (o tom v textu níže).
Pokud nahráváte program pod vývojovým prostředím Atollic TrueStudio, ten vám vypíše chybu Remote failure reply: E31. Atollic se vás v terminálu zeptá, jestli chcete ten proces zabít. Zmáčknete „y“ – yes. Mikrokontrolér je dále viditelný a vy si musíte opravit chybu ve vašem kódu.
Ale jak to opravit v IDE Keil? Buď zapnete Atollic TrueStudio a naprogramujete to tam NEBO si stáhnete utilitu ST-LINK, tam zaškrtnete v Target -> Settings -> Mode: Connect Under Reset nebo poslední a nejsnazší varianta:
Opravíte si v IDE Keil váš kód, abyste nenastavovali celý PORT, tedy přidáte |, zkompilujete program, na Discovery desce zmáčknete tlačítko RESET a po malé chvíli (cca 0.5s) zmáčknete tlačíko „Load“ v Keil a potom pustíte tlačítko RESETu na desce. Poté se kód nahraje do mikrokontroléru.
Poznámka z komentářů: Popřípadě v nastavení programátoru zaškrtnete „Connect under reset“. Za komentář děkujeme.
Pokud jste program správně opravili, tak ve Flash -> Configure Flash Tools -> Debug -> Settings (u výběru programátoru) -> Vypíše hlášku v okně SW Device: se vám objeví váš mikrokontrolér.
Přejdeme k další chybě a to je nastavení registru AFR – tedy nastavení alternativních funkcí.
GPIOA->AFR[1] |= 0x00000770; //nastaveni alternativnich funkci
Podle níže zobrazeného obrázku vidíte, že USART1 se nachází na AF7, což znamená, že nastavení PINu pro alternativní funkci musíte nastavit na hodnotu 7.
Protože každý PIN může mít až 16 (0 – 15) alternativních funkcí, jsou každému PINu vyhrazeny 4 bity v 32 bit registru AFR. Registr AFR[0] je registr pro PINy 0 – 7 a AFR[1] je pro PINy 8 – 15.
A nakonec poslední problém byl správné nastavení BRR tedy Baud rate register. Registr se dělí na dvě části – 4 bity pro tzv. Fraction a 12 bitů pro tzv. Mantissu. Vzorec je jednoduchý a naleznete ho zde: http://joudove.8u.cz
Použijte naši kalkulačku na výpočet Baud Rate!
A nakonec celý kód pro USART – mikrokontrolér přijme znak a pošle ho zpátky.
MAIN.C
/* Includes */
#include
#include „stm32l1xx.h“
#include „stm32l1xx_conf.h“
/**
**===========================================================================
** http://chiptron.cz
** Abstract: main program
** APB2 bezi na 16MHz !!!
**
**===========================================================================
*/
int main(void)
{
//—-LED—-//
RCC->AHBENR |= RCC_AHBENR_GPIOCEN; //Povoleni clocku pro port C
RCC->AHBRSTR |= RCC_AHBRSTR_GPIOCRST; //reset GPIOC
RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOCRST;
GPIOC->MODER |= GPIO_MODER_MODER9_0 | GPIO_MODER_MODER8_0; //Nastaveni pinu 9 a 8 na portu C
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR8; // Nastaveni rychlosti pro port C PIN 9 a PIN 8
GPIOC->ODR = GPIO_ODR_ODR_9 | GPIO_ODR_ODR_8; //Zapis do vystupniho registru portu E PIN 9 a PIN 8
//—PIN pro USART1—//
RCC->AHBENR |= RCC_AHBENR_GPIOAEN; //povoleni clocku pro GPIOA
RCC->AHBRSTR |= RCC_AHBRSTR_GPIOARST; //reset GPIOA
RCC->AHBRSTR &= ~RCC_AHBRSTR_GPIOARST;
GPIOA->MODER |= (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); //alternativni fuknce PIN 9 a 10
GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR9_1 | GPIO_OSPEEDER_OSPEEDR10_1); //rychlost 50MHz
GPIOA->AFR[1] |= 0x00000770; //nastaveni alternativnich funkci
//—USART1—//
RCC->APB2ENR |= (RCC_APB2ENR_USART1EN); //povoleni clocku USART1
RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST; //reset USART1
RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;
USART1->CR1 = (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE); //povoleni USART1, prijem, vysilani
USART1->CR2 = 0x0000;
USART1->CR3 = 0x0000;
USART1->BRR = 0x682; //APB2 bezi na 16MHz!!! mantisa – 104dec, fraction 2.56dec
GPIOC->ODR &= ~(GPIO_ODR_ODR_9 | GPIO_ODR_ODR_8);
while (1)
{
uint8_t znak;
if((USART1->SR & USART_SR_RXNE) && !(USART1->SR & (USART_SR_PE | USART_SR_FE | USART_SR_NE | USART_SR_ORE))) //pokud se nenahodi flagy
{
znak = USART1->DR; // do promene znak zapis z registru DR
GPIOC->ODR ^= GPIO_ODR_ODR_9; //neguj LED
while(!(USART1->SR & USART_SR_TXE)); //cekej dokud neni buffer prazdy
USART1->DR = znak; //odesli znak
}
}
}
a ještě system_stm32l1xx.c
/**
******************************************************************************
* @file system_stm32l1xx.c
* @author MCD Application Team
* @version V1.3.0
* @date 31-January-2014
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
* This file contains the system clock configuration for STM32L1xx Ultra
* Low Power devices, and is generated by the clock configuration
* tool „STM32L1xx_Clock_Configuration_V1.1.0.xls“.
*
* 1. This file provides two functions and one global variable to be called from
* user application:
* – SystemInit(): Setups the system clock (System clock source, PLL Multiplier
* and Divider factors, AHB/APBx prescalers and Flash settings),
* depending on the configuration made in the clock xls tool.
* This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the „startup_stm32l1xx_xx.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.
*
* 2. After each device reset the MSI (2.1 MHz Range) is used as system clock source.
* Then SystemInit() function is called, in „startup_stm32l1xx_xx.s“ file, to
* configure the system clock before to branch to main program.
*
* 3. If the system clock source selected by user fails to startup, the SystemInit()
* function will do nothing and MSI still used as system clock source. User can
* add some code to deal with this issue inside the SetSysClock() function.
*
* 4. The default value of HSE crystal is set to 8MHz, refer to „HSE_VALUE“ define
* in „stm32l1xx.h“ file. When HSE is used as system clock source, directly or
* through PLL, and you are using different crystal you have to adapt the HSE
* value to your own configuration.
*
* 5. This file configures the system clock as follows:
*=============================================================================
* System Clock Configuration
*=============================================================================
* System Clock source | PLL(HSE)
*—————————————————————————–
* SYSCLK | 32000000 Hz
*—————————————————————————–
* HCLK | 32000000 Hz
*—————————————————————————–
* AHB Prescaler | 1
*—————————————————————————–
* APB1 Prescaler | 1
*—————————————————————————–
* APB2 Prescaler | 1
*—————————————————————————–
* HSE Frequency | 8000000 Hz
*—————————————————————————–
* PLL DIV | 3
*—————————————————————————–
* PLL MUL | 12
*—————————————————————————–
* VDD | 3.3 V
*—————————————————————————–
* Vcore | 1.8 V (Range 1)
*—————————————————————————–
* Flash Latency | 1 WS
*—————————————————————————–
* SDIO clock (SDIOCLK) | 48000000 Hz
*—————————————————————————–
* Require 48MHz for USB clock | Disabled
*—————————————————————————–
*=============================================================================
******************************************************************************
* @attention
*
*
© COPYRIGHT 2014 STMicroelectronics
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the „License“);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an „AS IS“ BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32l1xx_system
* @{
*/
/** @addtogroup STM32L1xx_System_Private_Includes
* @{
*/
#include „stm32l1xx.h“
/**
* @}
*/
/** @addtogroup STM32L1xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32L1xx_System_Private_Defines
* @{
*/
/*!< Uncomment the following line if you need to use external SRAM mounted
on STM32L152D_EVAL board as data memory */
/* #define DATA_IN_ExtSRAM */
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/**
* @}
*/
/** @addtogroup STM32L1xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32L1xx_System_Private_Variables
* @{
*/
uint32_t SystemCoreClock = 32000000;
__I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/**
* @}
*/
/** @addtogroup STM32L1xx_System_Private_FunctionPrototypes
* @{
*/
static void SetSysClock(void);
#ifdef DATA_IN_ExtSRAM
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM */
/**
* @}
*/
/** @addtogroup STM32L1xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system.
* Initialize the Embedded Flash Interface, the PLL and update the
* SystemCoreClock variable.
* @param None
* @retval None
*/
void SystemInit (void)
{
/*!< Set MSION bit */
RCC->CR |= (uint32_t)0x00000100;
/*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
RCC->CFGR &= (uint32_t)0x88FFC00C;
/*!< Reset HSION, HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xEEFEFFFE;
/*!< Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
RCC->CFGR &= (uint32_t)0xFF02FFFF;
/*!< Disable all interrupts */
RCC->CIR = 0x00000000;
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
SetSysClock();
#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 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 MSI, SystemCoreClock will contain the MSI
* value as defined by the MSI range.
*
* – 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 stm32l1xx.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 stm32l1xx.h file (default value
* 8 MHz), 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, pllmul = 0, plldiv = 0, pllsource = 0, msirange = 0;
/* Get SYSCLK source ——————————————————-*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case 0x00: /* MSI used as system clock */
msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;
SystemCoreClock = (32768 * (1 << (msirange + 1)));
break;
case 0x04: /* HSI used as system clock */
SystemCoreClock = HSI_VALUE;
break;
case 0x08: /* HSE used as system clock */
SystemCoreClock = HSE_VALUE;
break;
case 0x0C: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ———————-*/
pllmul = RCC->CFGR & RCC_CFGR_PLLMUL;
plldiv = RCC->CFGR & RCC_CFGR_PLLDIV;
pllmul = PLLMulTable[(pllmul >> 18)];
plldiv = (plldiv >> 22) + 1;
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
if (pllsource == 0x00)
{
/* HSI oscillator clock selected as PLL clock entry */
SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv);
}
else
{
/* HSE selected as PLL clock entry */
SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv);
}
break;
default: /* MSI used as system clock */
msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;
SystemCoreClock = (32768 * (1 << (msirange + 1)));
break;
}
/* Compute HCLK clock frequency ——————————————–*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
/* HCLK clock frequency */
SystemCoreClock >>= tmp;
}
/**
* @brief Configures the System clock frequency, AHB/APBx prescalers and Flash
* settings.
* @note This function should be called only once the RCC clock configuration
* is reset to the default reset state (done in SystemInit() function).
* @param None
* @retval None
*/
static void SetSysClock(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration —————————*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable 64-bit access */
FLASH->ACR |= FLASH_ACR_ACC64;
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTEN;
/* Flash 1 wait state */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* Power enable */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
/* Select the Voltage Range 1 (1.8 V) */
PWR->CR = PWR_CR_VOS_0;
/* Wait Until the Voltage Regulator is ready */
while((PWR->CSR & PWR_CSR_VOSF) != RESET)
{
}
/* HCLK = SYSCLK /1*/
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK /1*/
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK /1*/
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
/* PLL configuration */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL |
RCC_CFGR_PLLDIV));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMUL12 | RCC_CFGR_PLLDIV3);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
}
else
{
/* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#ifdef DATA_IN_ExtSRAM
/**
* @brief Setup the external memory controller.
* Called in SystemInit() function before jump to main.
* This function configures the external SRAM mounted on STM32L152D_EVAL board
* This SRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
/*– GPIOs Configuration —————————————————–*/
/*
+——————-+——————–+——————+——————+
+ SRAM pins assignment +
+——————-+——————–+——————+——————+
| PD0 <-> FSMC_D2 | PE0 <-> FSMC_NBL0 | PF0 <-> FSMC_A0 | PG0 <-> FSMC_A10 |
| PD1 <-> FSMC_D3 | PE1 <-> FSMC_NBL1 | PF1 <-> FSMC_A1 | PG1 <-> FSMC_A11 |
| PD4 <-> FSMC_NOE | PE7 <-> FSMC_D4 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 |
| PD5 <-> FSMC_NWE | PE8 <-> FSMC_D5 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 |
| PD8 <-> FSMC_D13 | PE9 <-> FSMC_D6 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 |
| PD9 <-> FSMC_D14 | PE10 <-> FSMC_D7 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 |
| PD10 <-> FSMC_D15 | PE11 <-> FSMC_D8 | PF12 <-> FSMC_A6 | PG10<-> FSMC_NE2 |
| PD11 <-> FSMC_A16 | PE12 <-> FSMC_D9 | PF13 <-> FSMC_A7 |——————+
| PD12 <-> FSMC_A17 | PE13 <-> FSMC_D10 | PF14 <-> FSMC_A8 |
| PD13 <-> FSMC_A18 | PE14 <-> FSMC_D11 | PF15 <-> FSMC_A9 |
| PD14 <-> FSMC_D0 | PE15 <-> FSMC_D12 |——————+
| PD15 <-> FSMC_D1 |——————–+
+——————-+
*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHBENR = 0x000080D8;
/* Connect PDx pins to FSMC Alternate function */
GPIOD->AFR[0] = 0x00CC00CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A0A;
/* Configure PDx pins speed to 40 MHz */
GPIOD->OSPEEDR = 0xFFFF0F0F;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FSMC Alternate function */
GPIOE->AFR[0] = 0xC00000CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA800A;
/* Configure PEx pins speed to 40 MHz */
GPIOE->OSPEEDR = 0xFFFFC00F;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FSMC Alternate function */
GPIOF->AFR[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 40 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FSMC Alternate function */
GPIOG->AFR[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0x00000C00;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00200AAA;
/* Configure PGx pins speed to 40 MHz */
GPIOG->OSPEEDR = 0x00300FFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/*– FSMC Configuration ——————————————————*/
/* Enable the FSMC interface clock */
RCC->AHBENR = 0x400080D8;
/* Configure and enable Bank1_SRAM3 */
FSMC_Bank1->BTCR[4] = 0x00001011;
FSMC_Bank1->BTCR[5] = 0x00000300;
FSMC_Bank1E->BWTR[4] = 0x0FFFFFFF;
/*
Bank1_SRAM3 is configured as follow:
p.FSMC_AddressSetupTime = 0;
p.FSMC_AddressHoldTime = 0;
p.FSMC_DataSetupTime = 3;
p.FSMC_BusTurnAroundDuration = 0;
p.FSMC_CLKDivision = 0;
p.FSMC_DataLatency = 0;
p.FSMC_AccessMode = FSMC_AccessMode_A;
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
*/
}
#endif /* DATA_IN_ExtSRAM */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/