Merge branch 'tmaster' into future
[fw/stlink] / example / stm32f4 / Projects / discovery_demo / main.c
diff --git a/example/stm32f4/Projects/discovery_demo/main.c b/example/stm32f4/Projects/discovery_demo/main.c
new file mode 100644 (file)
index 0000000..761e761
--- /dev/null
@@ -0,0 +1,508 @@
+/**
+  ******************************************************************************
+  * @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.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */ 
+/* 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****/