From 43974f34adadb0b8af908e364681fb3025df3e7e Mon Sep 17 00:00:00 2001 From: jnosky Date: Thu, 10 Nov 2011 20:09:20 -0500 Subject: [PATCH] Added the IO_Toggle and discovery demo samples including a working make Can now build and flash these these samples --- exampleF4/Projects/IO_Toggle/Makefile | 31 + exampleF4/Projects/IO_Toggle/main.c | 143 ++ exampleF4/Projects/IO_Toggle/readme.txt | 91 + .../Projects/IO_Toggle/startup_stm32f4xx.s | 509 ++++ exampleF4/Projects/IO_Toggle/stm32_flash.ld | 170 ++ .../Projects/IO_Toggle/stm32f4_discovery.h | 158 ++ exampleF4/Projects/IO_Toggle/stm32f4xx_conf.h | 94 + exampleF4/Projects/IO_Toggle/stm32f4xx_it.c | 167 ++ exampleF4/Projects/IO_Toggle/stm32f4xx_it.h | 54 + .../Projects/IO_Toggle/system_stm32f4xx.c | 545 ++++ exampleF4/Projects/discovery_demo/Makefile | 61 + .../discovery_demo/Release_Notes.html | 151 ++ .../discovery_demo/STM32F4-Discovery_Demo.bin | Bin 0 -> 31620 bytes .../discovery_demo/STM32F4-Discovery_Demo.elf | Bin 0 -> 243586 bytes exampleF4/Projects/discovery_demo/main.c | 509 ++++ exampleF4/Projects/discovery_demo/main.h | 62 + exampleF4/Projects/discovery_demo/selftest.c | 808 ++++++ exampleF4/Projects/discovery_demo/selftest.h | 41 + .../discovery_demo/startup_stm32f4xx.s | 509 ++++ .../Projects/discovery_demo/stm32_flash.ld | 170 ++ .../Projects/discovery_demo/stm32f4xx_conf.h | 94 + .../Projects/discovery_demo/stm32f4xx_it.c | 320 +++ .../Projects/discovery_demo/stm32f4xx_it.h | 54 + .../discovery_demo/system_stm32f4xx.c | 566 +++++ exampleF4/Projects/discovery_demo/usb_bsp.c | 382 +++ exampleF4/Projects/discovery_demo/usb_conf.h | 252 ++ exampleF4/Projects/discovery_demo/usb_core.c | 2187 +++++++++++++++++ exampleF4/Projects/discovery_demo/usb_core.h | 408 +++ exampleF4/Projects/discovery_demo/usbd_conf.h | 93 + exampleF4/Projects/discovery_demo/usbd_desc.c | 313 +++ exampleF4/Projects/discovery_demo/usbd_desc.h | 114 + exampleF4/Projects/discovery_demo/usbd_usr.c | 238 ++ 32 files changed, 9294 insertions(+) create mode 100644 exampleF4/Projects/IO_Toggle/Makefile create mode 100644 exampleF4/Projects/IO_Toggle/main.c create mode 100644 exampleF4/Projects/IO_Toggle/readme.txt create mode 100644 exampleF4/Projects/IO_Toggle/startup_stm32f4xx.s create mode 100644 exampleF4/Projects/IO_Toggle/stm32_flash.ld create mode 100644 exampleF4/Projects/IO_Toggle/stm32f4_discovery.h create mode 100644 exampleF4/Projects/IO_Toggle/stm32f4xx_conf.h create mode 100644 exampleF4/Projects/IO_Toggle/stm32f4xx_it.c create mode 100644 exampleF4/Projects/IO_Toggle/stm32f4xx_it.h create mode 100644 exampleF4/Projects/IO_Toggle/system_stm32f4xx.c create mode 100644 exampleF4/Projects/discovery_demo/Makefile create mode 100644 exampleF4/Projects/discovery_demo/Release_Notes.html create mode 100644 exampleF4/Projects/discovery_demo/STM32F4-Discovery_Demo.bin create mode 100644 exampleF4/Projects/discovery_demo/STM32F4-Discovery_Demo.elf create mode 100644 exampleF4/Projects/discovery_demo/main.c create mode 100644 exampleF4/Projects/discovery_demo/main.h create mode 100644 exampleF4/Projects/discovery_demo/selftest.c create mode 100644 exampleF4/Projects/discovery_demo/selftest.h create mode 100644 exampleF4/Projects/discovery_demo/startup_stm32f4xx.s create mode 100644 exampleF4/Projects/discovery_demo/stm32_flash.ld create mode 100644 exampleF4/Projects/discovery_demo/stm32f4xx_conf.h create mode 100644 exampleF4/Projects/discovery_demo/stm32f4xx_it.c create mode 100644 exampleF4/Projects/discovery_demo/stm32f4xx_it.h create mode 100644 exampleF4/Projects/discovery_demo/system_stm32f4xx.c create mode 100644 exampleF4/Projects/discovery_demo/usb_bsp.c create mode 100644 exampleF4/Projects/discovery_demo/usb_conf.h create mode 100644 exampleF4/Projects/discovery_demo/usb_core.c create mode 100644 exampleF4/Projects/discovery_demo/usb_core.h create mode 100644 exampleF4/Projects/discovery_demo/usbd_conf.h create mode 100644 exampleF4/Projects/discovery_demo/usbd_desc.c create mode 100644 exampleF4/Projects/discovery_demo/usbd_desc.h create mode 100644 exampleF4/Projects/discovery_demo/usbd_usr.c diff --git a/exampleF4/Projects/IO_Toggle/Makefile b/exampleF4/Projects/IO_Toggle/Makefile new file mode 100644 index 0000000..ef8860a --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/Makefile @@ -0,0 +1,31 @@ +EXECUTABLE=IO_Toggle.elf +BIN_IMAGE=IO_Toggle.bin + +CC=arm-none-eabi-gcc +OBJCOPY=arm-none-eabi-objcopy + +CFLAGS=-g -O2 -mlittle-endian -mthumb +CFLAGS+=-mcpu=cortex-m4 +CFLAGS+=-ffreestanding -nostdlib + +# to run from FLASH +CFLAGS+=-Wl,-T,stm32_flash.ld + +# stm32f4_discovery lib +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc/device_support +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc/core_support + +all: $(BIN_IMAGE) + +$(BIN_IMAGE): $(EXECUTABLE) + $(OBJCOPY) -O binary $^ $@ + +$(EXECUTABLE): main.c system_stm32f4xx.c startup_stm32f4xx.s stm32f4xx_it.c + $(CC) $(CFLAGS) $^ -o $@ -L../../STM32F4xx_StdPeriph_Driver/build -lSTM32F4xx_StdPeriph_Driver + +clean: + rm -rf $(EXECUTABLE) + rm -rf $(BIN_IMAGE) + +.PHONY: all clean diff --git a/exampleF4/Projects/IO_Toggle/main.c b/exampleF4/Projects/IO_Toggle/main.c new file mode 100644 index 0000000..5da875f --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/main.c @@ -0,0 +1,143 @@ +/** + ****************************************************************************** + * @file IO_Toggle/main.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Main program body + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4_discovery.h" +#include "stm32f4xx_conf.h" + +/** @addtogroup STM32F4_Discovery_Peripheral_Examples + * @{ + */ + +/** @addtogroup IO_Toggle + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +GPIO_InitTypeDef GPIO_InitStructure; + +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +void Delay(__IO uint32_t nCount); +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Main program + * @param None + * @retval None + */ +int main(void) +{ + /*!< At this stage the microcontroller clock setting is already configured, + this is done through SystemInit() function which is called from startup + file (startup_stm32f4xx.s) before to branch to application main. + To reconfigure the default setting of SystemInit() function, refer to + system_stm32f4xx.c file + */ + + /* GPIOD Periph clock enable */ + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + + /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOD, &GPIO_InitStructure); + + while (1) + { + /* PD12 to be toggled */ + GPIO_SetBits(GPIOD, GPIO_Pin_12); + + /* Insert delay */ + Delay(0x3FFFFF); + + /* PD13 to be toggled */ + GPIO_SetBits(GPIOD, GPIO_Pin_13); + + /* Insert delay */ + Delay(0x3FFFFF); + + /* PD14 to be toggled */ + GPIO_SetBits(GPIOD, GPIO_Pin_14); + + /* Insert delay */ + Delay(0x3FFFFF); + + /* PD15 to be toggled */ + GPIO_SetBits(GPIOD, GPIO_Pin_15); + + /* Insert delay */ + Delay(0x7FFFFF); + + GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); + + /* Insert delay */ + Delay(0xFFFFFF); + } +} + +/** + * @brief Delay Function. + * @param nCount:specifies the Delay time length. + * @retval None + */ +void Delay(__IO uint32_t nCount) +{ + while(nCount--) + { + } +} + +#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 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/IO_Toggle/readme.txt b/exampleF4/Projects/IO_Toggle/readme.txt new file mode 100644 index 0000000..fda5b2e --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/readme.txt @@ -0,0 +1,91 @@ +/** + @page GPIO_IOToggle GPIO IO Toggle example + + @verbatim + ******************** (C) COPYRIGHT 2011 STMicroelectronics ******************* + * @file IO_Toggle/readme.txt + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Description of the GPIO IO Toggle example. + ****************************************************************************** + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + ****************************************************************************** + @endverbatim + +@par Example Description + +This example describes how to toggle the GPIO pins connected on AHB bus. + +PD12, PD13, PD14 and PD15 (configured in output pushpull mode) toggles in a forever loop. + - Set PD12, PD13, PD14 and PD15 by setting corresponding bits in BSRRL register + - Reset PD12, PD13, PD14 and PD15 by setting corresponding bits in BSRRH register + +In this example, HCLK is configured at 168 MHz. + +@par Directory contents + + - IO_Toggle/stm32f4xx_conf.h Library Configuration file + - IO_Toggle/stm32f4xx_it.c Interrupt handlers + - IO_Toggle/stm32f4xx_it.h Interrupt handlers header file + - IO_Toggle/main.c Main program + - IO_Toggle/system_stm32f4xx.c STM32F4xx system source file + +@par Hardware and Software environment + + - This example runs on STM32F4xx Devices Revision A. + + - This example has been tested with STM32F4-Discovery (MB997) RevA and can be + easily tailored to any other development board + + - STM32F4-Discovery + - LED4, LED3, LED5 and LED6 are connected respectively to PD.12, PD.13, PD.14 and PD.15. + + +@par How to use it ? + +In order to make the program work, you must do the following : + + + EWARM + - Open the IO_Toggle.eww workspace + - Rebuild all files: Project->Rebuild all + - Load project image: Project->Debug + - Run program: Debug->Go(F5) + + + MDK-ARM + - Open the IO_Toggle.uvproj project + - Rebuild all files: Project->Rebuild all target files + - Load project image: Debug->Start/Stop Debug Session + - Run program: Debug->Run (F5) + + + TASKING + - Open TASKING toolchain. + - Click on File->Import, select General->'Existing Projects into Workspace' + and then click "Next". + - Browse to TASKING workspace directory and select the project "IO_Toggle" + - Rebuild all project files: Select the project in the "Project explorer" + window then click on Project->build project menu. + - Run program: Select the project in the "Project explorer" window then click + Run->Debug (F11) + + + TrueSTUDIO + - Open the TrueSTUDIO toolchain. + - Click on File->Switch Workspace->Other and browse to TrueSTUDIO workspace + directory. + - Click on File->Import, select General->'Existing Projects into Workspace' + and then click "Next". + - Browse to the TrueSTUDIO workspace directory and select the project "IO_Toggle" + - Rebuild all project files: Select the project in the "Project explorer" + window then click on Project->build project menu. + - Run program: Select the project in the "Project explorer" window then click + Run->Debug (F11) + + + + *

© COPYRIGHT 2011 STMicroelectronics

+ */ diff --git a/exampleF4/Projects/IO_Toggle/startup_stm32f4xx.s b/exampleF4/Projects/IO_Toggle/startup_stm32f4xx.s new file mode 100644 index 0000000..ce5360f --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/startup_stm32f4xx.s @@ -0,0 +1,509 @@ +/** + ****************************************************************************** + * @file startup_stm32f4xx.s + * @author MCD Application Team + * @version V1.0.0 + * @date 30-September-2011 + * @brief STM32F4xx Devices vector table for RIDE7 toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Configure the clock system and the external SRAM mounted on + * STM324xG-EVAL board to be used as data memory (optional, + * to be enabled by user) + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FSMC_IRQHandler /* FSMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word CRYP_IRQHandler /* CRYP crypto */ + .word HASH_RNG_IRQHandler /* Hash and Rng */ + .word FPU_IRQHandler /* FPU */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak CRYP_IRQHandler + .thumb_set CRYP_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/IO_Toggle/stm32_flash.ld b/exampleF4/Projects/IO_Toggle/stm32_flash.ld new file mode 100644 index 0000000..1a0b4b8 --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/stm32_flash.ld @@ -0,0 +1,170 @@ +/* +***************************************************************************** +** +** File : stm32_flash.ld +** +** Abstract : Linker script for STM32F407VG Device with +** 1024KByte FLASH, 192KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Environment : Atollic TrueSTUDIO(R) +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +** (c)Copyright Atollic AB. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the Atollic TrueSTUDIO(R) toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of 128K RAM on AHB bus*/ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K + MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + /* MEMORY_bank1 section, code must be located here explicitly */ + /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ + .memory_b1_text : + { + *(.mb1text) /* .mb1text sections (code) */ + *(.mb1text*) /* .mb1text* sections (code) */ + *(.mb1rodata) /* read-only data (constants) */ + *(.mb1rodata*) + } >MEMORY_B1 + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/exampleF4/Projects/IO_Toggle/stm32f4_discovery.h b/exampleF4/Projects/IO_Toggle/stm32f4_discovery.h new file mode 100644 index 0000000..c6fec42 --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/stm32f4_discovery.h @@ -0,0 +1,158 @@ +/** + ****************************************************************************** + * @file stm32f4_discovery.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file contains definitions for STM32F4-Discovery Kit's Leds and + * push-button hardware resources. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4_DISCOVERY_H +#define __STM32F4_DISCOVERY_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + #include "stm32f4xx.h" + +/** @addtogroup Utilities + * @{ + */ + +/** @addtogroup STM32F4_DISCOVERY + * @{ + */ + +/** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL + * @{ + */ + +/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Types + * @{ + */ +typedef enum +{ + LED4 = 0, + LED3 = 1, + LED5 = 2, + LED6 = 3 +} Led_TypeDef; + +typedef enum +{ + BUTTON_USER = 0, +} Button_TypeDef; + +typedef enum +{ + BUTTON_MODE_GPIO = 0, + BUTTON_MODE_EXTI = 1 +} ButtonMode_TypeDef; +/** + * @} + */ + +/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Constants + * @{ + */ + +/** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_LED + * @{ + */ +#define LEDn 4 + +#define LED4_PIN GPIO_Pin_12 +#define LED4_GPIO_PORT GPIOD +#define LED4_GPIO_CLK RCC_AHB1Periph_GPIOD + +#define LED3_PIN GPIO_Pin_13 +#define LED3_GPIO_PORT GPIOD +#define LED3_GPIO_CLK RCC_AHB1Periph_GPIOD + +#define LED5_PIN GPIO_Pin_14 +#define LED5_GPIO_PORT GPIOD +#define LED5_GPIO_CLK RCC_AHB1Periph_GPIOD + +#define LED6_PIN GPIO_Pin_15 +#define LED6_GPIO_PORT GPIOD +#define LED6_GPIO_CLK RCC_AHB1Periph_GPIOD +/** + * @} + */ + +/** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_BUTTON + * @{ + */ +#define BUTTONn 1 + +/** + * @brief Wakeup push-button + */ +#define USER_BUTTON_PIN GPIO_Pin_0 +#define USER_BUTTON_GPIO_PORT GPIOA +#define USER_BUTTON_GPIO_CLK RCC_AHB1Periph_GPIOA +#define USER_BUTTON_EXTI_LINE EXTI_Line0 +#define USER_BUTTON_EXTI_PORT_SOURCE EXTI_PortSourceGPIOA +#define USER_BUTTON_EXTI_PIN_SOURCE EXTI_PinSource0 +#define USER_BUTTON_EXTI_IRQn EXTI0_IRQn +/** + * @} + */ + +/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Functions + * @{ + */ +void STM_EVAL_LEDInit(Led_TypeDef Led); +void STM_EVAL_LEDOn(Led_TypeDef Led); +void STM_EVAL_LEDOff(Led_TypeDef Led); +void STM_EVAL_LEDToggle(Led_TypeDef Led); +void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode); +uint32_t STM_EVAL_PBGetState(Button_TypeDef Button); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4_DISCOVERY_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/IO_Toggle/stm32f4xx_conf.h b/exampleF4/Projects/IO_Toggle/stm32f4xx_conf.h new file mode 100644 index 0000000..abd159f --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/stm32f4xx_conf.h @@ -0,0 +1,94 @@ +/** + ****************************************************************************** + * @file IO_Toggle/stm32f4xx_conf.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Library configuration file. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_CONF_H +#define __STM32F4xx_CONF_H + +#if defined (HSE_VALUE) +/* Redefine the HSE value; it's equal to 8 MHz on the STM32F4-DISCOVERY Kit */ + #undef HSE_VALUE + #define HSE_VALUE ((uint32_t)8000000) +#endif /* HSE_VALUE */ + +/* Includes ------------------------------------------------------------------*/ +/* Uncomment the line below to enable peripheral header file inclusion */ +#include "stm32f4xx_adc.h" +#include "stm32f4xx_can.h" +#include "stm32f4xx_crc.h" +#include "stm32f4xx_cryp.h" +#include "stm32f4xx_dac.h" +#include "stm32f4xx_dbgmcu.h" +#include "stm32f4xx_dcmi.h" +#include "stm32f4xx_dma.h" +#include "stm32f4xx_exti.h" +#include "stm32f4xx_flash.h" +#include "stm32f4xx_fsmc.h" +#include "stm32f4xx_hash.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_i2c.h" +#include "stm32f4xx_iwdg.h" +#include "stm32f4xx_pwr.h" +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_rng.h" +#include "stm32f4xx_rtc.h" +#include "stm32f4xx_sdio.h" +#include "stm32f4xx_spi.h" +#include "stm32f4xx_syscfg.h" +#include "stm32f4xx_tim.h" +#include "stm32f4xx_usart.h" +#include "stm32f4xx_wwdg.h" +#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* If an external clock source is used, then the value of the following define + should be set to the value of the external clock source, else, if no external + clock is used, keep this define commented */ +/*#define I2S_EXTERNAL_CLOCK_VAL 12288000 */ /* Value of the external clock in Hz */ + + +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +/* #define USE_FULL_ASSERT 1 */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM32F4xx_CONF_H */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/IO_Toggle/stm32f4xx_it.c b/exampleF4/Projects/IO_Toggle/stm32f4xx_it.c new file mode 100644 index 0000000..ceac51a --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/stm32f4xx_it.c @@ -0,0 +1,167 @@ +/** + ****************************************************************************** + * @file IO_Toggle/stm32f4xx_it.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Main Interrupt Service Routines. + * This file provides template for all exceptions handler and + * peripherals interrupt service routine. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_it.h" + +/** @addtogroup STM32F4_Discovery_Peripheral_Examples + * @{ + */ + +/** @addtogroup IO_Toggle + * @{ + */ + +/* 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) +{ +} + +/******************************************************************************/ +/* 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 PPP interrupt request. + * @param None + * @retval None + */ +/*void PPP_IRQHandler(void) +{ +}*/ + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/IO_Toggle/stm32f4xx_it.h b/exampleF4/Projects/IO_Toggle/stm32f4xx_it.h new file mode 100644 index 0000000..74f17c9 --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/stm32f4xx_it.h @@ -0,0 +1,54 @@ +/** + ****************************************************************************** + * @file GPIO/IOToggle/stm32f4xx_it.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_IT_H +#define __STM32F4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.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 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/IO_Toggle/system_stm32f4xx.c b/exampleF4/Projects/IO_Toggle/system_stm32f4xx.c new file mode 100644 index 0000000..b058084 --- /dev/null +++ b/exampleF4/Projects/IO_Toggle/system_stm32f4xx.c @@ -0,0 +1,545 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * This file contains the system clock configuration for STM32F4xx devices, + * and is generated by the clock configuration tool + * stm32f4xx_Clock_Configuration_V1.0.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_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. + * + * 2. After each device reset the HSI (16 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f4xx.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 HSI 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 8 MHz, refer to "HSE_VALUE" define + * in "stm32f4xx.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: + *============================================================================= + *============================================================================= + * Supported STM32F4xx device revision | Rev A + *----------------------------------------------------------------------------- + * System Clock source | PLL (HSE) + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 4 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 2 + *----------------------------------------------------------------------------- + * HSE Frequency(Hz) | 8000000 + *----------------------------------------------------------------------------- + * PLL_M | 8 + *----------------------------------------------------------------------------- + * PLL_N | 336 + *----------------------------------------------------------------------------- + * PLL_P | 2 + *----------------------------------------------------------------------------- + * PLL_Q | 7 + *----------------------------------------------------------------------------- + * PLLI2S_N | NA + *----------------------------------------------------------------------------- + * PLLI2S_R | NA + *----------------------------------------------------------------------------- + * I2S input clock | NA + *----------------------------------------------------------------------------- + * VDD(V) | 3.3 + *----------------------------------------------------------------------------- + * High Performance mode | Enabled + *----------------------------------------------------------------------------- + * Flash Latency(WS) | 5 + *----------------------------------------------------------------------------- + * Prefetch Buffer | OFF + *----------------------------------------------------------------------------- + * Instruction cache | ON + *----------------------------------------------------------------------------- + * Data cache | ON + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Enabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + +#include "stm32f4xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/*!< Uncomment the following line if you need to use external SRAM mounted + on STM324xG_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 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ + + +/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ +#define PLL_M 8 +#define PLL_N 336 + +/* SYSCLK = PLL_VCO / PLL_P */ +#define PLL_P 2 + +/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ +#define PLL_Q 7 + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + + uint32_t SystemCoreClock = 168000000; + + __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 + * @{ + */ + +static void SetSysClock(void); +#ifdef DATA_IN_ExtSRAM + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* 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; + +#ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM */ + + /* Configure the System clock source, PLL Multiplier and Divider factors, + AHB/APBx prescalers and Flash settings ----------------------------------*/ + SetSysClock(); + + /* 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.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.h file (default value + * 25 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, 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; +} + +/** + * @brief Configures the System clock source, PLL Multiplier and Divider factors, + * 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) +{ +/******************************************************************************/ +/* PLL (clocked by HSE) used as System clock source */ +/******************************************************************************/ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* 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 high performance mode, System frequency up to 168 MHz */ + RCC->APB1ENR |= RCC_APB1ENR_PWREN; + PWR->CR |= PWR_CR_PMODE; + + /* HCLK = SYSCLK / 1*/ + RCC->CFGR |= RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK / 2*/ + RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; + + /* PCLK1 = HCLK / 4*/ + RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; + + /* Configure the main PLL */ + RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | + (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); + + /* Enable the main PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till the main PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ + FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; + + /* Select the main PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= RCC_CFGR_SW_PLL; + + /* Wait till the main PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != 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 */ + } + +} + +/** + * @brief Setup the external memory controller. Called in startup_stm32f4xx.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external SRAM mounted on STM324xG_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 | PE3 <-> FSMC_A19 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | + | PD5 <-> FSMC_NWE | PE4 <-> FSMC_A20 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | + | PD8 <-> FSMC_D13 | PE7 <-> FSMC_D4 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | + | PD9 <-> FSMC_D14 | PE8 <-> FSMC_D5 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | + | PD10 <-> FSMC_D15 | PE9 <-> FSMC_D6 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | + | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7 | PF13 <-> FSMC_A7 |------------------+ + | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8 | PF14 <-> FSMC_A8 | + | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9 | PF15 <-> FSMC_A9 | + | PD14 <-> FSMC_D0 | PE13 <-> FSMC_D10 |------------------+ + | PD15 <-> FSMC_D1 | PE14 <-> FSMC_D11 | + | | PE15 <-> FSMC_D12 | + +-------------------+--------------------+ +*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR = 0x00000078; + + /* Connect PDx pins to FSMC Alternate function */ + GPIOD->AFR[0] = 0x00cc00cc; + GPIOD->AFR[1] = 0xcc0ccccc; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xaaaa0a0a; + /* Configure PDx pins speed to 100 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] = 0xc00cc0cc; + GPIOE->AFR[1] = 0xcccccccc; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xaaaa828a; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xffffc3cf; + /* 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 100 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] = 0x000000c0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00080aaa; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000c0fff; + /* 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->AHB3ENR = 0x00000001; + + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001015; + FSMC_Bank1->BTCR[3] = 0x00010603;//0x00010400; + FSMC_Bank1E->BWTR[2] = 0x0fffffff; +/* + Bank1_SRAM2 is configured as follow: + + p.FSMC_AddressSetupTime = 3;//0; + p.FSMC_AddressHoldTime = 0; + p.FSMC_DataSetupTime = 6;//4; + p.FSMC_BusTurnAroundDuration = 1; + p.FSMC_CLKDivision = 0; + p.FSMC_DataLatency = 0; + p.FSMC_AccessMode = FSMC_AccessMode_A; + + FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; + FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; + FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; + 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; +*/ + +} +#endif /* DATA_IN_ExtSRAM */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/exampleF4/Projects/discovery_demo/Makefile b/exampleF4/Projects/discovery_demo/Makefile new file mode 100644 index 0000000..782f982 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/Makefile @@ -0,0 +1,61 @@ +EXECUTABLE=STM32F4-Discovery_Demo.elf +BIN_IMAGE=STM32F4-Discovery_Demo.bin + +CC=arm-none-eabi-gcc +OBJCOPY=arm-none-eabi-objcopy + +CFLAGS=-g -O2 -mlittle-endian -mthumb +CFLAGS+=-mcpu=cortex-m4 +CFLAGS+=-ffreestanding -nostdlib + +#usb_conf.h +CFLAGS+=-DUSE_USB_OTG_FS=1 + +# to run from FLASH +CFLAGS+=-Wl,-T,stm32_flash.ld + +CFLAGS+=-I./ + +# stm32f4_discovery lib +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc/device_support +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc/core_support + +#STM32_USB_Device_Library +CFLAGS+=-I../../STM32_USB_Device_Library/Class/hid/inc +CFLAGS+=-I../../STM32_USB_Device_Library/Core/inc + +#STM32_USB_OTG_Driver +CFLAGS+=-I../../STM32_USB_OTG_Driver/inc + +#STM32F4xx_StdPeriph_Driver\inc +CFLAGS+=-I../../STM32F4xx_StdPeriph_Driver/inc + +#Utilities +CFLAGS+=-I../../Utilities/STM32F4-Discovery + +all: $(BIN_IMAGE) + +$(BIN_IMAGE): $(EXECUTABLE) + $(OBJCOPY) -O binary $^ $@ + +$(EXECUTABLE): main.c selftest.c system_stm32f4xx.c startup_stm32f4xx.s stm32f4xx_it.c \ + usb_bsp.c usbd_desc.c usbd_usr.c usb_core.c \ + ../../Utilities/STM32F4-Discovery/stm32f4_discovery.c \ + ../../Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.c \ + ../../Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.c \ + ../../STM32_USB_OTG_Driver/src/usb_dcd_int.c \ + ../../STM32_USB_OTG_Driver/src/usb_dcd.c \ + ../../STM32_USB_Device_Library/core/src/usbd_core.c \ + ../../STM32_USB_Device_Library/core/src/usbd_req.c \ + ../../STM32_USB_Device_Library/core/src/usbd_ioreq.c \ + ../../STM32_USB_Device_Library/class/hid/src/usbd_hid_core.c \ + + + $(CC) $(CFLAGS) $^ -o $@ -L../../STM32F4xx_StdPeriph_Driver/build -lSTM32F4xx_StdPeriph_Driver -L../../STM32F_USB_OTG_Driver/build + +clean: + rm -rf $(EXECUTABLE) + rm -rf $(BIN_IMAGE) + +.PHONY: all clean diff --git a/exampleF4/Projects/discovery_demo/Release_Notes.html b/exampleF4/Projects/discovery_demo/Release_Notes.html new file mode 100644 index 0000000..304ad5d --- /dev/null +++ b/exampleF4/Projects/discovery_demo/Release_Notes.html @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + Release Notes for STM32F4-Discovery Board Demonstration firmware + + + + + + + + + + +
+


+

+
+ + + + + + +
+ + + + + + + + + +
+

Back to Release page

+
+

Release +Notes for STM32F4-Discovery Board Demonstration firmware

+

Copyright +2011 STMicroelectronics

+

+
+

 

+ + + + + + +
+

Contents

+
    +
  1. STM32F4-Discovery Board Demonstration firmware update History
  2. +
  3. License
  4. +
+ + +

STM32F4-Discovery Board Demonstration firmware update History

For more information on the STM32F4-Discovery board visit www.st.com/stm32f4-discovery.

V1.0.0 / 19-September-2011

+

Main +Changes

+ +
  • First official version of the STM32F4-Discovery Board Demonstration firmware

License

+

The +enclosed firmware and all the related documentation are not covered by +a License Agreement, if you need such License you can contact your +local STMicroelectronics office.

+ + THE +PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO +SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR +ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY +CLAIMS ARISING FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY +CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH +THEIR PRODUCTS. + +
+
+

For +complete documentation on STMicroelectronics Microcontrollers visit www.st.com

+
+

+
+
+

 

+
+ + \ No newline at end of file diff --git a/exampleF4/Projects/discovery_demo/STM32F4-Discovery_Demo.bin b/exampleF4/Projects/discovery_demo/STM32F4-Discovery_Demo.bin new file mode 100644 index 0000000000000000000000000000000000000000..9635fb22d88868054c6472e6806c45b4a14e23c0 GIT binary patch literal 31620 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�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įgM3lpm0 zxe1+=6QU7qsZaAcwA@5gN(%iUHRl@b>bCOEs=5*NoN70?31!ZmvCY=`AVizeX$_Te z&K`7I->38=HhH*{7#TB$x)0}~T*HxfydP(2qwbz2Ib&dQXT7nzR*h$bm$;_mnw29bxIs^H6WwKvnVIV3PRE+kv+#61ESs)Ao|7hpneugUVmu#Z z#XO3ALBFN(tl^Kl%9ZeFiw{3sdF#v;3@oINebNsD;>)+V(IrQY6Ac_R%V9BU tkt<{UU;+qIuCwH_;drVW-b`>X`zeov*cQJ{lP$Vq=|BcifaCqy{{gf3@9h8p literal 0 HcmV?d00001 diff --git a/exampleF4/Projects/discovery_demo/main.c b/exampleF4/Projects/discovery_demo/main.c new file mode 100644 index 0000000..b7d92ed --- /dev/null +++ b/exampleF4/Projects/discovery_demo/main.c @@ -0,0 +1,509 @@ +/** + ****************************************************************************** + * @file main.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Main program body + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "usbd_hid_core.h" +#include "usbd_usr.h" +#include "usbd_desc.h" + +//Library config for this project!!!!!!!!!!! +#include "stm32f4xx_conf.h" + +/** @addtogroup STM32F4-Discovery_Demo + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +#define TESTRESULT_ADDRESS 0x080FFFFC +#define ALLTEST_PASS 0x00000000 +#define ALLTEST_FAIL 0x55555555 + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment = 4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +__ALIGN_BEGIN USB_OTG_CORE_HANDLE USB_OTG_dev __ALIGN_END; + +uint16_t PrescalerValue = 0; + +__IO uint32_t TimingDelay; +__IO uint8_t DemoEnterCondition = 0x00; +__IO uint8_t UserButtonPressed = 0x00; +LIS302DL_InitTypeDef LIS302DL_InitStruct; +LIS302DL_FilterConfigTypeDef LIS302DL_FilterStruct; +__IO int8_t X_Offset, Y_Offset, Z_Offset = 0x00; +uint8_t Buffer[6]; + +/* Private function prototypes -----------------------------------------------*/ +static uint32_t Demo_USBConfig(void); +static void TIM4_Config(void); +static void Demo_Exec(void); + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Main program. + * @param None + * @retval None + */ +int main(void) +{ + RCC_ClocksTypeDef RCC_Clocks; + + /* Initialize LEDs and User_Button on STM32F4-Discovery --------------------*/ + STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_EXTI); + + STM_EVAL_LEDInit(LED4); + STM_EVAL_LEDInit(LED3); + STM_EVAL_LEDInit(LED5); + STM_EVAL_LEDInit(LED6); + + /* SysTick end of count event each 10ms */ + RCC_GetClocksFreq(&RCC_Clocks); + SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); + + if (STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET) + { + /* Turn on LEDs available on STM32F4-Discovery ---------------------------*/ + STM_EVAL_LEDOn(LED4); + STM_EVAL_LEDOn(LED3); + STM_EVAL_LEDOn(LED5); + STM_EVAL_LEDOn(LED6); + + if ((*(__IO uint32_t*) TESTRESULT_ADDRESS) == ALLTEST_PASS) + { + TimingDelay = 300; + /* Waiting User Button is pressed or Test Program condition verified */ + while ((STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET)&&(TimingDelay != 0x00)) + {} + } + else + { + /* Waiting User Button is Released or TimeOut*/ + TimingDelay = 300; + while ((STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET)&&(TimingDelay != 0x00)) + {} + if (STM_EVAL_PBGetState(BUTTON_USER) == Bit_RESET) + { + TimingDelay = 0x00; + } + } + if (TimingDelay == 0x00) + { + /* Turn off LEDs available on STM32F4-Discovery ------------------------*/ + STM_EVAL_LEDOff(LED4); + STM_EVAL_LEDOff(LED3); + STM_EVAL_LEDOff(LED5); + STM_EVAL_LEDOff(LED6); + + /* Waiting User Button is released */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET) + {} + + /* Unlocks the FLASH control register access */ + FLASH_Unlock(); + + /* Move discovery kit to detect negative and positive acceleration values + on X, Y and Z axis */ + Accelerometer_MEMS_Test(); + + /* USB Hardware connection */ + USB_Test(); + + /* Audio Hardware connection */ + Audio_Test(); + + /* Microphone MEMS Hardware connection */ + Microphone_MEMS_Test(); + + /* Write PASS code at last word in the flash memory */ + FLASH_ProgramWord(TESTRESULT_ADDRESS, ALLTEST_PASS); + + while(1) + { + /* Toggle Green LED: signaling the End of the Test program */ + STM_EVAL_LEDToggle(LED4); + Delay(10); + } + } + else + { + Demo_Exec(); + } + } + else + { + Demo_Exec(); + } +} + +/** + * @brief Execute the demo application. + * @param None + * @retval None + */ +static void Demo_Exec(void) +{ + RCC_ClocksTypeDef RCC_Clocks; + uint8_t togglecounter = 0x00; + + while(1) + { + DemoEnterCondition = 0x00; + + /* Reset UserButton_Pressed variable */ + UserButtonPressed = 0x00; + + /* Initialize LEDs to be managed by GPIO */ + STM_EVAL_LEDInit(LED4); + STM_EVAL_LEDInit(LED3); + STM_EVAL_LEDInit(LED5); + STM_EVAL_LEDInit(LED6); + + /* SysTick end of count event each 10ms */ + RCC_GetClocksFreq(&RCC_Clocks); + SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); + + /* Turn OFF all LEDs */ + STM_EVAL_LEDOff(LED4); + STM_EVAL_LEDOff(LED3); + STM_EVAL_LEDOff(LED5); + STM_EVAL_LEDOff(LED6); + + /* Waiting User Button is pressed */ + while (UserButtonPressed == 0x00) + { + /* Toggle LED4 */ + STM_EVAL_LEDToggle(LED4); + Delay(10); + /* Toggle LED4 */ + STM_EVAL_LEDToggle(LED3); + Delay(10); + /* Toggle LED4 */ + STM_EVAL_LEDToggle(LED5); + Delay(10); + /* Toggle LED4 */ + STM_EVAL_LEDToggle(LED6); + Delay(10); + togglecounter ++; + if (togglecounter == 0x10) + { + togglecounter = 0x00; + while (togglecounter < 0x10) + { + STM_EVAL_LEDToggle(LED4); + STM_EVAL_LEDToggle(LED3); + STM_EVAL_LEDToggle(LED5); + STM_EVAL_LEDToggle(LED6); + Delay(10); + togglecounter ++; + } + togglecounter = 0x00; + } + } + + /* Waiting User Button is Released */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET) + {} + UserButtonPressed = 0x00; + + /* TIM4 channels configuration */ + TIM4_Config(); + + /* Disable all Timer4 channels */ + TIM_CCxCmd(TIM4, TIM_Channel_1, DISABLE); + TIM_CCxCmd(TIM4, TIM_Channel_2, DISABLE); + TIM_CCxCmd(TIM4, TIM_Channel_3, DISABLE); + TIM_CCxCmd(TIM4, TIM_Channel_4, DISABLE); + + /* MEMS configuration */ + LIS302DL_InitStruct.Power_Mode = LIS302DL_LOWPOWERMODE_ACTIVE; + LIS302DL_InitStruct.Output_DataRate = LIS302DL_DATARATE_100; + LIS302DL_InitStruct.Axes_Enable = LIS302DL_XYZ_ENABLE; + LIS302DL_InitStruct.Full_Scale = LIS302DL_FULLSCALE_2_3; + LIS302DL_InitStruct.Self_Test = LIS302DL_SELFTEST_NORMAL; + LIS302DL_Init(&LIS302DL_InitStruct); + + /* Required delay for the MEMS Accelerometre: Turn-on time = 3/Output data Rate + = 3/100 = 30ms */ + Delay(30); + + DemoEnterCondition = 0x01; + /* MEMS High Pass Filter configuration */ + LIS302DL_FilterStruct.HighPassFilter_Data_Selection = LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER; + LIS302DL_FilterStruct.HighPassFilter_CutOff_Frequency = LIS302DL_HIGHPASSFILTER_LEVEL_1; + LIS302DL_FilterStruct.HighPassFilter_Interrupt = LIS302DL_HIGHPASSFILTERINTERRUPT_1_2; + LIS302DL_FilterConfig(&LIS302DL_FilterStruct); + + LIS302DL_Read(Buffer, LIS302DL_OUT_X_ADDR, 6); + X_Offset = Buffer[0]; + Y_Offset = Buffer[2]; + Z_Offset = Buffer[4]; + + /* USB configuration */ + Demo_USBConfig(); + + /* Waiting User Button is pressed */ + while (UserButtonPressed == 0x00) + {} + + /* Waiting User Button is Released */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET) + {} + + /* Disable SPI1 used to drive the MEMS accelerometre */ + SPI_Cmd(LIS302DL_SPI, DISABLE); + + /* Disconnect the USB device */ + DCD_DevDisconnect(&USB_OTG_dev); + USB_OTG_StopDevice(&USB_OTG_dev); + } +} + +/** + * @brief Initializes the USB for the demonstration application. + * @param None + * @retval None + */ +static uint32_t Demo_USBConfig(void) +{ + USBD_Init(&USB_OTG_dev, + USB_OTG_FS_CORE_ID, + &USR_desc, + &USBD_HID_cb, + &USR_cb); + + return 0; +} + +/** + * @brief Configures the TIM Peripheral. + * @param None + * @retval None + */ +static void TIM4_Config(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + TIM_OCInitTypeDef TIM_OCInitStructure; + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + + /* --------------------------- System Clocks Configuration -----------------*/ + /* TIM4 clock enable */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); + + /* GPIOD clock enable */ + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); + + /*-------------------------- GPIO Configuration ----------------------------*/ + /* GPIOD Configuration: Pins 12, 13, 14 and 15 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_Init(GPIOD, &GPIO_InitStructure); + + /* Connect TIM4 pins to AF2 */ + GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4); + GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4); + + /* ----------------------------------------------------------------------- + TIM4 Configuration: Output Compare Timing Mode: + + In this example TIM4 input clock (TIM4CLK) is set to 2 * APB1 clock (PCLK1), + since APB1 prescaler is different from 1 (APB1 Prescaler = 4, see system_stm32f4xx.c file). + TIM4CLK = 2 * PCLK1 + PCLK1 = HCLK / 4 + => TIM4CLK = 2*(HCLK / 4) = HCLK/2 = SystemCoreClock/2 + + To get TIM4 counter clock at 2 KHz, the prescaler is computed as follows: + Prescaler = (TIM4CLK / TIM1 counter clock) - 1 + Prescaler = (168 MHz/(2 * 2 KHz)) - 1 = 41999 + + To get TIM4 output clock at 1 Hz, the period (ARR)) is computed as follows: + ARR = (TIM4 counter clock / TIM4 output clock) - 1 + = 1999 + + TIM4 Channel1 duty cycle = (TIM4_CCR1/ TIM4_ARR)* 100 = 50% + TIM4 Channel2 duty cycle = (TIM4_CCR2/ TIM4_ARR)* 100 = 50% + TIM4 Channel3 duty cycle = (TIM4_CCR3/ TIM4_ARR)* 100 = 50% + TIM4 Channel4 duty cycle = (TIM4_CCR4/ TIM4_ARR)* 100 = 50% + + ==> TIM4_CCRx = TIM4_ARR/2 = 1000 (where x = 1, 2, 3 and 4). + + Note: + SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file. + Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate() + function to update SystemCoreClock variable value. Otherwise, any configuration + based on this variable will be incorrect. + ----------------------------------------------------------------------- */ + + + /* Compute the prescaler value */ + PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 2000) - 1; + + /* Time base configuration */ + TIM_TimeBaseStructure.TIM_Period = TIM_ARR; + TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; + TIM_TimeBaseStructure.TIM_ClockDivision = 0; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); + + /* Enable TIM4 Preload register on ARR */ + TIM_ARRPreloadConfig(TIM4, ENABLE); + + /* TIM PWM1 Mode configuration: Channel */ + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_Pulse = TIM_CCR; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + + /* Output Compare PWM1 Mode configuration: Channel1 */ + TIM_OC1Init(TIM4, &TIM_OCInitStructure); + TIM_CCxCmd(TIM4, TIM_Channel_1, DISABLE); + + TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); + + /* Output Compare PWM1 Mode configuration: Channel2 */ + TIM_OC2Init(TIM4, &TIM_OCInitStructure); + TIM_CCxCmd(TIM4, TIM_Channel_2, DISABLE); + + TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); + + /* Output Compare PWM1 Mode configuration: Channel3 */ + TIM_OC3Init(TIM4, &TIM_OCInitStructure); + TIM_CCxCmd(TIM4, TIM_Channel_3, DISABLE); + + TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); + + /* Output Compare PWM1 Mode configuration: Channel4 */ + TIM_OC4Init(TIM4, &TIM_OCInitStructure); + TIM_CCxCmd(TIM4, TIM_Channel_4, DISABLE); + + TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); + + /* TIM4 enable counter */ + TIM_Cmd(TIM4, ENABLE); +} + +/** + * @brief Inserts a delay time. + * @param nTime: specifies the delay time length, in 10 ms. + * @retval None + */ +void Delay(__IO uint32_t nTime) +{ + TimingDelay = nTime; + + while(TimingDelay != 0); +} + +/** + * @brief Decrements the TimingDelay variable. + * @param None + * @retval None + */ +void TimingDelay_Decrement(void) +{ + if (TimingDelay != 0x00) + { + TimingDelay--; + } +} + +/** + * @brief This function handles the test program fail. + * @param None + * @retval None + */ +void Fail_Handler(void) +{ + /* Erase last sector */ + FLASH_EraseSector(FLASH_Sector_11, VoltageRange_3); + /* Write FAIL code at last word in the flash memory */ + FLASH_ProgramWord(TESTRESULT_ADDRESS, ALLTEST_FAIL); + + while(1) + { + /* Toggle Red LED */ + STM_EVAL_LEDToggle(LED5); + Delay(5); + } +} + +/** + * @brief MEMS accelerometre management of the timeout situation. + * @param None. + * @retval None. + */ +uint32_t LIS302DL_TIMEOUT_UserCallback(void) +{ + /* MEMS Accelerometer Timeout error occured during Test program execution */ + if (DemoEnterCondition == 0x00) + { + /* Timeout error occured for SPI TXE/RXNE flags waiting loops.*/ + Fail_Handler(); + } + /* MEMS Accelerometer Timeout error occured during Demo execution */ + else + { + while (1) + { + } + } + return 0; +} + +#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 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/main.h b/exampleF4/Projects/discovery_demo/main.h new file mode 100644 index 0000000..cc19bb4 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/main.h @@ -0,0 +1,62 @@ +/** + ****************************************************************************** + * @file main.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Header for main.c module + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4_DISCOVERY_DEMO_H +#define __STM32F4_DISCOVERY_DEMO_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4_discovery.h" +#include "stm32f4_discovery_audio_codec.h" +#include "stm32f4_discovery_lis302dl.h" +#include "selftest.h" +#include + + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* TIM2 Autoreload and Capture Compare register values */ +#define TIM_ARR (uint16_t)1999 +#define TIM_CCR (uint16_t)1000 + +/* MEMS Microphone SPI Interface */ +#define SPI_SCK_PIN GPIO_Pin_10 +#define SPI_SCK_GPIO_PORT GPIOB +#define SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOB +#define SPI_SCK_SOURCE GPIO_PinSource10 +#define SPI_SCK_AF GPIO_AF_SPI2 + +#define SPI_MOSI_PIN GPIO_Pin_3 +#define SPI_MOSI_GPIO_PORT GPIOC +#define SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOC +#define SPI_MOSI_SOURCE GPIO_PinSource3 +#define SPI_MOSI_AF GPIO_AF_SPI2 + +/* Exported macro ------------------------------------------------------------*/ +#define ABS(x) (x < 0) ? (-x) : x +#define MAX(a,b) (a < b) ? (b) : a +/* Exported functions ------------------------------------------------------- */ +void TimingDelay_Decrement(void); +void Delay(__IO uint32_t nTime); +void Fail_Handler(void); +#endif /* __STM32F4_DISCOVERY_DEMO_H */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/selftest.c b/exampleF4/Projects/discovery_demo/selftest.c new file mode 100644 index 0000000..7183ffa --- /dev/null +++ b/exampleF4/Projects/discovery_demo/selftest.c @@ -0,0 +1,808 @@ +/** + ****************************************************************************** + * @file selftest.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file provides the hardware tests + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ */ + +/* Includes ------------------------------------------------------------------*/ +#include "selftest.h" + +//Library config for this project!!!!!!!!!!! +#include "stm32f4xx_conf.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define MEMS_PASSCONDITION 15 +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Init Structure definition */ +RCC_ClocksTypeDef RCC_Clocks; +ADC_InitTypeDef ADC_InitStructure; +ADC_CommonInitTypeDef ADC_CommonInitStructure; + +__IO uint16_t ConvData1, ConvData2; +__IO uint16_t counter0 = 0, counter1 = 0, Idx = 0; +uint8_t ADC_Channel[2] = {ADC_Channel_2, ADC_Channel_3}; +uint8_t DACTest = 0; +uint8_t GPIO_Pin [2] = {GPIO_Pin_2, GPIO_Pin_3}; + +uint16_t count = 0, count1 = 24, Left_Right = 0; +const int16_t sinebuf[48] = {0, 4276, 8480, 12539, 16383, 19947, 23169, 25995, + 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272, + 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276, + 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995, + -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272, + -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276 + }; +extern __IO uint32_t TimingDelay; + +extern LIS302DL_InitTypeDef LIS302DL_InitStruct; +extern LIS302DL_FilterConfigTypeDef LIS302DL_FilterStruct; + +extern __IO int8_t X_Offset, Y_Offset, Z_Offset; +extern uint8_t Buffer[6]; +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Test MEMS Hardware. + * The main objectif of this test is to check the hardware connection of the + * MEMS peripheral. + * @param None + * @retval None + */ +void Accelerometer_MEMS_Test(void) +{ + uint8_t temp, memsteststatus = 0x00; + uint8_t xdata, ydata = 0; + + /* MEMS configuration ------------------------------------------------------*/ + /* Set configuration of LIS302DL*/ + LIS302DL_InitStruct.Power_Mode = LIS302DL_LOWPOWERMODE_ACTIVE; + LIS302DL_InitStruct.Output_DataRate = LIS302DL_DATARATE_100; + LIS302DL_InitStruct.Axes_Enable = LIS302DL_X_ENABLE | LIS302DL_Y_ENABLE; + LIS302DL_InitStruct.Full_Scale = LIS302DL_FULLSCALE_2_3; + LIS302DL_InitStruct.Self_Test = LIS302DL_SELFTEST_NORMAL; + LIS302DL_Init(&LIS302DL_InitStruct); + + /* Set configuration of Internal High Pass Filter of LIS302DL*/ + LIS302DL_FilterStruct.HighPassFilter_Data_Selection = LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER; + LIS302DL_FilterStruct.HighPassFilter_CutOff_Frequency = LIS302DL_HIGHPASSFILTER_LEVEL_1; + LIS302DL_FilterStruct.HighPassFilter_Interrupt = LIS302DL_HIGHPASSFILTERINTERRUPT_1_2; + LIS302DL_FilterConfig(&LIS302DL_FilterStruct); + + /* Required delay for the MEMS Accelerometre: Turn-on time = 3/Output data Rate + = 3/100 = 30ms */ + Delay(30); + + /* Read WHO_AM_I register */ + LIS302DL_Read(&temp, LIS302DL_WHO_AM_I_ADDR, 1); + + /* Check device identification register, this register should contains + the device identifier that for LIS302DL is set to 0x3B */ + if (temp != 0x3B) + { + Fail_Handler(); + } + + TimingDelay = 500; + /* Wait until detecting all MEMS direction or timeout */ + while((memsteststatus == 0x00)&&(TimingDelay != 0x00)) + { + LIS302DL_Read(Buffer, LIS302DL_OUT_X_ADDR, 4); + xdata = ABS((int8_t)(Buffer[0])); + ydata = ABS((int8_t)(Buffer[2])); + /* Check test PASS condition */ + if ((xdata > MEMS_PASSCONDITION) || (ydata > MEMS_PASSCONDITION)) + { + /* MEMS Test PASS */ + memsteststatus = 0x01; + } + } + + /* MEMS test status: PASS */ + if(memsteststatus != 0x00) + { + /* Turn Green LED ON: signaling MEMS Test PASS */ + STM_EVAL_LEDOn(LED4); + + /* Waiting User Button is pressed */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_RESET) + {} + + /* Waiting User Button is Released */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_SET) + {} + + /* Turn Green LED OFF: signaling the end of MEMS Test and switching to + the next Sub Test */ + STM_EVAL_LEDOff(LED4); + } + /* MEMS test status: Timeout occurs */ + else + { + Fail_Handler(); + } +} + +/** + * @brief Test USB Hardware. + * The main objectif of this test is to check the hardware connection of the + * Audio and USB peripheral. + * @param None + * @retval None + */ +void USB_Test(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + + /******************************** USB Test **********************************/ + + /*----------------- Part1: without cables connected ------------------------*/ + + /* GPIOA, GPIOC and GPIOD clock enable */ + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | \ + RCC_AHB1Periph_GPIOD, ENABLE); + + /* GPIOD Configuration: Pins 5 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOD, &GPIO_InitStructure); + + /* Turn LED8 ON using PD5 */ + GPIO_ResetBits(GPIOD, GPIO_Pin_5); + + /* GPIOC Configuration: Pin 0 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 9 in input pull-up */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Turn LED7 ON using PC0 (5v) */ + GPIO_ResetBits(GPIOC, GPIO_Pin_0); + + /* Waiting delay 10ms */ + Delay(1); + + if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == Bit_RESET) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 10 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check the ID level without cable connected */ + if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == Bit_RESET) + { + Fail_Handler(); + } + + /* Turn LED7 OFF using PC0 */ + GPIO_SetBits(GPIOC, GPIO_Pin_0); + + /* GPIOA Configuration: Pins 11, 12 in input pull-up */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 9 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_ResetBits(GPIOA, GPIO_Pin_9); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check PA11 and PA12 level without cable connected */ + if ((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == Bit_RESET) || \ + (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == Bit_RESET)) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 12 in input pull-up */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 11 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_ResetBits(GPIOA, GPIO_Pin_11); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check PA12 level without cable connected */ + if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == Bit_RESET) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 11 in input pull-up */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 12 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_ResetBits(GPIOA, GPIO_Pin_12); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check PA12 level without cable connected */ + if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == Bit_RESET) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 9 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Turn LED7 ON using PA9 */ + GPIO_SetBits(GPIOA, GPIO_Pin_9); + + /* Turn Green LED ON: signaling Audio USB Test part1 PASS */ + STM_EVAL_LEDOn(LED4); + + /* Waiting User Button is pressed */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_RESET) + {} + + /* Waiting User Button is Released */ + while (STM_EVAL_PBGetState(BUTTON_USER) != Bit_RESET) + {} + + /* Turn Green LED OFF: signaling the end of Audio USB Test part1 and switching to + the part2 */ + STM_EVAL_LEDOff(LED4); + + /* Turn LED7 OFF using PA9 */ + GPIO_ResetBits(GPIOA, GPIO_Pin_9); + + /* Turn LED8 OFF using PD5 */ + GPIO_SetBits(GPIOD, GPIO_Pin_5); + + /*--------------- Part2: with Audio USB cables connected ------------------*/ + + /*********************************** USB Test *******************************/ + /* Check the ID level with cable connected */ + if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) != Bit_RESET) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 11, 12 in input pull-down */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 9 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_SetBits(GPIOA, GPIO_Pin_9); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check PA11 and PA12 level with cable connected */ + if ((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == Bit_RESET) || \ + (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == Bit_RESET)) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 9, 12 in input pull-down */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 11 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_SetBits(GPIOA, GPIO_Pin_11); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check PA9 and PA12 level with cable connected */ + if ((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == Bit_RESET)|| \ + (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == Bit_RESET)) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 9, 11 in input pull-down */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_11; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 12 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_SetBits(GPIOA, GPIO_Pin_12); + + /* Waiting delay 10ms */ + Delay(1); + + /* Check PA9 and PA12 level with cable connected */ + if ((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == Bit_RESET)|| \ + (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == Bit_RESET)) + { + Fail_Handler(); + } + + /* GPIOA Configuration: Pins 11, 12 in input pull-down */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* GPIOA Configuration: Pin 9 in output push-pull */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Turn LED7 OFF using PA9 */ + GPIO_ResetBits(GPIOA, GPIO_Pin_9); +} + +/** + * @brief Test Audio Hardware. + * The main objectif of this test is to check the hardware connection of the + * Audio peripheral. + * @param None + * @retval None + */ +void Audio_Test(void) +{ + GPIO_InitTypeDef GPIO_InitStructure; + uint8_t audioteststatus = 0x00; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); + + /* Set the current audio interface: I2S or DAC */ + EVAL_AUDIO_SetAudioInterface(AUDIO_INTERFACE_I2S); + + /* Initialize the Audio codec and all related peripherals (I2S, I2C, IOs...) */ + if (EVAL_AUDIO_Init(OUTPUT_DEVICE_HEADPHONE, 87, I2S_AudioFreq_48k) !=0) + { + Fail_Handler(); + } + /* I2S code to be exectued under the I2S interrupt */ + DACTest = 0; + + /* ADC Common Init */ + ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8; + ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; + ADC_CommonInit(&ADC_CommonInitStructure); + + /* ADC peripherals Init */ + ADC_StructInit(&ADC_InitStructure); + ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b; + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfConversion = 1; + ADC_Init(ADC1, &ADC_InitStructure); + + ADC_Init(ADC2, &ADC_InitStructure); + + /* Configure ADC Channels pin as analog input */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + counter1 = 0; + counter0 = 0; + audioteststatus = 0; + /* ADCperipheral[PerIdx] Regular Channel Config */ + ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_56Cycles); + /* ADCperipheral[PerIdx] Regular Channel Config */ + ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 1, ADC_SampleTime_56Cycles); + /* Enable ADC1 */ + ADC_Cmd(ADC1, ENABLE); + ADC_Cmd(ADC2, ENABLE); + + TimingDelay = 500; + /* Wait until detecting 500 data*/ + while((audioteststatus == 0)&&(TimingDelay != 0)) + { + ADC_SoftwareStartConv(ADC1); + while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); + ConvData1 = ADC_GetConversionValue(ADC1); + + ADC_SoftwareStartConv(ADC2); + while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET); + ConvData2 = ADC_GetConversionValue(ADC2); + + /* 1.75V equals to 150 */ + if ((ConvData1 > 150) && (ConvData2 < 10) && (counter1 != 500)) + { + counter1 ++; + } + if ((ConvData1 < 10) && (ConvData2 > 150) && (counter0 != 500)) + { + counter0 ++; + } + if((counter1 == 500) && (counter0 == 500)) + { + audioteststatus = 1; + } + } + + /* Disable ADC Peripherals */ + ADC_Cmd(ADC1, DISABLE); + ADC_Cmd(ADC2, DISABLE); + + /* Audio test status: FAIL */ + if(audioteststatus == 0) + { + Fail_Handler(); + } + + EVAL_AUDIO_DeInit(); + EVAL_AUDIO_SetAudioInterface(AUDIO_INTERFACE_DAC); + /* Initialize the Audio codec and all related peripherals (I2S, I2C, IOs...) */ + if (EVAL_AUDIO_Init(OUTPUT_DEVICE_HEADPHONE, 100, I2S_AudioFreq_48k) !=0) + { + Fail_Handler(); + } + + /* DAC code to be exectued under the I2S interrupt */ + DACTest = 1; + counter1 = 0; + counter0 = 0; + audioteststatus = 0; + + /* Enable ADC1 */ + ADC_Cmd(ADC1, ENABLE); + ADC_Cmd(ADC2, ENABLE); + + TimingDelay = 500; + /* Wait until detecting 50 data*/ + while((audioteststatus == 0)&&(TimingDelay != 0)) + { + + ADC_SoftwareStartConv(ADC1); + while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); + + ConvData1 = ADC_GetConversionValue(ADC1); + + ADC_SoftwareStartConv(ADC2); + while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET); + + ConvData2 = ADC_GetConversionValue(ADC2); + + /* 2.0V equals to 170 */ + if ((ConvData1 > 170) && (ConvData2 > 170) &&(counter1 != 500)) + { + counter1 ++; + } + if ((ConvData1 < 10) && (ConvData2 < 10) && (counter0 != 500)) + { + counter0 ++; + } + if((counter1 == 500) && (counter0 == 500)) + { + audioteststatus = 1; + } + } + + /* Audio test status: FAIL */ + if(audioteststatus == 0x00) + { + Fail_Handler(); + } + + /* Turn Green LED ON: signaling Audio USB Test part2 PASS */ + STM_EVAL_LEDOn(LED4); + + /* Waiting User_Button pressed */ + while (STM_EVAL_PBGetState(BUTTON_USER) == Bit_RESET) + {} + + /* Turn Green LED OFF: signaling the end of Audio USB Test part2 */ + STM_EVAL_LEDOff(LED4); +} + +/** + * @brief Test Micophone MEMS Hardware. + * The main objectif of this test is to check the hardware connection of the + * Microphone MEMS peripheral. + * @param None + * @retval None + */ +void Microphone_MEMS_Test(void) +{ + uint16_t data = 0x00; + uint8_t index = 0x00; + I2S_InitTypeDef I2S_InitStructure; + GPIO_InitTypeDef GPIO_InitStructure; + + /* Enable the SPI clock */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); + + /* Enable GPIO clocks */ + RCC_AHB1PeriphClockCmd(SPI_SCK_GPIO_CLK | SPI_MOSI_GPIO_CLK, ENABLE); + + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; + + /* SPI SCK pin configuration */ + GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN; + GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStructure); + + /* Connect SPI pins to AF5 */ + GPIO_PinAFConfig(SPI_SCK_GPIO_PORT, SPI_SCK_SOURCE, SPI_SCK_AF); + + /* SPI MOSI pin configuration */ + GPIO_InitStructure.GPIO_Pin = SPI_MOSI_PIN; + GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); + + GPIO_PinAFConfig(SPI_MOSI_GPIO_PORT, SPI_MOSI_SOURCE, SPI_MOSI_AF); + + /* I2S configuration -------------------------------------------------------*/ + SPI_I2S_DeInit(SPI2); + I2S_InitStructure.I2S_AudioFreq = 64000; + I2S_InitStructure.I2S_Standard = I2S_Standard_MSB; + I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; + I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; + I2S_InitStructure.I2S_Mode = I2S_Mode_MasterRx; + I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; + /* Initialize the I2S peripheral with the structure above */ + I2S_Init(SPI2, &I2S_InitStructure); + + /* Enable the I2S peripheral */ + I2S_Cmd(SPI2, ENABLE); + + /* Waiting until MEMS microphone ready : Wake-up Time */ + Delay(10); + + TimingDelay = 500; + /* Wait until detect the click on the MEMS microphone or TimeOut delay*/ + while((index < 30) && (TimingDelay != 0x00)) + { + /* Waiting RXNE Flag or TimeOut delay */ + while((SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_RXNE) == RESET)&& (TimingDelay != 0x00)) + {} + data = SPI_I2S_ReceiveData(SPI2); + if (data == 0xFFFF) + { + index++; + } + } + + /* MEMS microphone test status: Timeout occurs */ + if(index != 30) + { + Fail_Handler(); + } +} + +/*-------------------------------- + Callbacks implementation: + the callbacks prototypes are defined in the stm324xg_eval_audio_codec.h file + and their implementation should be done in the user code if they are needed. + Below some examples of callback implementations. + --------------------------------------------------------*/ +/** + * @brief Calculates the remaining file size and new position of the pointer. + * @param None + * @retval None + */ +void EVAL_AUDIO_TransferComplete_CallBack(uint32_t pBuffer, uint32_t Size) +{ + /* Calculate the remaining audio data in the file and the new size + for the DMA transfer. If the Audio files size is less than the DMA max + data transfer size, so there is no calculation to be done, just restart + from the beginning of the file ... */ + /* Check if the end of file has been reached */ + +} + +/** + * @brief Manages the DMA Half Transfer complete interrupt. + * @param None + * @retval None + */ +void EVAL_AUDIO_HalfTransfer_CallBack(uint32_t pBuffer, uint32_t Size) +{ +#ifdef AUDIO_MAL_MODE_CIRCULAR + + /* Display message on the LCD screen */ + LCD_DisplayStringLine(Line8, " 1/2 Buffer Reached "); + +#endif /* AUDIO_MAL_MODE_CIRCULAR */ + + /* Generally this interrupt routine is used to load the buffer when + a streaming scheme is used: When first Half buffer is already transferred load + the new data to the first half of buffer while DMA is transferring data from + the second half. And when Transfer complete occurs, load the second half of + the buffer while the DMA is transferring from the first half ... */ + /* + ........... + */ +} +/** + * @brief Get next data sample callback + * @param None + * @retval Next data sample to be sent + */ +uint16_t EVAL_AUDIO_GetSampleCallBack(void) +{ + uint16_t data = 0; + + if (DACTest == 0) + { + if (Left_Right==0) + { + /* Get the next sample to be sent */ + data = sinebuf[count++]; + + if (count == 48) + { + count = 0x00; + } + Left_Right = 1; + } + else + { + /* Get the next sample to be sent */ + data = sinebuf[count1++]; + + if (count1 == 48) + { + count1 = 0x00; + } + Left_Right = 0; + } + } + else + { + /* Get the next sample to be sent */ + data = 32768 + sinebuf[count++]; + + if (count == 48) + { + count = 0x00; + } + } + return data; +} + + +/** + * @brief Manages the DMA FIFO error interrupt. + * @param None + * @retval None + */ +void EVAL_AUDIO_Error_CallBack(void* pData) +{ + /* Stop the program with an infinite loop */ + while (1) + {} + + /* could also generate a system reset to recover from the error */ + /* .... */ +} + +#ifndef USE_DEFAULT_TIMEOUT_CALLBACK +/** + * @brief Basic management of the timeout situation. + * @param None. + * @retval None. + */ +uint32_t Codec_TIMEOUT_UserCallback(void) +{ + /* Block communication and all processes */ + while (1) + { + } +} +#endif /* USE_DEFAULT_TIMEOUT_CALLBACK */ +/*----------------------------------------------------------------------------*/ + + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/selftest.h b/exampleF4/Projects/discovery_demo/selftest.h new file mode 100644 index 0000000..feef3de --- /dev/null +++ b/exampleF4/Projects/discovery_demo/selftest.h @@ -0,0 +1,41 @@ +/** + ****************************************************************************** + * @file selftest.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Header for selftest.c module + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __SELFTEST_H +#define __SELFTEST_H + +/* Includes ------------------------------------------------------------------*/ +#include +#include "main.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void Audio_Test(void); +void Accelerometer_MEMS_Test(void); +void USB_Test(void); +void Microphone_MEMS_Test(void); + +#endif /* __SELFTEST_H */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/startup_stm32f4xx.s b/exampleF4/Projects/discovery_demo/startup_stm32f4xx.s new file mode 100644 index 0000000..ce5360f --- /dev/null +++ b/exampleF4/Projects/discovery_demo/startup_stm32f4xx.s @@ -0,0 +1,509 @@ +/** + ****************************************************************************** + * @file startup_stm32f4xx.s + * @author MCD Application Team + * @version V1.0.0 + * @date 30-September-2011 + * @brief STM32F4xx Devices vector table for RIDE7 toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Configure the clock system and the external SRAM mounted on + * STM324xG-EVAL board to be used as data memory (optional, + * to be enabled by user) + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m3 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M3. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_IRQHandler /* PVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word CAN1_TX_IRQHandler /* CAN1 TX */ + .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ + .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ + .word CAN1_SCE_IRQHandler /* CAN1 SCE */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */ + .word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */ + .word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FSMC_IRQHandler /* FSMC */ + .word SDIO_IRQHandler /* SDIO */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word CAN2_TX_IRQHandler /* CAN2 TX */ + .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ + .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ + .word CAN2_SCE_IRQHandler /* CAN2 SCE */ + .word OTG_FS_IRQHandler /* USB OTG FS */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_IRQHandler /* DCMI */ + .word CRYP_IRQHandler /* CRYP crypto */ + .word HASH_RNG_IRQHandler /* Hash and Rng */ + .word FPU_IRQHandler /* FPU */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_IRQHandler + .thumb_set PVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM9_IRQHandler + .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM10_IRQHandler + .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM11_IRQHandler + .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak OTG_FS_WKUP_IRQHandler + .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FSMC_IRQHandler + .thumb_set FSMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak CRYP_IRQHandler + .thumb_set CRYP_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/stm32_flash.ld b/exampleF4/Projects/discovery_demo/stm32_flash.ld new file mode 100644 index 0000000..ee842a7 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/stm32_flash.ld @@ -0,0 +1,170 @@ +/* +***************************************************************************** +** +** File : stm32_flash.ld +** +** Abstract : Linker script for STM32F207IG Device with +** 1024KByte FLASH, 112KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Environment : Atollic TrueSTUDIO(R) +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +** (c)Copyright Atollic AB. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the Atollic TrueSTUDIO(R) toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x2001c000; /* end of 112K RAM */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K + MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + /* MEMORY_bank1 section, code must be located here explicitly */ + /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ + .memory_b1_text : + { + *(.mb1text) /* .mb1text sections (code) */ + *(.mb1text*) /* .mb1text* sections (code) */ + *(.mb1rodata) /* read-only data (constants) */ + *(.mb1rodata*) + } >MEMORY_B1 + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/exampleF4/Projects/discovery_demo/stm32f4xx_conf.h b/exampleF4/Projects/discovery_demo/stm32f4xx_conf.h new file mode 100644 index 0000000..74447a8 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/stm32f4xx_conf.h @@ -0,0 +1,94 @@ +/** + ****************************************************************************** + * @file stm32f4xx_conf.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Library configuration file. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_CONF_H +#define __STM32F4xx_CONF_H + +#if defined (HSE_VALUE) +/* Redefine the HSE value; it's equal to 8 MHz on the STM32F4-DISCOVERY Kit */ + #undef HSE_VALUE + #define HSE_VALUE ((uint32_t)8000000) +#endif /* HSE_VALUE */ + +/* Includes ------------------------------------------------------------------*/ +/* Uncomment the line below to enable peripheral header file inclusion */ +#include "stm32f4xx_adc.h" +#include "stm32f4xx_can.h" +#include "stm32f4xx_crc.h" +#include "stm32f4xx_cryp.h" +#include "stm32f4xx_dac.h" +#include "stm32f4xx_dbgmcu.h" +#include "stm32f4xx_dcmi.h" +#include "stm32f4xx_dma.h" +#include "stm32f4xx_exti.h" +#include "stm32f4xx_flash.h" +#include "stm32f4xx_fsmc.h" +#include "stm32f4xx_hash.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_i2c.h" +#include "stm32f4xx_iwdg.h" +#include "stm32f4xx_pwr.h" +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_rng.h" +#include "stm32f4xx_rtc.h" +#include "stm32f4xx_sdio.h" +#include "stm32f4xx_spi.h" +#include "stm32f4xx_syscfg.h" +#include "stm32f4xx_tim.h" +#include "stm32f4xx_usart.h" +#include "stm32f4xx_wwdg.h" +#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* If an external clock source is used, then the value of the following define + should be set to the value of the external clock source, else, if no external + clock is used, keep this define commented */ +/*#define I2S_EXTERNAL_CLOCK_VAL 12288000 */ /* Value of the external clock in Hz */ + + +/* Uncomment the line below to expanse the "assert_param" macro in the + Standard Peripheral Library drivers code */ +/* #define USE_FULL_ASSERT 1 */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0) +#endif /* USE_FULL_ASSERT */ + +#endif /* __STM32F4xx_CONF_H */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/stm32f4xx_it.c b/exampleF4/Projects/discovery_demo/stm32f4xx_it.c new file mode 100644 index 0000000..cee2c24 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/stm32f4xx_it.c @@ -0,0 +1,320 @@ +/** + ****************************************************************************** + * @file stm32f4xx_it.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief Main Interrupt Service Routines. + * This file provides all exceptions handler and peripherals interrupt + * service routine. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_it.h" +#include "main.h" +#include "usb_core.h" +#include "usbd_core.h" +#include "stm32f4_discovery.h" +#include "usbd_hid_core.h" + +//Library config for this project!!!!!!!!!!! +#include "stm32f4xx_conf.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define CURSOR_STEP 7 + +extern uint8_t Buffer[6]; +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +extern __IO uint8_t DemoEnterCondition; +uint8_t Counter = 0x00; +extern int8_t X_Offset; +extern int8_t Y_Offset; +extern __IO uint8_t UserButtonPressed; +__IO uint8_t TempAcceleration = 0; +/* Private function prototypes -----------------------------------------------*/ +extern USB_OTG_CORE_HANDLE USB_OTG_dev; +static uint8_t *USBD_HID_GetPos (void); +extern uint32_t USBD_OTG_ISR_Handler (USB_OTG_CORE_HANDLE *pdev); + +/******************************************************************************/ +/* Cortex-M3 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) +{ + uint8_t *buf; + uint8_t temp1, temp2 = 0x00; + + if (DemoEnterCondition == 0x00) + { + TimingDelay_Decrement(); + } + else + { + buf = USBD_HID_GetPos(); + if((buf[1] != 0) ||(buf[2] != 0)) + { + USBD_HID_SendReport (&USB_OTG_dev, + buf, + 4); + } + Counter ++; + if (Counter == 10) + { + Buffer[0] = 0; + Buffer[2] = 0; + /* Disable All TIM4 Capture Compare Channels */ + TIM_CCxCmd(TIM4, TIM_Channel_1, DISABLE); + TIM_CCxCmd(TIM4, TIM_Channel_2, DISABLE); + TIM_CCxCmd(TIM4, TIM_Channel_3, DISABLE); + TIM_CCxCmd(TIM4, TIM_Channel_4, DISABLE); + + LIS302DL_Read(Buffer, LIS302DL_OUT_X_ADDR, 6); + /* Remove the offsets values from data */ + Buffer[0] -= X_Offset; + Buffer[2] -= Y_Offset; + /* Update autoreload and capture compare registers value*/ + temp1 = ABS((int8_t)(Buffer[0])); + temp2 = ABS((int8_t)(Buffer[2])); + TempAcceleration = MAX(temp1, temp2); + + if(TempAcceleration != 0) + { + if ((int8_t)Buffer[0] < -2) + { + /* Enable TIM4 Capture Compare Channel 4 */ + TIM_CCxCmd(TIM4, TIM_Channel_4, ENABLE); + /* Sets the TIM4 Capture Compare4 Register value */ + TIM_SetCompare4(TIM4, TIM_CCR/TempAcceleration); + } + if ((int8_t)Buffer[0] > 2) + { + /* Enable TIM4 Capture Compare Channel 2 */ + TIM_CCxCmd(TIM4, TIM_Channel_2, ENABLE); + /* Sets the TIM4 Capture Compare2 Register value */ + TIM_SetCompare2(TIM4, TIM_CCR/TempAcceleration); + } + if ((int8_t)Buffer[2] > 2) + { + /* Enable TIM4 Capture Compare Channel 1 */ + TIM_CCxCmd(TIM4, TIM_Channel_1, ENABLE); + /* Sets the TIM4 Capture Compare1 Register value */ + TIM_SetCompare1(TIM4, TIM_CCR/TempAcceleration); + } + if ((int8_t)Buffer[2] < -2) + { + /* Enable TIM4 Capture Compare Channel 3 */ + TIM_CCxCmd(TIM4, TIM_Channel_3, ENABLE); + /* Sets the TIM4 Capture Compare3 Register value */ + TIM_SetCompare3(TIM4, TIM_CCR/TempAcceleration); + } + /* Time base configuration */ + TIM_SetAutoreload(TIM4, TIM_ARR/TempAcceleration); + } + Counter = 0x00; + } + } + +} + +/******************************************************************************/ +/* STM32Fxxx 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_stm32fxxx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles PPP interrupt request. + * @param None + * @retval None + */ +/*void PPP_IRQHandler(void) +{ +}*/ + +/** + * @brief This function handles EXTI0_IRQ Handler. + * @param None + * @retval None + */ +void EXTI0_IRQHandler(void) +{ + UserButtonPressed = 0x01; + + /* Clear the EXTI line pending bit */ + EXTI_ClearITPendingBit(USER_BUTTON_EXTI_LINE); +} + +/** + * @brief This function handles EXTI15_10_IRQ Handler. + * @param None + * @retval None + */ +void OTG_FS_WKUP_IRQHandler(void) +{ + if(USB_OTG_dev.cfg.low_power) + { + /* Reset SLEEPDEEP and SLEEPONEXIT bits */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + + /* After wake-up from sleep mode, reconfigure the system clock */ + SystemInit(); + USB_OTG_UngateClock(&USB_OTG_dev); + } + EXTI_ClearITPendingBit(EXTI_Line18); +} + +/** + * @brief This function handles OTG_HS Handler. + * @param None + * @retval None + */ +void OTG_FS_IRQHandler(void) +{ + USBD_OTG_ISR_Handler (&USB_OTG_dev); +} + +/** +* @brief USBD_HID_GetPos +* @param None +* @retval Pointer to report +*/ +static uint8_t *USBD_HID_GetPos (void) +{ + static uint8_t HID_Buffer[4] = {0}; + + HID_Buffer[1] = 0; + HID_Buffer[2] = 0; + /* LEFT Direction */ + if(((int8_t)Buffer[2]) < -2) + { + HID_Buffer[1] += CURSOR_STEP; + } + /* RIGHT Direction */ + if(((int8_t)Buffer[2]) > 2) + { + HID_Buffer[1] -= CURSOR_STEP; + } + /* UP Direction */ + if(((int8_t)Buffer[0]) < -2) + { + HID_Buffer[2] += CURSOR_STEP; + } + /* DOWN Direction */ + if(((int8_t)Buffer[0]) > 2) + { + HID_Buffer[2] -= CURSOR_STEP; + } + + return HID_Buffer; +} +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/stm32f4xx_it.h b/exampleF4/Projects/discovery_demo/stm32f4xx_it.h new file mode 100644 index 0000000..4ae766c --- /dev/null +++ b/exampleF4/Projects/discovery_demo/stm32f4xx_it.h @@ -0,0 +1,54 @@ +/** + ****************************************************************************** + * @file stm32f4xx_it.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4xx_IT_H +#define __STM32F4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.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 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/system_stm32f4xx.c b/exampleF4/Projects/discovery_demo/system_stm32f4xx.c new file mode 100644 index 0000000..fbb195c --- /dev/null +++ b/exampleF4/Projects/discovery_demo/system_stm32f4xx.c @@ -0,0 +1,566 @@ +/** + ****************************************************************************** + * @file system_stm32f4xx.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File. + * This file contains the system clock configuration for STM32F4xx devices, + * and is generated by the clock configuration tool + * stm32f4xx_Clock_Configuration_V1.0.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_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. + * + * 2. After each device reset the HSI (16 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32f4xx.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 HSI 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 8 MHz, refer to "HSE_VALUE" define + * in "stm32f4xx.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: + *============================================================================= + *============================================================================= + * Supported STM32F4xx device revision | Rev A + *----------------------------------------------------------------------------- + * System Clock source | PLL (HSE) + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 168000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 4 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 2 + *----------------------------------------------------------------------------- + * HSE Frequency(Hz) | 8000000 + *----------------------------------------------------------------------------- + * PLL_M | 8 + *----------------------------------------------------------------------------- + * PLL_N | 336 + *----------------------------------------------------------------------------- + * PLL_P | 2 + *----------------------------------------------------------------------------- + * PLL_Q | 7 + *----------------------------------------------------------------------------- + * PLLI2S_N | 192 + *----------------------------------------------------------------------------- + * PLLI2S_R | 5 + *----------------------------------------------------------------------------- + * I2S input clock(Hz) | 38400000 + *----------------------------------------------------------------------------- + * VDD(V) | 3.3 + *----------------------------------------------------------------------------- + * High Performance mode | Enabled + *----------------------------------------------------------------------------- + * Flash Latency(WS) | 5 + *----------------------------------------------------------------------------- + * Prefetch Buffer | OFF + *----------------------------------------------------------------------------- + * Instruction cache | ON + *----------------------------------------------------------------------------- + * Data cache | ON + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Enabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f4xx_system + * @{ + */ + +/** @addtogroup STM32F4xx_System_Private_Includes + * @{ + */ + +#include "stm32f4xx.h" + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Defines + * @{ + */ + +/*!< Uncomment the following line if you need to use external SRAM mounted + on STM324xG_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 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ + + +/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ +#define PLL_M 8 +#define PLL_N 336 + +/* SYSCLK = PLL_VCO / PLL_P */ +#define PLL_P 2 + +/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ +#define PLL_Q 7 + +/* PLLI2S_VCO = (HSE_VALUE Or HSI_VALUE / PLL_M) * PLLI2S_N + I2SCLK = PLLI2S_VCO / PLLI2S_R */ +#define PLLI2S_N 192 +#define PLLI2S_R 5 + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Variables + * @{ + */ + + uint32_t SystemCoreClock = 168000000; + + __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 + * @{ + */ + +static void SetSysClock(void); +#ifdef DATA_IN_ExtSRAM + static void SystemInit_ExtMemCtl(void); +#endif /* DATA_IN_ExtSRAM */ + +/** + * @} + */ + +/** @addtogroup STM32F4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* 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; + +#ifdef DATA_IN_ExtSRAM + SystemInit_ExtMemCtl(); +#endif /* DATA_IN_ExtSRAM */ + + /* Configure the System clock source, PLL Multiplier and Divider factors, + AHB/APBx prescalers and Flash settings ----------------------------------*/ + SetSysClock(); + + /* 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.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.h file (default value + * 25 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, 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; +} + +/** + * @brief Configures the System clock source, PLL Multiplier and Divider factors, + * 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) +{ +/******************************************************************************/ +/* PLL (clocked by HSE) used as System clock source */ +/******************************************************************************/ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + /* 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 high performance mode, System frequency up to 168 MHz */ + RCC->APB1ENR |= RCC_APB1ENR_PWREN; + PWR->CR |= PWR_CR_PMODE; + + /* HCLK = SYSCLK / 1*/ + RCC->CFGR |= RCC_CFGR_HPRE_DIV1; + + /* PCLK2 = HCLK / 2*/ + RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; + + /* PCLK1 = HCLK / 4*/ + RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; + + /* Configure the main PLL */ + RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | + (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); + + /* Enable the main PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait till the main PLL is ready */ + while((RCC->CR & RCC_CR_PLLRDY) == 0) + { + } + + /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ + FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; + + /* Select the main PLL as system clock source */ + RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); + RCC->CFGR |= RCC_CFGR_SW_PLL; + + /* Wait till the main PLL is used as system clock source */ + while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != 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 */ + } + +/******************************************************************************/ +/* I2S clock configuration */ +/******************************************************************************/ + /* PLLI2S clock used as I2S clock source */ + RCC->CFGR &= ~RCC_CFGR_I2SSRC; + + /* Configure PLLI2S */ + RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28); + + /* Enable PLLI2S */ + RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON); + + /* Wait till PLLI2S is ready */ + while((RCC->CR & RCC_CR_PLLI2SRDY) == 0) + { + } +} + +/** + * @brief Setup the external memory controller. Called in startup_stm32f4xx.s + * before jump to __main + * @param None + * @retval None + */ +#ifdef DATA_IN_ExtSRAM +/** + * @brief Setup the external memory controller. + * Called in startup_stm32f4xx.s before jump to main. + * This function configures the external SRAM mounted on STM324xG_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 | PE3 <-> FSMC_A19 | PF2 <-> FSMC_A2 | PG2 <-> FSMC_A12 | + | PD5 <-> FSMC_NWE | PE4 <-> FSMC_A20 | PF3 <-> FSMC_A3 | PG3 <-> FSMC_A13 | + | PD8 <-> FSMC_D13 | PE7 <-> FSMC_D4 | PF4 <-> FSMC_A4 | PG4 <-> FSMC_A14 | + | PD9 <-> FSMC_D14 | PE8 <-> FSMC_D5 | PF5 <-> FSMC_A5 | PG5 <-> FSMC_A15 | + | PD10 <-> FSMC_D15 | PE9 <-> FSMC_D6 | PF12 <-> FSMC_A6 | PG9 <-> FSMC_NE2 | + | PD11 <-> FSMC_A16 | PE10 <-> FSMC_D7 | PF13 <-> FSMC_A7 |------------------+ + | PD12 <-> FSMC_A17 | PE11 <-> FSMC_D8 | PF14 <-> FSMC_A8 | + | PD13 <-> FSMC_A18 | PE12 <-> FSMC_D9 | PF15 <-> FSMC_A9 | + | PD14 <-> FSMC_D0 | PE13 <-> FSMC_D10 |------------------+ + | PD15 <-> FSMC_D1 | PE14 <-> FSMC_D11 | + | | PE15 <-> FSMC_D12 | + +-------------------+--------------------+ +*/ + /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */ + RCC->AHB1ENR = 0x00000078; + + /* Connect PDx pins to FSMC Alternate function */ + GPIOD->AFR[0] = 0x00cc00cc; + GPIOD->AFR[1] = 0xcc0ccccc; + /* Configure PDx pins in Alternate function mode */ + GPIOD->MODER = 0xaaaa0a0a; + /* Configure PDx pins speed to 100 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] = 0xc00cc0cc; + GPIOE->AFR[1] = 0xcccccccc; + /* Configure PEx pins in Alternate function mode */ + GPIOE->MODER = 0xaaaa828a; + /* Configure PEx pins speed to 100 MHz */ + GPIOE->OSPEEDR = 0xffffc3cf; + /* 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 100 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] = 0x000000c0; + /* Configure PGx pins in Alternate function mode */ + GPIOG->MODER = 0x00080aaa; + /* Configure PGx pins speed to 100 MHz */ + GPIOG->OSPEEDR = 0x000c0fff; + /* 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->AHB3ENR = 0x00000001; + + /* Configure and enable Bank1_SRAM2 */ + FSMC_Bank1->BTCR[2] = 0x00001015; + FSMC_Bank1->BTCR[3] = 0x00010603;//0x00010400; + FSMC_Bank1E->BWTR[2] = 0x0fffffff; +/* + Bank1_SRAM2 is configured as follow: + + p.FSMC_AddressSetupTime = 3;//0; + p.FSMC_AddressHoldTime = 0; + p.FSMC_DataSetupTime = 6;//4; + p.FSMC_BusTurnAroundDuration = 1; + p.FSMC_CLKDivision = 0; + p.FSMC_DataLatency = 0; + p.FSMC_AccessMode = FSMC_AccessMode_A; + + FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2; + FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; + FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_PSRAM; + 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; +*/ + +} +#endif /* DATA_IN_ExtSRAM */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/exampleF4/Projects/discovery_demo/usb_bsp.c b/exampleF4/Projects/discovery_demo/usb_bsp.c new file mode 100644 index 0000000..6861d65 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usb_bsp.c @@ -0,0 +1,382 @@ +/** + ****************************************************************************** + * @file usb_bsp.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file is responsible to offer board support package and is + * configurable by user. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_bsp.h" +#include "usbd_conf.h" +#include "stm32f4_discovery.h" + +//Library config for this project!!!!!!!!!!! +#include "stm32f4xx_conf.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY +* @{ +*/ + +/** @defgroup USB_BSP +* @brief This file is responsible to offer board support package +* @{ +*/ + +/** @defgroup USB_BSP_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_BSP_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + + + +/** @defgroup USB_BSP_Private_Macros +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_BSP_Private_Variables +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBH_BSP_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USB_BSP_Private_Functions +* @{ +*/ + + +/** +* @brief USB_OTG_BSP_Init +* Initilizes BSP configurations +* @param None +* @retval None +*/ + +void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) +{ + GPIO_InitTypeDef GPIO_InitStructure; + +#ifndef USE_ULPI_PHY +#ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT + EXTI_InitTypeDef EXTI_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure; +#endif +#endif + + + #ifdef USE_USB_OTG_FS + + RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE); + + /* Configure SOF VBUS ID DM DP Pins */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | + GPIO_Pin_9 | + GPIO_Pin_11 | + GPIO_Pin_12; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_OTG1_FS) ; + GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_OTG1_FS) ; + GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_OTG1_FS) ; + GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_OTG1_FS) ; + + /* this for ID line debug */ + + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_OTG1_FS) ; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ; + #else // USE_USB_OTG_HS + + #ifdef USE_ULPI_PHY // ULPI + RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | + RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOH | + RCC_AHB1Periph_GPIOI, ENABLE); + + + GPIO_PinAFConfig(GPIOA,GPIO_PinSource3, GPIO_AF_OTG2_HS) ; // D0 + GPIO_PinAFConfig(GPIOA,GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // CLK + GPIO_PinAFConfig(GPIOB,GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // D1 + GPIO_PinAFConfig(GPIOB,GPIO_PinSource1, GPIO_AF_OTG2_HS) ; // D2 + GPIO_PinAFConfig(GPIOB,GPIO_PinSource5, GPIO_AF_OTG2_HS) ; // D7 + GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_OTG2_HS) ; // D3 + GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_OTG2_HS) ; // D4 + GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_OTG2_HS) ; // D5 + GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_HS) ; // D6 + GPIO_PinAFConfig(GPIOH,GPIO_PinSource4, GPIO_AF_OTG2_HS) ; // NXT + GPIO_PinAFConfig(GPIOI,GPIO_PinSource11,GPIO_AF_OTG2_HS) ; // DIR + GPIO_PinAFConfig(GPIOC,GPIO_PinSource0, GPIO_AF_OTG2_HS) ; // STP + + // CLK + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // D0 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + + + // D1 D2 D3 D4 D5 D6 D7 + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | + GPIO_Pin_5 | GPIO_Pin_10 | + GPIO_Pin_11| GPIO_Pin_12 | + GPIO_Pin_13 ; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + + // STP + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOC, &GPIO_InitStructure); + + //NXT + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOH, &GPIO_InitStructure); + + + //DIR + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOI, &GPIO_InitStructure); + + + RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS | + RCC_AHB1Periph_OTG_HS_ULPI, ENABLE) ; + + #else + #ifdef USE_I2C_PHY + RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB , ENABLE); + /* Configure RESET INTN SCL SDA (Phy/I2C) Pins */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | + GPIO_Pin_1 | + GPIO_Pin_10 | + GPIO_Pin_11; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOB,GPIO_PinSource0,GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB,GPIO_PinSource1,GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_OTG2_FS); + RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS, ENABLE) ; + + #else + + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); + + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | + GPIO_Pin_13 | + GPIO_Pin_14 | + GPIO_Pin_15; + + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + GPIO_PinAFConfig(GPIOB,GPIO_PinSource12, GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_OTG2_FS) ; + GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_OTG2_FS) ; + RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_OTG_HS, ENABLE) ; + #endif + #endif // USE_ULPI_PHY + + #endif //USB_OTG_HS + + + /* enable the PWR clock */ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE); + + /* Configure the Key button in EXTI mode */ + STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_EXTI); + +#ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT + EXTI_ClearITPendingBit(EXTI_Line18); + + EXTI_InitStructure.EXTI_Line = EXTI_Line18; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + EXTI_ClearITPendingBit(EXTI_Line18); + + NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_WKUP_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + EXTI_ClearITPendingBit(EXTI_Line18); +#endif + +#ifdef USB_OTG_HS_LOW_PWR_MGMT_SUPPORT + EXTI_ClearITPendingBit(EXTI_Line20); + + EXTI_InitStructure.EXTI_Line = EXTI_Line20; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + EXTI_ClearITPendingBit(EXTI_Line20); + + NVIC_InitStructure.NVIC_IRQChannel = OTG_HS_WKUP_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + EXTI_ClearITPendingBit(EXTI_Line20); +#endif + + EXTI_ClearITPendingBit(USER_BUTTON_EXTI_LINE); +} +/** +* @brief USB_OTG_BSP_EnableInterrupt +* Enabele USB Global interrupt +* @param None +* @retval None +*/ +void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) +{ + NVIC_InitTypeDef NVIC_InitStructure; + + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); +#ifdef USE_USB_OTG_HS + NVIC_InitStructure.NVIC_IRQChannel = OTG_HS_IRQn; +#else + NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn; +#endif + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); + NVIC_InitStructure.NVIC_IRQChannel = OTG_HS_EP1_OUT_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); + NVIC_InitStructure.NVIC_IRQChannel = OTG_HS_EP1_IN_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +#endif +} +/** +* @brief USB_OTG_BSP_uDelay +* This function provides delay time in micro sec +* @param usec : Value of delay required in micro sec +* @retval None +*/ +void USB_OTG_BSP_uDelay (const uint32_t usec) +{ + uint32_t count = 0; + const uint32_t utime = (120 * usec / 7); + do + { + if ( ++count > utime ) + { + return ; + } + } + while (1); +} + + +/** +* @brief USB_OTG_BSP_mDelay +* This function provides delay time in milli sec +* @param msec : Value of delay required in milli sec +* @retval None +*/ +void USB_OTG_BSP_mDelay (const uint32_t msec) +{ + USB_OTG_BSP_uDelay(msec * 1000); +} +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/usb_conf.h b/exampleF4/Projects/discovery_demo/usb_conf.h new file mode 100644 index 0000000..eeb2f79 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usb_conf.h @@ -0,0 +1,252 @@ +/** + ****************************************************************************** + * @file usb_conf.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief General low level driver configuration + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CONF__H__ +#define __USB_CONF__H__ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_CONF + * @brief USB low level driver configuration file + * @{ + */ + +/** @defgroup USB_CONF_Exported_Defines + * @{ + */ + +/* USB Core and PHY interface configuration. + Tip: To avoid modifying these defines each time you need to change the USB + configuration, you can declare the needed define in your toolchain + compiler preprocessor. + */ +#ifndef USE_USB_OTG_FS + //#define USE_USB_OTG_FS +#endif /* USE_USB_OTG_FS */ + +#ifdef USE_USB_OTG_FS + #define USB_OTG_FS_CORE +#endif + +/******************************************************************************* +* FIFO Size Configuration in Device mode +* +* (i) Receive data FIFO size = RAM for setup packets + +* OUT endpoint control information + +* data OUT packets + miscellaneous +* Space = ONE 32-bits words +* --> RAM for setup packets = 10 spaces +* (n is the nbr of CTRL EPs the device core supports) +* --> OUT EP CTRL info = 1 space +* (one space for status information written to the FIFO along with each +* received packet) +* --> data OUT packets = (Largest Packet Size / 4) + 1 spaces +* (MINIMUM to receive packets) +* --> OR data OUT packets = at least 2*(Largest Packet Size / 4) + 1 spaces +* (if high-bandwidth EP is enabled or multiple isochronous EPs) +* --> miscellaneous = 1 space per OUT EP +* (one space for transfer complete status information also pushed to the +* FIFO with each endpoint's last packet) +* +* (ii)MINIMUM RAM space required for each IN EP Tx FIFO = MAX packet size for +* that particular IN EP. More space allocated in the IN EP Tx FIFO results +* in a better performance on the USB and can hide latencies on the AHB. +* +* (iii) TXn min size = 16 words. (n : Transmit FIFO index) +* (iv) When a TxFIFO is not used, the Configuration should be as follows: +* case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) +* --> Txm can use the space allocated for Txn. +* case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) +* --> Txn should be configured with the minimum space of 16 words +* (v) The FIFO is used optimally when used TxFIFOs are allocated in the top +* of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. +*******************************************************************************/ + + + +/****************** USB OTG FS CONFIGURATION **********************************/ +#ifdef USB_OTG_FS_CORE + #define RX_FIFO_FS_SIZE 128 + #define TX0_FIFO_FS_SIZE 64 + #define TX1_FIFO_FS_SIZE 128 + #define TX2_FIFO_FS_SIZE 0 + #define TX3_FIFO_FS_SIZE 0 + + //#define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT + //#define USB_OTG_FS_SOF_OUTPUT_ENABLED +#endif + +/****************** USB OTG MODE CONFIGURATION ********************************/ + +//#define USE_HOST_MODE +#define USE_DEVICE_MODE +//#define USE_OTG_MODE + + +#ifndef USB_OTG_FS_CORE + #ifndef USB_OTG_HS_CORE + #error "USB_OTG_HS_CORE or USB_OTG_FS_CORE should be defined" + #endif +#endif + + +#ifndef USE_DEVICE_MODE + #ifndef USE_HOST_MODE + #error "USE_DEVICE_MODE or USE_HOST_MODE should be defined" + #endif +#endif + +#ifndef USE_USB_OTG_HS + #ifndef USE_USB_OTG_FS + #error "USE_USB_OTG_HS or USE_USB_OTG_FS should be defined" + #endif +#else //USE_USB_OTG_HS + #ifndef USE_ULPI_PHY + #ifndef USE_EMBEDDED_PHY + #ifndef USE_I2C_PHY + #error "USE_ULPI_PHY or USE_EMBEDDED_PHY or USE_I2C_PHY should be defined" + #endif + #endif + #endif +#endif + +/****************** C Compilers dependant keywords ****************************/ +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined (__GNUC__) /* GNU Compiler */ + #define __ALIGN_END __attribute__ ((aligned (4))) + #define __ALIGN_BEGIN + #else + #define __ALIGN_END + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #elif defined (__TASKING__) /* TASKING Compiler */ + #define __ALIGN_BEGIN __align(4) + #endif /* __CC_ARM */ + #endif /* __GNUC__ */ +#else + #define __ALIGN_BEGIN + #define __ALIGN_END +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ + +/* __packed keyword used to decrease the data type alignment to 1-byte */ +#if defined (__CC_ARM) /* ARM Compiler */ + #define __packed __packed +#elif defined (__ICCARM__) /* IAR Compiler */ + #define __packed __packed +#elif defined ( __GNUC__ ) /* GNU Compiler */ + #define __packed __attribute__ ((__packed__)) +#elif defined (__TASKING__) /* TASKING Compiler */ + #define __packed __unaligned +#endif /* __CC_ARM */ + +/****************** C Compilers dependant keywords ****************************/ +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined (__GNUC__) /* GNU Compiler */ + #define __ALIGN_END __attribute__ ((aligned (4))) + #define __ALIGN_BEGIN + #else + #define __ALIGN_END + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #elif defined (__TASKING__) /* TASKING Compiler */ + #define __ALIGN_BEGIN __align(4) + #endif /* __CC_ARM */ + #endif /* __GNUC__ */ +#else + #define __ALIGN_BEGIN + #define __ALIGN_END +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ + +/* __packed keyword used to decrease the data type alignment to 1-byte */ +#if defined (__CC_ARM) /* ARM Compiler */ + #define __packed __packed +#elif defined (__ICCARM__) /* IAR Compiler */ + #define __packed __packed +#elif defined ( __GNUC__ ) /* GNU Compiler */ + #define __packed __attribute__ ((__packed__)) +#elif defined (__TASKING__) /* TASKING Compiler */ + #define __packed __unaligned +#endif /* __CC_ARM */ + + +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USB_CONF__H__ + + +/** + * @} + */ + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/exampleF4/Projects/discovery_demo/usb_core.c b/exampleF4/Projects/discovery_demo/usb_core.c new file mode 100644 index 0000000..74e432a --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usb_core.c @@ -0,0 +1,2187 @@ +/** + ****************************************************************************** + * @file usb_core.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief USB-OTG Core Layer + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_core.h" +#include "usb_bsp.h" + + +/** @addtogroup USB_OTG_DRIVER +* @{ +*/ + +/** @defgroup USB_CORE +* @brief This file includes the USB-OTG Core Layer +* @{ +*/ + + +/** @defgroup USB_CORE_Private_Defines +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + + +/** @defgroup USB_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_Variables +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USB_CORE_Private_Functions +* @{ +*/ + +/** +* @brief USB_OTG_EnableCommonInt +* Initializes the commmon interrupts, used in both device and modes +* @param pdev : Selected device +* @retval None +*/ +static void USB_OTG_EnableCommonInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_GINTMSK_TypeDef int_mask; + + int_mask.d32 = 0; + /* Clear any pending USB_OTG Interrupts */ +#ifndef USE_OTG_MODE + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GOTGINT, 0xFFFFFFFF); +#endif + /* Clear any pending interrupts */ + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTSTS, 0xFFFFFFFF); + /* Enable the interrupts in the INTMSK */ + int_mask.b.wkupintr = 1; + int_mask.b.usbsuspend = 1; + +#ifdef USE_OTG_MODE + int_mask.b.otgintr = 1; + int_mask.b.sessreqintr = 1; + int_mask.b.conidstschng = 1; +#endif + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTMSK, int_mask.d32); +} + +/** +* @brief USB_OTG_CoreReset : Soft reset of the core +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +static USB_OTG_STS USB_OTG_CoreReset(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + __IO USB_OTG_GRSTCTL_TypeDef greset; + uint32_t count = 0; + + greset.d32 = 0; + /* Wait for AHB master IDLE state. */ + do + { + USB_OTG_BSP_uDelay(3); + greset.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + return USB_OTG_OK; + } + } + while (greset.b.ahbidle == 0); + /* Core Soft Reset */ + count = 0; + greset.b.csftrst = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRSTCTL, greset.d32 ); + do + { + greset.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + break; + } + } + while (greset.b.csftrst == 1); + /* Wait for 3 PHY Clocks*/ + USB_OTG_BSP_uDelay(3); + return status; +} + +/** +* @brief USB_OTG_WritePacket : Writes a packet into the Tx FIFO associated +* with the EP +* @param pdev : Selected device +* @param src : source pointer +* @param ch_ep_num : end point number +* @param bytes : No. of bytes +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_WritePacket(USB_OTG_CORE_HANDLE *pdev, + uint8_t *src, + uint8_t ch_ep_num, + uint16_t len) +{ + USB_OTG_STS status = USB_OTG_OK; + if (pdev->cfg.dma_enable == 0) + { + uint32_t count32b= 0 , i= 0; + __IO uint32_t *fifo; + + count32b = (len + 3) / 4; + fifo = pdev->regs.DFIFO[ch_ep_num]; + for (i = 0; i < count32b; i++, src+=4) + { + USB_OTG_WRITE_REG32( fifo, *((__packed uint32_t *)src) ); + } + } + return status; +} + + +/** +* @brief USB_OTG_ReadPacket : Reads a packet from the Rx FIFO +* @param pdev : Selected device +* @param dest : Destination Pointer +* @param bytes : No. of bytes +* @retval None +*/ +void *USB_OTG_ReadPacket(USB_OTG_CORE_HANDLE *pdev, + uint8_t *dest, + uint16_t len) +{ + uint32_t i=0; + uint32_t count32b = (len + 3) / 4; + + __IO uint32_t *fifo = pdev->regs.DFIFO[0]; + + for ( i = 0; i < count32b; i++, dest += 4 ) + { + *(__packed uint32_t *)dest = USB_OTG_READ_REG32(fifo); + + } + return ((void *)dest); +} + +/** +* @brief USB_OTG_SelectCore +* Initialize core registers address. +* @param pdev : Selected device +* @param coreID : USB OTG Core ID +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_SelectCore(USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID) +{ + uint32_t i , baseAddress = 0; + USB_OTG_STS status = USB_OTG_OK; + + pdev->cfg.dma_enable = 0; + + /* at startup the core is in FS mode */ + pdev->cfg.speed = USB_OTG_SPEED_FULL; + pdev->cfg.mps = USB_OTG_FS_MAX_PACKET_SIZE ; + + /* initialize device cfg following its address */ + if (coreID == USB_OTG_FS_CORE_ID) + { + baseAddress = USB_OTG_FS_BASE_ADDR; + pdev->cfg.coreID = USB_OTG_FS_CORE_ID; + pdev->cfg.host_channels = 8 ; + pdev->cfg.dev_endpoints = 4 ; + pdev->cfg.TotalFifoSize = 320; /* in 32-bits */ + pdev->cfg.phy_itface = USB_OTG_EMBEDDED_PHY; + +#ifdef USB_OTG_FS_SOF_OUTPUT_ENABLED + pdev->cfg.Sof_output = 1; +#endif + +#ifdef USB_OTG_FS_LOW_PWR_MGMT_SUPPORT + pdev->cfg.low_power = 1; +#endif + } + else if (coreID == USB_OTG_HS_CORE_ID) + { + baseAddress = USB_OTG_HS_BASE_ADDR; + pdev->cfg.coreID = USB_OTG_HS_CORE_ID; + pdev->cfg.host_channels = 12 ; + pdev->cfg.dev_endpoints = 6 ; + pdev->cfg.TotalFifoSize = 1280;/* in 32-bits */ + +#ifdef USB_OTG_ULPI_PHY_ENABLED + pdev->cfg.phy_itface = USB_OTG_ULPI_PHY; +#else + #ifdef USB_OTG_EMBEDDED_PHY_ENABLED + pdev->cfg.phy_itface = USB_OTG_EMBEDDED_PHY; + #else + #ifdef USB_OTG_I2C_PHY_ENABLED + pdev->cfg.phy_itface = USB_OTG_I2C_PHY; + #endif + #endif +#endif + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + pdev->cfg.dma_enable = 1; +#endif + +#ifdef USB_OTG_HS_SOF_OUTPUT_ENABLED + pdev->cfg.Sof_output = 1; +#endif + +#ifdef USB_OTG_HS_LOW_PWR_MGMT_SUPPORT + pdev->cfg.low_power = 1; +#endif + + } + + pdev->regs.GREGS = (USB_OTG_GREGS *)(baseAddress + \ + USB_OTG_CORE_GLOBAL_REGS_OFFSET); + pdev->regs.DREGS = (USB_OTG_DREGS *) (baseAddress + \ + USB_OTG_DEV_GLOBAL_REG_OFFSET); + + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + pdev->regs.INEP_REGS[i] = (USB_OTG_INEPREGS *) \ + (baseAddress + USB_OTG_DEV_IN_EP_REG_OFFSET + \ + (i * USB_OTG_EP_REG_OFFSET)); + pdev->regs.OUTEP_REGS[i] = (USB_OTG_OUTEPREGS *) \ + (baseAddress + USB_OTG_DEV_OUT_EP_REG_OFFSET + \ + (i * USB_OTG_EP_REG_OFFSET)); + } + pdev->regs.HREGS = (USB_OTG_HREGS *)(baseAddress + \ + USB_OTG_HOST_GLOBAL_REG_OFFSET); + pdev->regs.HPRT0 = (uint32_t *)(baseAddress + USB_OTG_HOST_PORT_REGS_OFFSET); + + for (i = 0; i < pdev->cfg.host_channels; i++) + { + pdev->regs.HC_REGS[i] = (USB_OTG_HC_REGS *)(baseAddress + \ + USB_OTG_HOST_CHAN_REGS_OFFSET + \ + (i * USB_OTG_CHAN_REGS_OFFSET)); + } + for (i = 0; i < pdev->cfg.host_channels; i++) + { + pdev->regs.DFIFO[i] = (uint32_t *)(baseAddress + USB_OTG_DATA_FIFO_OFFSET +\ + (i * USB_OTG_DATA_FIFO_SIZE)); + } + pdev->regs.PCGCCTL = (uint32_t *)(baseAddress + USB_OTG_PCGCCTL_OFFSET); + + return status; +} + + +/** +* @brief USB_OTG_CoreInit +* Initializes the USB_OTG controller registers and prepares the core +* device mode or host mode operation. +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_CoreInit(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GUSBCFG_TypeDef usbcfg; + USB_OTG_GCCFG_TypeDef gccfg; + USB_OTG_GI2CCTL_TypeDef i2cctl; + USB_OTG_GAHBCFG_TypeDef ahbcfg; + + usbcfg.d32 = 0; + gccfg.d32 = 0; + ahbcfg.d32 = 0; + + + + if (pdev->cfg.phy_itface == USB_OTG_ULPI_PHY) + { + gccfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GCCFG); + gccfg.b.pwdn = 0; + + if (pdev->cfg.Sof_output) + { + gccfg.b.sofouten = 1; + } + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GCCFG, gccfg.d32); + + /* Init The ULPI Interface */ + usbcfg.d32 = 0; + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + + usbcfg.b.physel = 0; /* HS Interface */ +#ifdef USB_OTG_INTERNAL_VBUS_ENABLED + usbcfg.b.ulpi_ext_vbus_drv = 0; /* Use internal VBUS */ +#else + #ifdef USB_OTG_EXTERNAL_VBUS_ENABLED + usbcfg.b.ulpi_ext_vbus_drv = 1; /* Use external VBUS */ + #endif +#endif + usbcfg.b.term_sel_dl_pulse = 0; /* Data line pulsing using utmi_txvalid */ + usbcfg.b.ulpi_utmi_sel = 1; /* ULPI seleInterfacect */ + + usbcfg.b.phyif = 0; /* 8 bits */ + usbcfg.b.ddrsel = 0; /* single data rate */ + + usbcfg.b.ulpi_fsls = 0; + usbcfg.b.ulpi_clk_sus_m = 0; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + + /* Reset after a PHY select */ + USB_OTG_CoreReset(pdev); + + if(pdev->cfg.dma_enable == 1) + { + + ahbcfg.b.hburstlen = 5; /* 64 x 32-bits*/ + ahbcfg.b.dmaenable = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32); + + } + } + else /* FS interface (embedded Phy or I2C Phy) */ + { + + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG);; + usbcfg.b.physel = 1; /* FS Interface */ + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + /* Reset after a PHY select and set Host mode */ + USB_OTG_CoreReset(pdev); + /* Enable the I2C interface and deactivate the power down*/ + gccfg.d32 = 0; + gccfg.b.pwdn = 1; + + if(pdev->cfg.phy_itface == USB_OTG_I2C_PHY) + { + gccfg.b.i2cifen = 1; + } + gccfg.b.vbussensingA = 1 ; + gccfg.b.vbussensingB = 1 ; +#ifndef VBUS_SENSING_ENABLED + gccfg.b.disablevbussensing = 1; +#endif + + if(pdev->cfg.Sof_output) + { + gccfg.b.sofouten = 1; + } + + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GCCFG, gccfg.d32); + USB_OTG_BSP_mDelay(20); + /* Program GUSBCFG.OtgUtmifsSel to I2C*/ + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + + if(pdev->cfg.phy_itface == USB_OTG_I2C_PHY) + { + usbcfg.b.otgutmifssel = 1; + } + + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + + if(pdev->cfg.phy_itface == USB_OTG_I2C_PHY) + { + /*Program GI2CCTL.I2CEn*/ + i2cctl.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GI2CCTL); + i2cctl.b.i2cdevaddr = 1; + i2cctl.b.i2cen = 0; + i2cctl.b.dat_se0 = 1; + i2cctl.b.addr = 0x2D; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GI2CCTL, i2cctl.d32); + + USB_OTG_BSP_mDelay(200); + + i2cctl.b.i2cen = 1; + USB_OTG_WRITE_REG32 (&pdev->regs.GREGS->GI2CCTL, i2cctl.d32); + USB_OTG_BSP_mDelay(200); + } + } + /* case the HS core is working in FS mode */ + if(pdev->cfg.dma_enable == 1) + { + + ahbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GAHBCFG); + ahbcfg.b.hburstlen = 5; /* 64 x 32-bits*/ + ahbcfg.b.dmaenable = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32); + + } + /* initialize OTG features */ +#ifdef USE_OTG_MODE + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + usbcfg.b.hnpcap = 1; + usbcfg.b.srpcap = 1; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + USB_OTG_EnableCommonInt(pdev); +#endif + return status; +} +/** +* @brief USB_OTG_EnableGlobalInt +* Enables the controller's Global Int in the AHB Config reg +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EnableGlobalInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GAHBCFG_TypeDef ahbcfg; + + ahbcfg.d32 = 0; + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GAHBCFG, 0, ahbcfg.d32); + return status; +} + + +/** +* @brief USB_OTG_DisableGlobalInt +* Enables the controller's Global Int in the AHB Config reg +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GAHBCFG_TypeDef ahbcfg; + ahbcfg.d32 = 0; + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GAHBCFG, ahbcfg.d32, 0); + return status; +} + + +/** +* @brief USB_OTG_FlushTxFifo : Flush a Tx FIFO +* @param pdev : Selected device +* @param num : FO num +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_FlushTxFifo (USB_OTG_CORE_HANDLE *pdev , uint32_t num ) +{ + USB_OTG_STS status = USB_OTG_OK; + __IO USB_OTG_GRSTCTL_TypeDef greset; + + uint32_t count = 0; + greset.d32 = 0; + greset.b.txfflsh = 1; + greset.b.txfnum = num; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GRSTCTL, greset.d32 ); + do + { + greset.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + break; + } + } + while (greset.b.txfflsh == 1); + /* Wait for 3 PHY Clocks*/ + USB_OTG_BSP_uDelay(3); + return status; +} + + +/** +* @brief USB_OTG_FlushRxFifo : Flush a Rx FIFO +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_FlushRxFifo( USB_OTG_CORE_HANDLE *pdev ) +{ + USB_OTG_STS status = USB_OTG_OK; + __IO USB_OTG_GRSTCTL_TypeDef greset; + uint32_t count = 0; + + greset.d32 = 0; + greset.b.rxfflsh = 1; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GRSTCTL, greset.d32 ); + do + { + greset.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRSTCTL); + if (++count > 200000) + { + break; + } + } + while (greset.b.rxfflsh == 1); + /* Wait for 3 PHY Clocks*/ + USB_OTG_BSP_uDelay(3); + return status; +} + + +/** +* @brief USB_OTG_SetCurrentMode : Set ID line +* @param pdev : Selected device +* @param mode : (Host/device) +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_SetCurrentMode(USB_OTG_CORE_HANDLE *pdev , uint8_t mode) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GUSBCFG_TypeDef usbcfg; + + usbcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->GUSBCFG); + + usbcfg.b.force_host = 0; + usbcfg.b.force_dev = 0; + + if ( mode == HOST_MODE) + { + usbcfg.b.force_host = 1; + } + else if ( mode == DEVICE_MODE) + { + usbcfg.b.force_dev = 1; + } + + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GUSBCFG, usbcfg.d32); + USB_OTG_BSP_mDelay(50); + return status; +} + + +/** +* @brief USB_OTG_GetMode : Get current mode +* @param pdev : Selected device +* @retval current mode +*/ +uint32_t USB_OTG_GetMode(USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTSTS ) & 0x1); +} + + +/** +* @brief USB_OTG_IsDeviceMode : Check if it is device mode +* @param pdev : Selected device +* @retval num_in_ep +*/ +uint8_t USB_OTG_IsDeviceMode(USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_GetMode(pdev) != HOST_MODE); +} + + +/** +* @brief USB_OTG_IsHostMode : Check if it is host mode +* @param pdev : Selected device +* @retval num_in_ep +*/ +uint8_t USB_OTG_IsHostMode(USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_GetMode(pdev) == HOST_MODE); +} + + +/** +* @brief USB_OTG_ReadCoreItr : returns the Core Interrupt register +* @param pdev : Selected device +* @retval Status +*/ +uint32_t USB_OTG_ReadCoreItr(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t v = 0; + v = USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTSTS); + v &= USB_OTG_READ_REG32(&pdev->regs.GREGS->GINTMSK); + return v; +} + + +/** +* @brief USB_OTG_ReadOtgItr : returns the USB_OTG Interrupt register +* @param pdev : Selected device +* @retval Status +*/ +uint32_t USB_OTG_ReadOtgItr (USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32 (&pdev->regs.GREGS->GOTGINT)); +} + +#ifdef USE_HOST_MODE +/** +* @brief USB_OTG_CoreInitHost : Initializes USB_OTG controller for host mode +* @param pdev : Selected device +* @retval status +*/ +USB_OTG_STS USB_OTG_CoreInitHost(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_FSIZ_TypeDef nptxfifosize; + USB_OTG_FSIZ_TypeDef ptxfifosize; + USB_OTG_HCFG_TypeDef hcfg; + +#ifdef USE_OTG_MODE + USB_OTG_OTGCTL_TypeDef gotgctl; +#endif + + uint32_t i = 0; + + nptxfifosize.d32 = 0; + ptxfifosize.d32 = 0; +#ifdef USE_OTG_MODE + gotgctl.d32 = 0; +#endif + hcfg.d32 = 0; + + + /* configure charge pump IO */ + USB_OTG_BSP_ConfigVBUS(pdev); + + /* Restart the Phy Clock */ + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, 0); + + /* Initialize Host Configuration Register */ + USB_OTG_InitFSLSPClkSel(pdev , HCFG_48_MHZ); /* in init phase */ + + hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); + hcfg.b.fslssupp = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HCFG, hcfg.d32); + + /* Configure data FIFO sizes */ + /* Rx FIFO */ +#ifdef USB_OTG_FS_CORE + if(pdev->cfg.coreID == USB_OTG_FS_CORE_ID) + { + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_FS_SIZE); + nptxfifosize.b.startaddr = RX_FIFO_FS_SIZE; + nptxfifosize.b.depth = TXH_NP_FS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32); + + ptxfifosize.b.startaddr = RX_FIFO_FS_SIZE + TXH_NP_FS_FIFOSIZ; + ptxfifosize.b.depth = TXH_P_FS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->HPTXFSIZ, ptxfifosize.d32); + } +#endif +#ifdef USB_OTG_HS_CORE + if (pdev->cfg.coreID == USB_OTG_HS_CORE_ID) + { + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_HS_SIZE); + nptxfifosize.b.startaddr = RX_FIFO_HS_SIZE; + nptxfifosize.b.depth = TXH_NP_HS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32); + + ptxfifosize.b.startaddr = RX_FIFO_HS_SIZE + TXH_NP_HS_FIFOSIZ; + ptxfifosize.b.depth = TXH_P_HS_FIFOSIZ; + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->HPTXFSIZ, ptxfifosize.d32); + } +#endif + +#ifdef USE_OTG_MODE + /* Clear Host Set HNP Enable in the USB_OTG Control Register */ + gotgctl.b.hstsethnpen = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GOTGCTL, gotgctl.d32, 0); +#endif + + /* Make sure the FIFOs are flushed. */ + USB_OTG_FlushTxFifo(pdev, 0x10 ); /* all Tx FIFOs */ + USB_OTG_FlushRxFifo(pdev); + + + /* Clear all pending HC Interrupts */ + for (i = 0; i < pdev->cfg.host_channels; i++) + { + USB_OTG_WRITE_REG32( &pdev->regs.HC_REGS[i]->HCINT, 0xFFFFFFFF ); + USB_OTG_WRITE_REG32( &pdev->regs.HC_REGS[i]->HCGINTMSK, 0 ); + } +#ifndef USE_OTG_MODE + USB_OTG_DriveVbus(pdev, 1); +#endif + + USB_OTG_EnableHostInt(pdev); + return status; +} + +/** +* @brief USB_OTG_IsEvenFrame +* This function returns the frame number for sof packet +* @param pdev : Selected device +* @retval Frame number +*/ +uint8_t USB_OTG_IsEvenFrame (USB_OTG_CORE_HANDLE *pdev) +{ + return !(USB_OTG_READ_REG32(&pdev->regs.HREGS->HFNUM) & 0x1); +} + +/** +* @brief USB_OTG_DriveVbus : set/reset vbus +* @param pdev : Selected device +* @param state : VBUS state +* @retval None +*/ +void USB_OTG_DriveVbus (USB_OTG_CORE_HANDLE *pdev, uint8_t state) +{ + USB_OTG_HPRT0_TypeDef hprt0; + + hprt0.d32 = 0; + + /* enable disable the external charge pump */ + USB_OTG_BSP_DriveVBUS(pdev, state); + + /* Turn on the Host port power. */ + hprt0.d32 = USB_OTG_ReadHPRT0(pdev); + if ((hprt0.b.prtpwr == 0 ) && (state == 1 )) + { + hprt0.b.prtpwr = 1; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + } + if ((hprt0.b.prtpwr == 1 ) && (state == 0 )) + { + hprt0.b.prtpwr = 0; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + } + + USB_OTG_BSP_mDelay(200); +} +/** +* @brief USB_OTG_EnableHostInt: Enables the Host mode interrupts +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EnableHostInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GINTMSK_TypeDef intmsk; + intmsk.d32 = 0; + /* Disable all interrupts. */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTMSK, 0); + + /* Clear any pending interrupts. */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GINTSTS, 0xFFFFFFFF); + + /* Enable the common interrupts */ + USB_OTG_EnableCommonInt(pdev); + + if (pdev->cfg.dma_enable == 0) + { + intmsk.b.rxstsqlvl = 1; + } + intmsk.b.portintr = 1; + intmsk.b.hcintr = 1; + intmsk.b.disconnect = 1; + intmsk.b.sofintr = 1; + intmsk.b.incomplisoout = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, intmsk.d32, intmsk.d32); + return status; +} + +/** +* @brief USB_OTG_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the +* HCFG register on the PHY type +* @param pdev : Selected device +* @param freq : clock frequency +* @retval None +*/ +void USB_OTG_InitFSLSPClkSel(USB_OTG_CORE_HANDLE *pdev , uint8_t freq) +{ + USB_OTG_HCFG_TypeDef hcfg; + + hcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HCFG); + hcfg.b.fslspclksel = freq; + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HCFG, hcfg.d32); +} + + +/** +* @brief USB_OTG_ReadHPRT0 : Reads HPRT0 to modify later +* @param pdev : Selected device +* @retval HPRT0 value +*/ +uint32_t USB_OTG_ReadHPRT0(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HPRT0_TypeDef hprt0; + + hprt0.d32 = USB_OTG_READ_REG32(pdev->regs.HPRT0); + hprt0.b.prtena = 0; + hprt0.b.prtconndet = 0; + hprt0.b.prtenchng = 0; + hprt0.b.prtovrcurrchng = 0; + return hprt0.d32; +} + + +/** +* @brief USB_OTG_ReadHostAllChannels_intr : Register PCD Callbacks +* @param pdev : Selected device +* @retval Status +*/ +uint32_t USB_OTG_ReadHostAllChannels_intr (USB_OTG_CORE_HANDLE *pdev) +{ + return (USB_OTG_READ_REG32 (&pdev->regs.HREGS->HAINT)); +} + + +/** +* @brief USB_OTG_ResetPort : Reset Host Port +* @param pdev : Selected device +* @retval status +* @note : (1)The application must wait at least 10 ms (+ 10 ms security) +* before clearing the reset bit. +*/ +uint32_t USB_OTG_ResetPort(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HPRT0_TypeDef hprt0; + + hprt0.d32 = USB_OTG_ReadHPRT0(pdev); + hprt0.b.prtrst = 1; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + USB_OTG_BSP_mDelay (10); /* See Note #1 */ + hprt0.b.prtrst = 0; + USB_OTG_WRITE_REG32(pdev->regs.HPRT0, hprt0.d32); + USB_OTG_BSP_mDelay (20); + return 1; +} + + +/** +* @brief USB_OTG_HC_Init : Prepares a host channel for transferring packets +* @param pdev : Selected device +* @param hc_num : channel number +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_HC_Init(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + uint32_t intr_enable = 0; + USB_OTG_HCGINTMSK_TypeDef hcintmsk; + USB_OTG_GINTMSK_TypeDef gintmsk; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCINTn_TypeDef hcint; + + + gintmsk.d32 = 0; + hcintmsk.d32 = 0; + hcchar.d32 = 0; + + /* Clear old interrupt conditions for this host channel. */ + hcint.d32 = 0xFFFFFFFF; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCINT, hcint.d32); + + /* Enable channel interrupts required for this transfer. */ + hcintmsk.d32 = 0; + + if (pdev->cfg.dma_enable == 1) + { + hcintmsk.b.ahberr = 1; + } + + switch (pdev->host.hc[hc_num].ep_type) + { + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + hcintmsk.b.xfercompl = 1; + hcintmsk.b.stall = 1; + hcintmsk.b.xacterr = 1; + hcintmsk.b.datatglerr = 1; + hcintmsk.b.nak = 1; + if (pdev->host.hc[hc_num].ep_is_in) + { + hcintmsk.b.bblerr = 1; + } + else + { + hcintmsk.b.nyet = 1; + if (pdev->host.hc[hc_num].do_ping) + { + hcintmsk.b.ack = 1; + } + } + break; + case EP_TYPE_INTR: + hcintmsk.b.xfercompl = 1; + hcintmsk.b.nak = 1; + hcintmsk.b.stall = 1; + hcintmsk.b.xacterr = 1; + hcintmsk.b.datatglerr = 1; + hcintmsk.b.frmovrun = 1; + + if (pdev->host.hc[hc_num].ep_is_in) + { + hcintmsk.b.bblerr = 1; + } + + break; + case EP_TYPE_ISOC: + hcintmsk.b.xfercompl = 1; + hcintmsk.b.frmovrun = 1; + hcintmsk.b.ack = 1; + + if (pdev->host.hc[hc_num].ep_is_in) + { + hcintmsk.b.xacterr = 1; + hcintmsk.b.bblerr = 1; + } + break; + } + + + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCGINTMSK, hcintmsk.d32); + + + /* Enable the top level host channel interrupt. */ + intr_enable = (1 << hc_num); + USB_OTG_MODIFY_REG32(&pdev->regs.HREGS->HAINTMSK, 0, intr_enable); + + /* Make sure host channel interrupts are enabled. */ + gintmsk.b.hcintr = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.GREGS->GINTMSK, 0, gintmsk.d32); + + /* Program the HCCHAR register */ + hcchar.d32 = 0; + hcchar.b.devaddr = pdev->host.hc[hc_num].dev_addr; + hcchar.b.epnum = pdev->host.hc[hc_num].ep_num; + hcchar.b.epdir = pdev->host.hc[hc_num].ep_is_in; + hcchar.b.lspddev = (pdev->host.hc[hc_num].speed == HPRT0_PRTSPD_LOW_SPEED); + hcchar.b.eptype = pdev->host.hc[hc_num].ep_type; + hcchar.b.mps = pdev->host.hc[hc_num].max_packet; + if (pdev->host.hc[hc_num].ep_type == HCCHAR_INTR) + { + hcchar.b.oddfrm = 1; + } + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + return status; +} + + +/** +* @brief USB_OTG_HC_StartXfer : Start transfer +* @param pdev : Selected device +* @param hc_num : channel number +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_HC_StartXfer(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCTSIZn_TypeDef hctsiz; + USB_OTG_HNPTXSTS_TypeDef hnptxsts; + USB_OTG_HPTXSTS_TypeDef hptxsts; + USB_OTG_GINTMSK_TypeDef intmsk; + uint16_t len_words = 0; + + uint16_t num_packets; + uint16_t max_hc_pkt_count; + + max_hc_pkt_count = 256; + hctsiz.d32 = 0; + hcchar.d32 = 0; + intmsk.d32 = 0; + + /* Compute the expected number of packets associated to the transfer */ + if (pdev->host.hc[hc_num].xfer_len > 0) + { + num_packets = (pdev->host.hc[hc_num].xfer_len + \ + pdev->host.hc[hc_num].max_packet - 1) / pdev->host.hc[hc_num].max_packet; + + if (num_packets > max_hc_pkt_count) + { + num_packets = max_hc_pkt_count; + pdev->host.hc[hc_num].xfer_len = num_packets * \ + pdev->host.hc[hc_num].max_packet; + } + } + else + { + num_packets = 1; + } + if (pdev->host.hc[hc_num].ep_is_in) + { + pdev->host.hc[hc_num].xfer_len = num_packets * \ + pdev->host.hc[hc_num].max_packet; + } + /* Initialize the HCTSIZn register */ + hctsiz.b.xfersize = pdev->host.hc[hc_num].xfer_len; + hctsiz.b.pktcnt = num_packets; + hctsiz.b.pid = pdev->host.hc[hc_num].data_pid; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCTSIZ, hctsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCDMA, (unsigned int)pdev->host.hc[hc_num].xfer_buff); + } + + + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR); + hcchar.b.oddfrm = USB_OTG_IsEvenFrame(pdev); + + /* Set host channel enable */ + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + + if (pdev->cfg.dma_enable == 0) /* Slave mode */ + { + if((pdev->host.hc[hc_num].ep_is_in == 0) && + (pdev->host.hc[hc_num].xfer_len > 0)) + { + switch(pdev->host.hc[hc_num].ep_type) + { + /* Non periodic transfer */ + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + + hnptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS); + len_words = (pdev->host.hc[hc_num].xfer_len + 3) / 4; + + /* check if there is enough space in FIFO space */ + if(len_words > hnptxsts.b.nptxfspcavail) + { + /* need to process data in nptxfempty interrupt */ + intmsk.b.nptxfempty = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, intmsk.d32); + } + + break; + /* Periodic transfer */ + case EP_TYPE_INTR: + case EP_TYPE_ISOC: + hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS); + len_words = (pdev->host.hc[hc_num].xfer_len + 3) / 4; + /* check if there is enough space in FIFO space */ + if(len_words > hptxsts.b.ptxfspcavail) /* split the transfer */ + { + /* need to process data in ptxfempty interrupt */ + intmsk.b.ptxfempty = 1; + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, intmsk.d32); + } + break; + + default: + break; + } + + /* Write packet into the Tx FIFO. */ + USB_OTG_WritePacket(pdev, + pdev->host.hc[hc_num].xfer_buff , + hc_num, pdev->host.hc[hc_num].xfer_len); + } + } + return status; +} + + +/** +* @brief USB_OTG_HC_Halt : Halt channel +* @param pdev : Selected device +* @param hc_num : channel number +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_HC_Halt(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_HNPTXSTS_TypeDef nptxsts; + USB_OTG_HPTXSTS_TypeDef hptxsts; + USB_OTG_HCCHAR_TypeDef hcchar; + + nptxsts.d32 = 0; + hptxsts.d32 = 0; + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR); + hcchar.b.chen = 1; + hcchar.b.chdis = 1; + + /* Check for space in the request queue to issue the halt. */ + if (hcchar.b.eptype == HCCHAR_CTRL || hcchar.b.eptype == HCCHAR_BULK) + { + nptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.GREGS->HNPTXSTS); + if (nptxsts.b.nptxqspcavail == 0) + { + hcchar.b.chen = 0; + } + } + else + { + hptxsts.d32 = USB_OTG_READ_REG32(&pdev->regs.HREGS->HPTXSTS); + if (hptxsts.b.ptxqspcavail == 0) + { + hcchar.b.chen = 0; + } + } + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + return status; +} + +/** +* @brief Issue a ping token +* @param None +* @retval : None +*/ +USB_OTG_STS USB_OTG_HC_DoPing(USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_HCCHAR_TypeDef hcchar; + USB_OTG_HCTSIZn_TypeDef hctsiz; + + hctsiz.d32 = 0; + hctsiz.b.dopng = 1; + hctsiz.b.pktcnt = 1; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCTSIZ, hctsiz.d32); + + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR); + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[hc_num]->HCCHAR, hcchar.d32); + return status; +} + +/** +* @brief Stop the device and clean up fifo's +* @param None +* @retval : None +*/ +void USB_OTG_StopHost(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_HCCHAR_TypeDef hcchar; + uint32_t i; + + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HAINTMSK , 0); + USB_OTG_WRITE_REG32(&pdev->regs.HREGS->HAINT, 0xFFFFFFFF); + /* Flush out any leftover queued requests. */ + + for (i = 0; i < pdev->cfg.host_channels; i++) + { + hcchar.d32 = USB_OTG_READ_REG32(&pdev->regs.HC_REGS[i]->HCCHAR); + hcchar.b.chen = 0; + hcchar.b.chdis = 1; + hcchar.b.epdir = 0; + USB_OTG_WRITE_REG32(&pdev->regs.HC_REGS[i]->HCCHAR, hcchar.d32); + } + + /* Flush the FIFO */ + USB_OTG_FlushRxFifo(pdev); + USB_OTG_FlushTxFifo(pdev , 0x10 ); +} +#endif +#ifdef USE_DEVICE_MODE +/* PCD Core Layer */ + +/** +* @brief USB_OTG_InitDevSpeed :Initializes the DevSpd field of DCFG register +* depending the PHY type and the enumeration speed of the device. +* @param pdev : Selected device +* @retval : None +*/ +void USB_OTG_InitDevSpeed(USB_OTG_CORE_HANDLE *pdev , uint8_t speed) +{ + USB_OTG_DCFG_TypeDef dcfg; + + dcfg.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCFG); + dcfg.b.devspd = speed; + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCFG, dcfg.d32); +} + + +/** +* @brief USB_OTG_CoreInitDev : Initializes the USB_OTG controller registers +* for device mode +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_CoreInitDev (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + uint32_t i; + USB_OTG_DCFG_TypeDef dcfg; + USB_OTG_FSIZ_TypeDef nptxfifosize; + USB_OTG_FSIZ_TypeDef txfifosize; + USB_OTG_DIEPMSK_TypeDef msk; + USB_OTG_DTHRCTL_TypeDef dthrctl; + + depctl.d32 = 0; + dcfg.d32 = 0; + nptxfifosize.d32 = 0; + txfifosize.d32 = 0; + msk.d32 = 0; + + /* Restart the Phy Clock */ + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, 0); + /* Device configuration register */ + dcfg.d32 = USB_OTG_READ_REG32( &pdev->regs.DREGS->DCFG); + dcfg.b.perfrint = DCFG_FRAME_INTERVAL_80; + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DCFG, dcfg.d32 ); + +#ifdef USB_OTG_FS_CORE + if(pdev->cfg.coreID == USB_OTG_FS_CORE_ID ) + { + + /* Set Full speed phy */ + USB_OTG_InitDevSpeed (pdev , USB_OTG_SPEED_PARAM_FULL); + + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_FS_SIZE); + + /* EP0 TX*/ + nptxfifosize.b.depth = TX0_FIFO_FS_SIZE; + nptxfifosize.b.startaddr = RX_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32 ); + + + /* EP1 TX*/ + txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth; + txfifosize.b.depth = TX1_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[0], txfifosize.d32 ); + + + /* EP2 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX2_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[1], txfifosize.d32 ); + + + /* EP3 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX3_FIFO_FS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[2], txfifosize.d32 ); + } +#endif +#ifdef USB_OTG_HS_CORE + if(pdev->cfg.coreID == USB_OTG_HS_CORE_ID ) + { + + /* Set High speed phy */ + + if(pdev->cfg.phy_itface == USB_OTG_ULPI_PHY) + { + USB_OTG_InitDevSpeed (pdev , USB_OTG_SPEED_PARAM_HIGH); + } + else /* set High speed phy in Full speed mode */ + { + USB_OTG_InitDevSpeed (pdev , USB_OTG_SPEED_PARAM_HIGH_IN_FULL); + } + + /* set Rx FIFO size */ + USB_OTG_WRITE_REG32(&pdev->regs.GREGS->GRXFSIZ, RX_FIFO_HS_SIZE); + + /* EP0 TX*/ + nptxfifosize.b.depth = TX0_FIFO_HS_SIZE; + nptxfifosize.b.startaddr = RX_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF0_HNPTXFSIZ, nptxfifosize.d32 ); + + + /* EP1 TX*/ + txfifosize.b.startaddr = nptxfifosize.b.startaddr + nptxfifosize.b.depth; + txfifosize.b.depth = TX1_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[0], txfifosize.d32 ); + + + /* EP2 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX2_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[1], txfifosize.d32 ); + + + /* EP3 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX3_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[2], txfifosize.d32 ); + + /* EP4 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX4_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[3], txfifosize.d32 ); + + + /* EP5 TX*/ + txfifosize.b.startaddr += txfifosize.b.depth; + txfifosize.b.depth = TX5_FIFO_HS_SIZE; + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->DIEPTXF[4], txfifosize.d32 ); + } +#endif + /* Flush the FIFOs */ + USB_OTG_FlushTxFifo(pdev , 0x10); /* all Tx FIFOs */ + USB_OTG_FlushRxFifo(pdev); + /* Clear all pending Device Interrupts */ + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DIEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DOEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINT, 0xFFFFFFFF ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINTMSK, 0 ); + + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + depctl.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[i]->DIEPCTL); + if (depctl.b.epena) + { + depctl.d32 = 0; + depctl.b.epdis = 1; + depctl.b.snak = 1; + } + else + { + depctl.d32 = 0; + } + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPCTL, depctl.d32); + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPTSIZ, 0); + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPINT, 0xFF); + } + for (i = 0; i < pdev->cfg.dev_endpoints; i++) + { + USB_OTG_DEPCTL_TypeDef depctl; + depctl.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[i]->DOEPCTL); + if (depctl.b.epena) + { + depctl.d32 = 0; + depctl.b.epdis = 1; + depctl.b.snak = 1; + } + else + { + depctl.d32 = 0; + } + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPCTL, depctl.d32); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPTSIZ, 0); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPINT, 0xFF); + } + msk.d32 = 0; + msk.b.txfifoundrn = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPMSK, msk.d32, msk.d32); + + if (pdev->cfg.dma_enable == 1) + { + dthrctl.d32 = 0; + dthrctl.b.non_iso_thr_en = 1; + dthrctl.b.iso_thr_en = 1; + dthrctl.b.tx_thr_len = 64; + dthrctl.b.rx_thr_en = 1; + dthrctl.b.rx_thr_len = 64; + USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DTHRCTL, dthrctl.d32); + } + USB_OTG_EnableDevInt(pdev); + return status; +} + + +/** +* @brief USB_OTG_EnableDevInt : Enables the Device mode interrupts +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EnableDevInt(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_GINTMSK_TypeDef intmsk; + + intmsk.d32 = 0; + + /* Disable all interrupts. */ + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTMSK, 0); + /* Clear any pending interrupts */ + USB_OTG_WRITE_REG32( &pdev->regs.GREGS->GINTSTS, 0xFFFFFFFF); + /* Enable the common interrupts */ + USB_OTG_EnableCommonInt(pdev); + + if (pdev->cfg.dma_enable == 0) + { + intmsk.b.rxstsqlvl = 1; + } + + /* Enable interrupts matching to the Device mode ONLY */ + intmsk.b.usbsuspend = 1; + intmsk.b.usbreset = 1; + intmsk.b.enumdone = 1; + intmsk.b.inepintr = 1; + intmsk.b.outepintr = 1; + intmsk.b.sofintr = 1; + + intmsk.b.incomplisoin = 1; + intmsk.b.incomplisoout = 1; +#ifdef VBUS_SENSING_ENABLED + intmsk.b.sessreqintr = 1; + intmsk.b.otgintr = 1; +#endif + USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, intmsk.d32, intmsk.d32); + return status; +} + + +/** +* @brief USB_OTG_GetDeviceSpeed +* Get the device speed from the device status register +* @param None +* @retval status +*/ +enum USB_OTG_SPEED USB_OTG_GetDeviceSpeed (USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_DSTS_TypeDef dsts; + enum USB_OTG_SPEED speed = USB_SPEED_UNKNOWN; + + + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + switch (dsts.b.enumspd) + { + case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: + speed = USB_SPEED_HIGH; + break; + case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: + case DSTS_ENUMSPD_FS_PHY_48MHZ: + speed = USB_SPEED_FULL; + break; + + case DSTS_ENUMSPD_LS_PHY_6MHZ: + speed = USB_SPEED_LOW; + break; + } + + return speed; +} +/** +* @brief enables EP0 OUT to receive SETUP packets and configures EP0 +* for transmitting packets +* @param None +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EP0Activate(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DSTS_TypeDef dsts; + USB_OTG_DEPCTL_TypeDef diepctl; + USB_OTG_DCTL_TypeDef dctl; + + dctl.d32 = 0; + /* Read the Device Status and Endpoint 0 Control registers */ + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + diepctl.d32 = USB_OTG_READ_REG32(&pdev->regs.INEP_REGS[0]->DIEPCTL); + /* Set the MPS of the IN EP based on the enumeration speed */ + switch (dsts.b.enumspd) + { + case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: + case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: + case DSTS_ENUMSPD_FS_PHY_48MHZ: + diepctl.b.mps = DEP0CTL_MPS_64; + break; + case DSTS_ENUMSPD_LS_PHY_6MHZ: + diepctl.b.mps = DEP0CTL_MPS_8; + break; + } + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[0]->DIEPCTL, diepctl.d32); + dctl.b.cgnpinnak = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, dctl.d32); + return status; +} + + +/** +* @brief USB_OTG_EPActivate : Activates an EP +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPActivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DAINT_TypeDef daintmsk; + __IO uint32_t *addr; + + + depctl.d32 = 0; + daintmsk.d32 = 0; + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL; + daintmsk.ep.in = 1 << ep->num; + } + else + { + addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL; + daintmsk.ep.out = 1 << ep->num; + } + /* If the EP is already active don't change the EP Control + * register. */ + depctl.d32 = USB_OTG_READ_REG32(addr); + if (!depctl.b.usbactep) + { + depctl.b.mps = ep->maxpacket; + depctl.b.eptype = ep->type; + depctl.b.txfnum = ep->tx_fifo_num; + depctl.b.setd0pid = 1; + depctl.b.usbactep = 1; + USB_OTG_WRITE_REG32(addr, depctl.d32); + } + /* Enable the Interrupt for this EP */ +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + if((ep->num == 1)&&(pdev->cfg.coreID == USB_OTG_HS_CORE_ID)) + { + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DEACHMSK, 0, daintmsk.d32); + } + else +#endif + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, 0, daintmsk.d32); + return status; +} + + +/** +* @brief USB_OTG_EPDeactivate : Deactivates an EP +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPDeactivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DAINT_TypeDef daintmsk; + __IO uint32_t *addr; + + depctl.d32 = 0; + daintmsk.d32 = 0; + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL; + daintmsk.ep.in = 1 << ep->num; + } + else + { + addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL; + daintmsk.ep.out = 1 << ep->num; + } + depctl.b.usbactep = 0; + USB_OTG_WRITE_REG32(addr, depctl.d32); + /* Disable the Interrupt for this EP */ + +#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED + if((ep->num == 1)&&(pdev->cfg.coreID == USB_OTG_HS_CORE_ID)) + { + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DEACHMSK, daintmsk.d32, 0); + } + else +#endif + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, daintmsk.d32, 0); + return status; +} + + +/** +* @brief USB_OTG_EPStartXfer : Handle the setup for data xfer for an EP and +* starts the xfer +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPStartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DEPXFRSIZ_TypeDef deptsiz; + USB_OTG_DSTS_TypeDef dsts; + uint32_t fifoemptymsk = 0; + + depctl.d32 = 0; + deptsiz.d32 = 0; + /* IN endpoint */ + if (ep->is_in == 1) + { + depctl.d32 = USB_OTG_READ_REG32(&(pdev->regs.INEP_REGS[ep->num]->DIEPCTL)); + deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ)); + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = 0; + deptsiz.b.pktcnt = 1; + } + else + { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + deptsiz.b.xfersize = ep->xfer_len; + deptsiz.b.pktcnt = (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; + + if (ep->type == EP_TYPE_ISOC) + { + deptsiz.b.mc = 1; + } + } + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ, deptsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPDMA, ep->dma_addr); + } + else + { + if (ep->type != EP_TYPE_ISOC) + { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + fifoemptymsk = 1 << ep->num; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, 0, fifoemptymsk); + } + } + } + + + if (ep->type == EP_TYPE_ISOC) + { + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + if (((dsts.b.soffn)&0x1) == 0) + { + depctl.b.setd1pid = 1; + } + else + { + depctl.b.setd0pid = 1; + } + } + + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPCTL, depctl.d32); + + if (ep->type == EP_TYPE_ISOC) + { + USB_OTG_WritePacket(pdev, ep->xfer_buff, ep->num, ep->xfer_len); + } + } + else + { + /* OUT endpoint */ + depctl.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL)); + deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ)); + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + } + else + { + deptsiz.b.pktcnt = (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; + } + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ, deptsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPDMA, ep->dma_addr); + } + + if (ep->type == EP_TYPE_ISOC) + { + if (ep->even_odd_frame) + { + depctl.b.setd1pid = 1; + } + else + { + depctl.b.setd0pid = 1; + } + } + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL, depctl.d32); + } + return status; +} + + +/** +* @brief USB_OTG_EP0StartXfer : Handle the setup for a data xfer for EP0 and +* starts the xfer +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EP0StartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + USB_OTG_DEP0XFRSIZ_TypeDef deptsiz; + USB_OTG_INEPREGS *in_regs; + uint32_t fifoemptymsk = 0; + + depctl.d32 = 0; + deptsiz.d32 = 0; + /* IN endpoint */ + if (ep->is_in == 1) + { + in_regs = pdev->regs.INEP_REGS[0]; + depctl.d32 = USB_OTG_READ_REG32(&in_regs->DIEPCTL); + deptsiz.d32 = USB_OTG_READ_REG32(&in_regs->DIEPTSIZ); + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = 0; + deptsiz.b.pktcnt = 1; + + } + else + { + if (ep->xfer_len > ep->maxpacket) + { + ep->xfer_len = ep->maxpacket; + deptsiz.b.xfersize = ep->maxpacket; + } + else + { + deptsiz.b.xfersize = ep->xfer_len; + } + deptsiz.b.pktcnt = 1; + } + USB_OTG_WRITE_REG32(&in_regs->DIEPTSIZ, deptsiz.d32); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPDMA, ep->dma_addr); + } + + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32(&in_regs->DIEPCTL, depctl.d32); + + + + if (pdev->cfg.dma_enable == 0) + { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + { + fifoemptymsk |= 1 << ep->num; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, 0, fifoemptymsk); + } + } + } + } + else + { + /* OUT endpoint */ + depctl.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + deptsiz.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ); + /* Program the transfer size and packet count as follows: + * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) + * pktcnt = N */ + if (ep->xfer_len == 0) + { + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + } + else + { + ep->xfer_len = ep->maxpacket; + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + } + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ, deptsiz.d32); + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPDMA, ep->dma_addr); + } + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + USB_OTG_WRITE_REG32 (&(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL), depctl.d32); + + } + return status; +} + + +/** +* @brief USB_OTG_EPSetStall : Set the EP STALL +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPSetStall(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + + depctl.d32 = 0; + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + /* set the disable and stall bits */ + if (depctl.b.epena) + { + depctl.b.epdis = 1; + } + depctl.b.stall = 1; + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); + } + else + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + /* set the stall bit */ + depctl.b.stall = 1; + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); + } + return status; +} + + +/** +* @brief Clear the EP STALL +* @param pdev : Selected device +* @retval USB_OTG_STS : status +*/ +USB_OTG_STS USB_OTG_EPClearStall(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep) +{ + USB_OTG_STS status = USB_OTG_OK; + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + + depctl.d32 = 0; + + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + } + else + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + } + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + /* clear the stall bits */ + depctl.b.stall = 0; + if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) + { + depctl.b.setd0pid = 1; /* DATA0 */ + } + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); + return status; +} + + +/** +* @brief USB_OTG_ReadDevAllOutEp_itr : returns OUT endpoint interrupt bits +* @param pdev : Selected device +* @retval OUT endpoint interrupt bits +*/ +uint32_t USB_OTG_ReadDevAllOutEp_itr(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t v; + v = USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINT); + v &= USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINTMSK); + return ((v & 0xffff0000) >> 16); +} + + +/** +* @brief USB_OTG_ReadDevOutEP_itr : returns Device OUT EP Interrupt register +* @param pdev : Selected device +* @param ep : end point number +* @retval Device OUT EP Interrupt register +*/ +uint32_t USB_OTG_ReadDevOutEP_itr(USB_OTG_CORE_HANDLE *pdev , uint8_t epnum) +{ + uint32_t v; + v = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[epnum]->DOEPINT); + v &= USB_OTG_READ_REG32(&pdev->regs.DREGS->DOEPMSK); + return v; +} + + +/** +* @brief USB_OTG_ReadDevAllInEPItr : Get int status register +* @param pdev : Selected device +* @retval int status register +*/ +uint32_t USB_OTG_ReadDevAllInEPItr(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t v; + v = USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINT); + v &= USB_OTG_READ_REG32(&pdev->regs.DREGS->DAINTMSK); + return (v & 0xffff); +} + +/** +* @brief configures EPO to receive SETUP packets +* @param None +* @retval : None +*/ +void USB_OTG_EP0_OutStart(USB_OTG_CORE_HANDLE *pdev) +{ + USB_OTG_DEP0XFRSIZ_TypeDef doeptsize0; + doeptsize0.d32 = 0; + doeptsize0.b.supcnt = 3; + doeptsize0.b.pktcnt = 1; + doeptsize0.b.xfersize = 8 * 3; + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[0]->DOEPTSIZ, doeptsize0.d32 ); + + if (pdev->cfg.dma_enable == 1) + { + USB_OTG_DEPCTL_TypeDef doepctl; + doepctl.d32 = 0; + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[0]->DOEPDMA, + (uint32_t)&pdev->dev.setup_packet); + + /* EP enable */ + doepctl.d32 = USB_OTG_READ_REG32(&pdev->regs.OUTEP_REGS[0]->DOEPCTL); + doepctl.b.epena = 1; + doepctl.d32 = 0x80008000; + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[0]->DOEPCTL, doepctl.d32); + } +} + +/** +* @brief USB_OTG_RemoteWakeup : active remote wakeup signalling +* @param None +* @retval : None +*/ +void USB_OTG_ActiveRemoteWakeup(USB_OTG_CORE_HANDLE *pdev) +{ + + USB_OTG_DCTL_TypeDef dctl; + USB_OTG_DSTS_TypeDef dsts; + USB_OTG_PCGCCTL_TypeDef power; + + if (pdev->dev.DevRemoteWakeup) + { + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + if(dsts.b.suspsts == 1) + { + if(pdev->cfg.low_power) + { + /* un-gate USB Core clock */ + power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL); + power.b.gatehclk = 0; + power.b.stoppclk = 0; + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32); + } + /* active Remote wakeup signaling */ + dctl.d32 = 0; + dctl.b.rmtwkupsig = 1; + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, 0, dctl.d32); + USB_OTG_BSP_mDelay(5); + USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DCTL, dctl.d32, 0 ); + } + } +} + + +/** +* @brief USB_OTG_UngateClock : active USB Core clock +* @param None +* @retval : None +*/ +void USB_OTG_UngateClock(USB_OTG_CORE_HANDLE *pdev) +{ + if(pdev->cfg.low_power) + { + + USB_OTG_DSTS_TypeDef dsts; + USB_OTG_PCGCCTL_TypeDef power; + + dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS); + + if(dsts.b.suspsts == 1) + { + /* un-gate USB Core clock */ + power.d32 = USB_OTG_READ_REG32(&pdev->regs.PCGCCTL); + power.b.gatehclk = 0; + power.b.stoppclk = 0; + USB_OTG_WRITE_REG32(pdev->regs.PCGCCTL, power.d32); + + } + } +} + +/** +* @brief Stop the device and clean up fifo's +* @param None +* @retval : None +*/ +void USB_OTG_StopDevice(USB_OTG_CORE_HANDLE *pdev) +{ + uint32_t i; + + pdev->dev.device_status = 1; + + for (i = 0; i < pdev->cfg.dev_endpoints ; i++) + { + USB_OTG_WRITE_REG32( &pdev->regs.INEP_REGS[i]->DIEPINT, 0xFF); + USB_OTG_WRITE_REG32( &pdev->regs.OUTEP_REGS[i]->DOEPINT, 0xFF); + } + + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DIEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DOEPMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINTMSK, 0 ); + USB_OTG_WRITE_REG32( &pdev->regs.DREGS->DAINT, 0xFFFFFFFF ); + + /* Flush the FIFO */ + USB_OTG_FlushRxFifo(pdev); + USB_OTG_FlushTxFifo(pdev , 0x10 ); +} + +/** +* @brief returns the EP Status +* @param pdev : Selected device +* ep : endpoint structure +* @retval : EP status +*/ + +uint32_t USB_OTG_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,USB_OTG_EP *ep) +{ + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + uint32_t Status = 0; + + depctl.d32 = 0; + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + + if (depctl.b.stall == 1) + Status = USB_OTG_EP_TX_STALL; + else if (depctl.b.naksts == 1) + Status = USB_OTG_EP_TX_NAK; + else + Status = USB_OTG_EP_TX_VALID; + + } + else + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + if (depctl.b.stall == 1) + Status = USB_OTG_EP_RX_STALL; + else if (depctl.b.naksts == 1) + Status = USB_OTG_EP_RX_NAK; + else + Status = USB_OTG_EP_RX_VALID; + } + + /* Return the current status */ + return Status; +} + +/** +* @brief Set the EP Status +* @param pdev : Selected device +* Status : new Status +* ep : EP structure +* @retval : None +*/ +void USB_OTG_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep , uint32_t Status) +{ + USB_OTG_DEPCTL_TypeDef depctl; + __IO uint32_t *depctl_addr; + + depctl.d32 = 0; + + /* Process for IN endpoint */ + if (ep->is_in == 1) + { + depctl_addr = &(pdev->regs.INEP_REGS[ep->num]->DIEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + + if (Status == USB_OTG_EP_TX_STALL) + { + USB_OTG_EPSetStall(pdev, ep); return; + } + else if (Status == USB_OTG_EP_TX_NAK) + depctl.b.snak = 1; + else if (Status == USB_OTG_EP_TX_VALID) + { + if (depctl.b.stall == 1) + { + ep->even_odd_frame = 0; + USB_OTG_EPClearStall(pdev, ep); + return; + } + depctl.b.cnak = 1; + depctl.b.usbactep = 1; + depctl.b.epena = 1; + } + else if (Status == USB_OTG_EP_TX_DIS) + depctl.b.usbactep = 0; + } + else /* Process for OUT endpoint */ + { + depctl_addr = &(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL); + depctl.d32 = USB_OTG_READ_REG32(depctl_addr); + + if (Status == USB_OTG_EP_RX_STALL) { + depctl.b.stall = 1; + } + else if (Status == USB_OTG_EP_RX_NAK) + depctl.b.snak = 1; + else if (Status == USB_OTG_EP_RX_VALID) + { + if (depctl.b.stall == 1) + { + ep->even_odd_frame = 0; + USB_OTG_EPClearStall(pdev, ep); + return; + } + depctl.b.cnak = 1; + depctl.b.usbactep = 1; + depctl.b.epena = 1; + } + else if (Status == USB_OTG_EP_RX_DIS) + { + depctl.b.usbactep = 0; + } + } + + USB_OTG_WRITE_REG32(depctl_addr, depctl.d32); +} + +#endif +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/usb_core.h b/exampleF4/Projects/discovery_demo/usb_core.h new file mode 100644 index 0000000..82a09e1 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usb_core.h @@ -0,0 +1,408 @@ +/** + ****************************************************************************** + * @file usb_core.h + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief Header of the Core Layer + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CORE_H__ +#define __USB_CORE_H__ + +/* Includes ------------------------------------------------------------------*/ +#include "usb_conf.h" +#include "usb_regs.h" +#include "usb_defines.h" + + +/** @addtogroup USB_OTG_DRIVER + * @{ + */ + +/** @defgroup USB_CORE + * @brief usb otg driver core layer + * @{ + */ + + +/** @defgroup USB_CORE_Exported_Defines + * @{ + */ + +#define USB_OTG_EP0_IDLE 0 +#define USB_OTG_EP0_SETUP 1 +#define USB_OTG_EP0_DATA_IN 2 +#define USB_OTG_EP0_DATA_OUT 3 +#define USB_OTG_EP0_STATUS_IN 4 +#define USB_OTG_EP0_STATUS_OUT 5 +#define USB_OTG_EP0_STALL 6 + +#define USB_OTG_EP_TX_DIS 0x0000 +#define USB_OTG_EP_TX_STALL 0x0010 +#define USB_OTG_EP_TX_NAK 0x0020 +#define USB_OTG_EP_TX_VALID 0x0030 + +#define USB_OTG_EP_RX_DIS 0x0000 +#define USB_OTG_EP_RX_STALL 0x1000 +#define USB_OTG_EP_RX_NAK 0x2000 +#define USB_OTG_EP_RX_VALID 0x3000 +/** + * @} + */ +#define MAX_DATA_LENGTH 0xFF + +/** @defgroup USB_CORE_Exported_Types + * @{ + */ + + +typedef enum { + USB_OTG_OK = 0, + USB_OTG_FAIL +}USB_OTG_STS; + +typedef enum { + HC_IDLE = 0, + HC_XFRC, + HC_HALTED, + HC_NAK, + HC_NYET, + HC_STALL, + HC_XACTERR, + HC_BBLERR, + HC_DATATGLERR, +}HC_STATUS; + +typedef enum { + URB_IDLE = 0, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL +}URB_STATE; + +typedef enum { + CTRL_START = 0, + CTRL_XFRC, + CTRL_HALTED, + CTRL_NAK, + CTRL_STALL, + CTRL_XACTERR, + CTRL_BBLERR, + CTRL_DATATGLERR, + CTRL_FAIL +}CTRL_STATUS; + + +typedef struct USB_OTG_hc +{ + uint8_t dev_addr ; + uint8_t ep_num; + uint8_t ep_is_in; + uint8_t speed; + uint8_t do_ping; + uint8_t ep_type; + uint16_t max_packet; + uint8_t data_pid; + uint8_t *xfer_buff; + uint32_t xfer_len; + uint32_t xfer_count; + uint8_t toggle_in; + uint8_t toggle_out; + uint32_t dma_addr; +} +USB_OTG_HC , *PUSB_OTG_HC; + +typedef struct USB_OTG_ep +{ + uint8_t num; + uint8_t is_in; + uint8_t is_stall; + uint8_t type; + uint8_t data_pid_start; + uint8_t even_odd_frame; + uint16_t tx_fifo_num; + uint32_t maxpacket; + /* transaction level variables*/ + uint8_t *xfer_buff; + uint32_t dma_addr; + uint32_t xfer_len; + uint32_t xfer_count; + /* Transfer level variables*/ + uint32_t rem_data_len; + uint32_t total_data_len; + uint32_t ctl_data_len; + +} + +USB_OTG_EP , *PUSB_OTG_EP; + + + +typedef struct USB_OTG_core_cfg +{ + uint8_t host_channels; + uint8_t dev_endpoints; + uint8_t speed; + uint8_t dma_enable; + uint16_t mps; + uint16_t TotalFifoSize; + uint8_t phy_itface; + uint8_t Sof_output; + uint8_t low_power; + uint8_t coreID; + +} +USB_OTG_CORE_CFGS, *PUSB_OTG_CORE_CFGS; + + + +typedef struct usb_setup_req { + + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USB_SETUP_REQ; + +typedef struct _Device_TypeDef +{ + uint8_t *(*GetDeviceDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetLangIDStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetManufacturerStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetProductStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetSerialStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetConfigurationStrDescriptor)( uint8_t speed , uint16_t *length); + uint8_t *(*GetInterfaceStrDescriptor)( uint8_t speed , uint16_t *length); +} USBD_DEVICE, *pUSBD_DEVICE; + +typedef struct USB_OTG_hPort +{ + void (*Disconnect) (void *phost); + void (*Connect) (void *phost); + uint8_t ConnStatus; + uint8_t DisconnStatus; + uint8_t ConnHandled; + uint8_t DisconnHandled; +} USB_OTG_hPort_TypeDef; + +typedef struct _Device_cb +{ + uint8_t (*Init) (void *pdev , uint8_t cfgidx); + uint8_t (*DeInit) (void *pdev , uint8_t cfgidx); + /* Control Endpoints*/ + uint8_t (*Setup) (void *pdev , USB_SETUP_REQ *req); + uint8_t (*EP0_TxSent) (void *pdev ); + uint8_t (*EP0_RxReady) (void *pdev ); + /* Class Specific Endpoints*/ + uint8_t (*DataIn) (void *pdev , uint8_t epnum); + uint8_t (*DataOut) (void *pdev , uint8_t epnum); + uint8_t (*SOF) (void *pdev); + uint8_t (*IsoINIncomplete) (void *pdev); + uint8_t (*IsoOUTIncomplete) (void *pdev); + + uint8_t *(*GetConfigDescriptor)( uint8_t speed , uint16_t *length); +#ifdef USB_OTG_HS_CORE + uint8_t *(*GetOtherConfigDescriptor)( uint8_t speed , uint16_t *length); +#endif + +#ifdef USB_SUPPORT_USER_STRING_DESC + uint8_t *(*GetUsrStrDescriptor)( uint8_t speed ,uint8_t index, uint16_t *length); +#endif + +} USBD_Class_cb_TypeDef; + + + +typedef struct _USBD_USR_PROP +{ + void (*Init)(void); + void (*DeviceReset)(uint8_t speed); + void (*DeviceConfigured)(void); + void (*DeviceSuspended)(void); + void (*DeviceResumed)(void); + + void (*DeviceConnected)(void); + void (*DeviceDisconnected)(void); + +} +USBD_Usr_cb_TypeDef; + +typedef struct _DCD +{ + uint8_t device_config; + uint8_t device_state; + uint8_t device_status; + uint8_t device_address; + uint32_t DevRemoteWakeup; + USB_OTG_EP in_ep [USB_OTG_MAX_TX_FIFOS]; + USB_OTG_EP out_ep [USB_OTG_MAX_TX_FIFOS]; + uint8_t setup_packet [8*3]; + USBD_Class_cb_TypeDef *class_cb; + USBD_Usr_cb_TypeDef *usr_cb; + USBD_DEVICE *usr_device; + uint8_t *pConfig_descriptor; + } +DCD_DEV , *DCD_PDEV; + + +typedef struct _HCD +{ + uint8_t Rx_Buffer [MAX_DATA_LENGTH]; + __IO uint32_t ConnSts; + __IO uint32_t ErrCnt[USB_OTG_MAX_TX_FIFOS]; + __IO uint32_t XferCnt[USB_OTG_MAX_TX_FIFOS]; + __IO HC_STATUS HC_Status[USB_OTG_MAX_TX_FIFOS]; + __IO URB_STATE URB_State[USB_OTG_MAX_TX_FIFOS]; + USB_OTG_HC hc [USB_OTG_MAX_TX_FIFOS]; + uint16_t channel [USB_OTG_MAX_TX_FIFOS]; + USB_OTG_hPort_TypeDef *port_cb; +} +HCD_DEV , *USB_OTG_USBH_PDEV; + + +typedef struct _OTG +{ + uint8_t OTG_State; + uint8_t OTG_PrevState; + uint8_t OTG_Mode; +} +OTG_DEV , *USB_OTG_USBO_PDEV; + +typedef struct USB_OTG_handle +{ + USB_OTG_CORE_CFGS cfg; + USB_OTG_CORE_REGS regs; +#ifdef USE_DEVICE_MODE + DCD_DEV dev; +#endif +#ifdef USE_HOST_MODE + HCD_DEV host; +#endif +#ifdef USE_OTG_MODE + OTG_DEV otg; +#endif +} +USB_OTG_CORE_HANDLE , *PUSB_OTG_CORE_HANDLE; + +/** + * @} + */ + + +/** @defgroup USB_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_FunctionsPrototype + * @{ + */ + + +USB_OTG_STS USB_OTG_CoreInit (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_SelectCore (USB_OTG_CORE_HANDLE *pdev, + USB_OTG_CORE_ID_TypeDef coreID); +USB_OTG_STS USB_OTG_EnableGlobalInt (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_DisableGlobalInt(USB_OTG_CORE_HANDLE *pdev); +void* USB_OTG_ReadPacket (USB_OTG_CORE_HANDLE *pdev , + uint8_t *dest, + uint16_t len); +USB_OTG_STS USB_OTG_WritePacket (USB_OTG_CORE_HANDLE *pdev , + uint8_t *src, + uint8_t ch_ep_num, + uint16_t len); +USB_OTG_STS USB_OTG_FlushTxFifo (USB_OTG_CORE_HANDLE *pdev , uint32_t num); +USB_OTG_STS USB_OTG_FlushRxFifo (USB_OTG_CORE_HANDLE *pdev); + +uint32_t USB_OTG_ReadCoreItr (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadOtgItr (USB_OTG_CORE_HANDLE *pdev); +uint8_t USB_OTG_IsHostMode (USB_OTG_CORE_HANDLE *pdev); +uint8_t USB_OTG_IsDeviceMode (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_GetMode (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_PhyInit (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_SetCurrentMode (USB_OTG_CORE_HANDLE *pdev, + uint8_t mode); + +/*********************** HOST APIs ********************************************/ +#ifdef USE_HOST_MODE +USB_OTG_STS USB_OTG_CoreInitHost (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EnableHostInt (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_HC_Init (USB_OTG_CORE_HANDLE *pdev, uint8_t hc_num); +USB_OTG_STS USB_OTG_HC_Halt (USB_OTG_CORE_HANDLE *pdev, uint8_t hc_num); +USB_OTG_STS USB_OTG_HC_StartXfer (USB_OTG_CORE_HANDLE *pdev, uint8_t hc_num); +USB_OTG_STS USB_OTG_HC_DoPing (USB_OTG_CORE_HANDLE *pdev , uint8_t hc_num); +uint32_t USB_OTG_ReadHostAllChannels_intr (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ResetPort (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadHPRT0 (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_DriveVbus (USB_OTG_CORE_HANDLE *pdev, uint8_t state); +void USB_OTG_InitFSLSPClkSel (USB_OTG_CORE_HANDLE *pdev ,uint8_t freq); +uint8_t USB_OTG_IsEvenFrame (USB_OTG_CORE_HANDLE *pdev) ; +void USB_OTG_StopHost (USB_OTG_CORE_HANDLE *pdev); +#endif +/********************* DEVICE APIs ********************************************/ +#ifdef USE_DEVICE_MODE +USB_OTG_STS USB_OTG_CoreInitDev (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EnableDevInt (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadDevAllInEPItr (USB_OTG_CORE_HANDLE *pdev); +enum USB_OTG_SPEED USB_OTG_GetDeviceSpeed (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EP0Activate (USB_OTG_CORE_HANDLE *pdev); +USB_OTG_STS USB_OTG_EPActivate (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPDeactivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPStartXfer (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EP0StartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPSetStall (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +USB_OTG_STS USB_OTG_EPClearStall (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep); +uint32_t USB_OTG_ReadDevAllOutEp_itr (USB_OTG_CORE_HANDLE *pdev); +uint32_t USB_OTG_ReadDevOutEP_itr (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum); +uint32_t USB_OTG_ReadDevAllInEPItr (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_InitDevSpeed (USB_OTG_CORE_HANDLE *pdev , uint8_t speed); +uint8_t USBH_IsEvenFrame (USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_EP0_OutStart(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_ActiveRemoteWakeup(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_UngateClock(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_StopDevice(USB_OTG_CORE_HANDLE *pdev); +void USB_OTG_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep , uint32_t Status); +uint32_t USB_OTG_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,USB_OTG_EP *ep); +#endif +/** + * @} + */ + +#endif /* __USB_CORE_H__ */ + + +/** + * @} + */ + +/** + * @} + */ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/exampleF4/Projects/discovery_demo/usbd_conf.h b/exampleF4/Projects/discovery_demo/usbd_conf.h new file mode 100644 index 0000000..3ff02b6 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usbd_conf.h @@ -0,0 +1,93 @@ +/** + ****************************************************************************** + * @file usbd_conf.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief USB Device configuration file + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4_discovery.h" + +/** @defgroup USB_CONF_Exported_Defines + * @{ + */ + + +#define USBD_CFG_MAX_NUM 1 +#define USBD_ITF_MAX_NUM 1 + +#define USB_MAX_STR_DESC_SIZ 64 + + + +#define USBD_DYNAMIC_DESCRIPTOR_CHANGE_ENABLED + +/** @defgroup USB_String_Descriptors + * @{ + */ + + +/** @defgroup USB_HID_Class_Layer_Parameter + * @{ + */ +#define HID_IN_EP 0x81 +#define HID_OUT_EP 0x01 + +#define HID_IN_PACKET 4 +#define HID_OUT_PACKET 4 + +/** + * @} + */ +/** @defgroup USB_CONF_Exported_Types + * @{ + */ +/** + * @} + */ + + +/** @defgroup USB_CONF_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USB_CONF_Exported_FunctionsPrototype + * @{ + */ +/** + * @} + */ + + +#endif //__USBD_CONF__H__ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/exampleF4/Projects/discovery_demo/usbd_desc.c b/exampleF4/Projects/discovery_demo/usbd_desc.c new file mode 100644 index 0000000..ff9b670 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usbd_desc.c @@ -0,0 +1,313 @@ +/** + ****************************************************************************** + * @file usbd_desc.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file provides the USBD descriptors and string formating method. + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_req.h" +#include "usbd_conf.h" +#include "usb_regs.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_DESC + * @brief USBD descriptors module + * @{ + */ + +/** @defgroup USBD_DESC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Defines + * @{ + */ + +#define USBD_VID 0x0483 +#define USBD_PID 0x5710 + +#define USBD_LANGID_STRING 0x409 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" + +#define USBD_PRODUCT_HS_STRING "Joystick in HS mode" +#define USBD_SERIALNUMBER_HS_STRING "00000000011B" + +#define USBD_PRODUCT_FS_STRING "Joystick in FS Mode" +#define USBD_SERIALNUMBER_FS_STRING "00000000011C" + +#define USBD_CONFIGURATION_HS_STRING "HID Config" +#define USBD_INTERFACE_HS_STRING "HID Interface" + +#define USBD_CONFIGURATION_FS_STRING "HID Config" +#define USBD_INTERFACE_FS_STRING "HID Interface" +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Variables + * @{ + */ + +USBD_DEVICE USR_desc = +{ + USBD_USR_DeviceDescriptor, + USBD_USR_LangIDStrDescriptor, + USBD_USR_ManufacturerStrDescriptor, + USBD_USR_ProductStrDescriptor, + USBD_USR_SerialStrDescriptor, + USBD_USR_ConfigStrDescriptor, + USBD_USR_InterfaceStrDescriptor, + +}; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] __ALIGN_END = + { + 0x12, /*bLength */ + USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/ + 0x00, /*bcdUSB */ + 0x02, + 0x00, /*bDeviceClass*/ + 0x00, /*bDeviceSubClass*/ + 0x00, /*bDeviceProtocol*/ + USB_OTG_MAX_EP0_SIZE, /*bMaxPacketSize*/ + LOBYTE(USBD_VID), /*idVendor*/ + HIBYTE(USBD_VID), /*idVendor*/ + LOBYTE(USBD_PID), /*idVendor*/ + HIBYTE(USBD_PID), /*idVendor*/ + 0x00, /*bcdDevice rel. 2.00*/ + 0x02, + USBD_IDX_MFC_STR, /*Index of manufacturer string*/ + USBD_IDX_PRODUCT_STR, /*Index of product string*/ + USBD_IDX_SERIAL_STR, /*Index of serial number string*/ + USBD_CFG_MAX_NUM /*bNumConfigurations*/ + } ; /* USB_DeviceDescriptor */ + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = +{ + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED + #if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 + #endif +#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */ +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID] __ALIGN_END = +{ + USB_SIZ_STRING_LANGID, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING), +}; +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_DESC_Private_Functions + * @{ + */ + +/** +* @brief USBD_USR_DeviceDescriptor +* return the device descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length) +{ + *length = sizeof(USBD_DeviceDesc); + return USBD_DeviceDesc; +} + +/** +* @brief USBD_USR_LangIDStrDescriptor +* return the LangID string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length) +{ + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + + +/** +* @brief USBD_USR_ProductStrDescriptor +* return the product string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_ProductStrDescriptor( uint8_t speed , uint16_t *length) +{ + + + if(speed == 0) + { + USBD_GetString (USBD_PRODUCT_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_PRODUCT_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** +* @brief USBD_USR_ManufacturerStrDescriptor +* return the manufacturer string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_ManufacturerStrDescriptor( uint8_t speed , uint16_t *length) +{ + USBD_GetString (USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** +* @brief USBD_USR_SerialStrDescriptor +* return the serial number string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length) +{ + if(speed == USB_OTG_SPEED_HIGH) + { + USBD_GetString (USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** +* @brief USBD_USR_ConfigStrDescriptor +* return the configuration string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length) +{ + if(speed == USB_OTG_SPEED_HIGH) + { + USBD_GetString (USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + + +/** +* @brief USBD_USR_InterfaceStrDescriptor +* return the interface string descriptor +* @param speed : current device speed +* @param length : pointer to data length variable +* @retval pointer to descriptor buffer +*/ +uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString (USBD_INTERFACE_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString (USBD_INTERFACE_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + diff --git a/exampleF4/Projects/discovery_demo/usbd_desc.h b/exampleF4/Projects/discovery_demo/usbd_desc.h new file mode 100644 index 0000000..ed999dc --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usbd_desc.h @@ -0,0 +1,114 @@ +/** + ****************************************************************************** + * @file usbd_desc.h + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief header file for the usbd_desc.c file + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ + +#ifndef __USB_DESC_H +#define __USB_DESC_H + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DESC + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DESC_Exported_Defines + * @{ + */ +#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 +#define USB_STRING_DESCRIPTOR_TYPE 0x03 +#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 +#define USB_SIZ_DEVICE_DESC 18 +#define USB_SIZ_STRING_LANGID 4 + +/** + * @} + */ + + +/** @defgroup USBD_DESC_Exported_TypesDefinitions + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_DESC_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_Variables + * @{ + */ +extern uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC]; +extern uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ]; +extern uint8_t USBD_OtherSpeedCfgDesc[USB_LEN_CFG_DESC]; +extern uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC]; +extern uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID]; +extern USBD_DEVICE USR_desc; +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_FunctionsPrototype + * @{ + */ + + +uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_ManufacturerStrDescriptor ( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_ProductStrDescriptor ( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length); +uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length); + +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t * USBD_USR_USRStringDesc (uint8_t speed, uint8_t idx , uint16_t *length); +#endif /* USB_SUPPORT_USER_STRING_DESC */ + +/** + * @} + */ + +#endif /* __USBD_DESC_H */ + +/** + * @} + */ + +/** +* @} +*/ +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/exampleF4/Projects/discovery_demo/usbd_usr.c b/exampleF4/Projects/discovery_demo/usbd_usr.c new file mode 100644 index 0000000..6ebd157 --- /dev/null +++ b/exampleF4/Projects/discovery_demo/usbd_usr.c @@ -0,0 +1,238 @@ +/** + ****************************************************************************** + * @file usbd_usr.c + * @author MCD Application Team + * @version V1.0.0 + * @date 19-September-2011 + * @brief This file includes the user application layer + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_usr.h" +#include "usbd_ioreq.h" + + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY +* @{ +*/ + +/** @defgroup USBD_USR +* @brief This file includes the user application layer +* @{ +*/ + +/** @defgroup USBD_USR_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_USR_Private_Defines +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_USR_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_USR_Private_Variables +* @{ +*/ + +USBD_Usr_cb_TypeDef USR_cb = +{ + USBD_USR_Init, + USBD_USR_DeviceReset, + USBD_USR_DeviceConfigured, + USBD_USR_DeviceSuspended, + USBD_USR_DeviceResumed, + + USBD_USR_DeviceConnected, + USBD_USR_DeviceDisconnected, + + +}; + + + +/** +* @} +*/ + +/** @defgroup USBD_USR_Private_Constants +* @{ +*/ + +/** +* @} +*/ + + + +/** @defgroup USBD_USR_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_USR_Private_Functions +* @{ +*/ + +/** +* @brief USBD_USR_Init +* Displays the message on LCD for host lib initialization +* @param None +* @retval None +*/ +void USBD_USR_Init(void) +{ + /* Setup SysTick Timer for 40 msec interrupts + This interrupt is used to probe the joystick */ + if (SysTick_Config(SystemCoreClock / 24)) + { + /* Capture error */ + while (1); + } +} + +/** +* @brief USBD_USR_DeviceReset +* Displays the message on LCD on device Reset Event +* @param speed : device speed +* @retval None +*/ +void USBD_USR_DeviceReset(uint8_t speed ) +{ + switch (speed) + { + case USB_OTG_SPEED_HIGH: + break; + + case USB_OTG_SPEED_FULL: + break; + default: + break; + + } +} + + +/** +* @brief USBD_USR_DeviceConfigured +* Displays the message on LCD on device configuration Event +* @param None +* @retval Staus +*/ +void USBD_USR_DeviceConfigured (void) +{ +} + + +/** +* @brief USBD_USR_DeviceConnected +* Displays the message on LCD on device connection Event +* @param None +* @retval Staus +*/ +void USBD_USR_DeviceConnected (void) +{ +} + + +/** +* @brief USBD_USR_DeviceDisonnected +* Displays the message on LCD on device disconnection Event +* @param None +* @retval Staus +*/ +void USBD_USR_DeviceDisconnected (void) +{ +} + +/** +* @brief USBD_USR_DeviceSuspended +* Displays the message on LCD on device suspend Event +* @param None +* @retval None +*/ +void USBD_USR_DeviceSuspended(void) +{ + /* Users can do their application actions here for the USB-Reset */ +} + + +/** +* @brief USBD_USR_DeviceResumed +* Displays the message on LCD on device resume Event +* @param None +* @retval None +*/ +void USBD_USR_DeviceResumed(void) +{ + /* Users can do their application actions here for the USB-Reset */ +} + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.47.2