From: jnosky Date: Sat, 29 Oct 2011 22:17:46 +0000 (-0400) Subject: Fixed flash utility for STM32F4 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=0fbdd62e61f410d6ad9f442f158b2206511fcd91;p=fw%2Fstlink Fixed flash utility for STM32F4 Can write entire 1MB of flash --- diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..d54110e --- /dev/null +++ b/.cproject @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +make +CONFIG_STM32F4_DISCOVERY=1 +true +true +true + + +make +clean +true +true +true + + +make + +CONFIG_STM32F4_DISCOVERY=1 +true +true +true + + +make + +clean +true +true +true + + +make +CONFIG_STM32F4_DISCOVERY=1 +true +true +true + + +make + +CONFIG_USE_LIBSG=0 +true +true +true + + +make +clean CONFIG_USE_LIBSG=0 +true +true +true + + +make +all +true +true +true + + +make + +CONFIG_USE_LIBSG=0 +true +true +true + + +make +CONFIGURE_USE_LIBSG=0 +true +true +true + + +make + +clean CONFIG_USE_LIBSG=0 +true +true +true + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..12a2f85 --- /dev/null +++ b/.project @@ -0,0 +1,81 @@ + + + stlink + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?children? + ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\|| + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/doc/tutorial/tutorial.pdf b/doc/tutorial/tutorial.pdf index 6481387..82372df 100644 Binary files a/doc/tutorial/tutorial.pdf and b/doc/tutorial/tutorial.pdf differ diff --git a/doc/tutorial/tutorial.tex b/doc/tutorial/tutorial.tex index 0437119..6d7773f 100644 --- a/doc/tutorial/tutorial.tex +++ b/doc/tutorial/tutorial.tex @@ -90,8 +90,8 @@ It includes: \newpage -\section{Building and running a program in SRAM} -\paragraph{} + +\section{Building and running a program} A simple LED blinking example is provided in the example directory. It is built using:\\ \begin{small} \begin{lstlisting}[frame=tb] @@ -154,9 +154,10 @@ The board BLUE and GREEN leds should be blinking (those leds are near the user a \newpage -\section{Building and flashing a program} +\section{Reading and writing to flash} \paragraph{} -FLASH memory reading and writing is done by a separate tool, as shown below:\\ +Flash memory reading and writing is done by a separate tool. A binary running in flash is assumed to +be linked against address 0x8000000. The flash tool is then used as shown below:\\ \begin{small} \begin{lstlisting}[frame=tb] # change to the flash tool directory @@ -176,21 +177,6 @@ $> ./flash write in.bin 0x8000000 \end{lstlisting} \end{small} -\paragraph{} -A LED blinking example is provided:\\ -\begin{small} -\begin{lstlisting}[frame=tb] -# build the example, resulting in blink.bin -$> cd stlink.git/example/blink_flash -$> PATH=$TOOLCHAIN_PATH:$PATH make CONFIG_STM32L_DISCOVERY=1 - -# write blink.bin into FLASH -$> sudo ./flash write blink.bin 0x08000000 -\end{lstlisting} -\end{small} - -\paragraph{} -Upon reset, the board LEDs should be blinking. \newpage \section{Building and installing the CHIBIOS kernel} diff --git a/example/blink/.cproject b/example/blink/.cproject new file mode 100644 index 0000000..2fd5b99 --- /dev/null +++ b/example/blink/.cproject @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/blink/.project b/example/blink/.project new file mode 100644 index 0000000..249c18c --- /dev/null +++ b/example/blink/.project @@ -0,0 +1,81 @@ + + + Blink + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/Blink/Debug} + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/example/blink/Makefile b/example/blink/Makefile index 1906b91..a8e3532 100644 --- a/example/blink/Makefile +++ b/example/blink/Makefile @@ -4,7 +4,8 @@ BIN_IMAGE=blink.bin CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -CFLAGS=-g -O2 -mlittle-endian -mthumb +CFLAGS=-g -mlittle-endian -mthumb +#CFLAGS=-g -O2 -mlittle-endian -mthumb ifeq ($(CONFIG_STM32L_DISCOVERY), 1) CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY else ifeq ($(CONFIG_STM32VL_DISCOVERY), 1) diff --git a/example/blink/blink.bin b/example/blink/blink.bin new file mode 100644 index 0000000..1af82ee Binary files /dev/null and b/example/blink/blink.bin differ diff --git a/example/blink/blink.elf b/example/blink/blink.elf new file mode 100644 index 0000000..6cf22c6 Binary files /dev/null and b/example/blink/blink.elf differ diff --git a/example/blink/default_bootloader.bin b/example/blink/default_bootloader.bin old mode 100755 new mode 100644 diff --git a/example/blink/disasm.sh b/example/blink/disasm.sh old mode 100755 new mode 100644 diff --git a/example/blink/main.c b/example/blink/main.c index 0889b81..66fa6e0 100644 --- a/example/blink/main.c +++ b/example/blink/main.c @@ -65,6 +65,9 @@ static inline void switch_leds_off(void) # define LED_RED (1 << 14) /* port B, pin 14 */ # define LED_BLUE (1 << 15) /* port B, pin 15 */ +void _tmain(void) { + main(); +} static inline void setup_leds(void) { *(volatile uint32_t*)GPIOD_MODER |= (1 << (12 * 2)) | (1 << (13 * 2)) | @@ -74,7 +77,7 @@ static inline void setup_leds(void) static inline void switch_leds_on(void) { - *(volatile uint32_t*)GPIOD_ODR = LED_GREEN | LED_ORANGE | LED_RED | LED_BLUE; + *(volatile uint32_t*)GPIOD_ODR = LED_GREEN | LED_RED ; } static inline void switch_leds_off(void) @@ -94,7 +97,8 @@ do { \ __asm__ __volatile__ ("nop\n\t":::"memory"); \ } while (0) -static void __attribute__((naked)) __attribute__((used)) main(void) +//static void __attribute__((naked)) __attribute__((used)) main(void) +void main(void) { setup_leds(); diff --git a/example/blink/o.bin b/example/blink/o.bin old mode 100755 new mode 100644 diff --git a/example/blink_flash/blink.bin b/example/blink_flash/blink.bin new file mode 100644 index 0000000..314b6c0 Binary files /dev/null and b/example/blink_flash/blink.bin differ diff --git a/example/blink_flash/blink.elf b/example/blink_flash/blink.elf new file mode 100644 index 0000000..4d0898d Binary files /dev/null and b/example/blink_flash/blink.elf differ diff --git a/example/blink_flash/main.c b/example/blink_flash/main.c index d27ef7f..4385b09 100644 --- a/example/blink_flash/main.c +++ b/example/blink_flash/main.c @@ -69,6 +69,37 @@ static inline void switch_leds_off(void) GPIO_LOW(LD_GPIO_PORT, LD_BLUE_GPIO_PIN); } +#elif CONFIG_STM32F4_DISCOVERY + +//#define GPIOD 0x40020C00 /* port D */ +# define GPIOD_MODER (GPIOD + 0x00) /* port mode register */ +# define GPIOD_ODR (GPIOD + 0x14) /* port output data register */ + +# define LED_GREEN (1 << 12) /* port B, pin 12 */ +# define LED_ORANGE (1 << 13) /* port B, pin 13 */ +# define LED_RED (1 << 14) /* port B, pin 14 */ +# define LED_BLUE (1 << 15) /* port B, pin 15 */ + +void _tmain(void) { + main(); +} +static inline void setup_leds(void) +{ + *(volatile uint32_t*)GPIOD_MODER |= (1 << (12 * 2)) | (1 << (13 * 2)) | + (1 << (13 * 2)) | (1 << (14 * 2)) | (1 << (15 * 2)); +} + + +static inline void switch_leds_on(void) +{ + *(volatile uint32_t*)GPIOD_ODR = LED_GREEN | LED_RED ; +} + +static inline void switch_leds_off(void) +{ + *(volatile uint32_t*)GPIOD_ODR = 0; +} + #endif /* otherwise, error */ diff --git a/example/dac/Makefile b/example/dac/Makefile deleted file mode 100644 index 84db69e..0000000 --- a/example/dac/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -EXECUTABLE=dac.elf -BIN_IMAGE=dac.bin - -CC=arm-none-eabi-gcc -OBJCOPY=arm-none-eabi-objcopy - -CFLAGS=-O3 -mlittle-endian -mthumb -ifeq ($(CONFIG_STM32L_DISCOVERY), 1) - CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY=1 -else ifeq ($(CONFIG_STM32VL_DISCOVERY), 1) - CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32VL_DISCOVERY=1 -else ifeq ($(CONFIG_STM32F4_DISCOVERY), 1) - CFLAGS+=-mcpu=cortex-m4 -DCONFIG_STM32F4_DISCOVERY=1 -else -$(error "must specify CONFIG_ for board!") -endif -CFLAGS+=-ffreestanding -nostdlib -nostdinc - -# to run from FLASH -CFLAGS+=-Wl,-T,stm32_flash.ld - -# stm32l_discovery lib -CFLAGS+=-I../libstm32l_discovery/inc -CFLAGS+=-I../libstm32l_discovery/inc/base -CFLAGS+=-I../libstm32l_discovery/inc/core_support -CFLAGS+=-I../libstm32l_discovery/inc/device_support - -all: $(BIN_IMAGE) - -$(BIN_IMAGE): $(EXECUTABLE) - $(OBJCOPY) -O binary $^ $@ - -$(EXECUTABLE): main.c system_stm32l1xx.c startup_stm32l1xx_md.s - $(CC) $(CFLAGS) $^ -o $@ -L../libstm32l_discovery/build -lstm32l_discovery - -clean: - rm -rf $(EXECUTABLE) - rm -rf $(BIN_IMAGE) - -write: all - sudo ../../flash/flash write ./dac.bin 0x08000000 - -.PHONY: all clean write diff --git a/example/dac/discover_board.h b/example/dac/discover_board.h deleted file mode 100644 index d93a184..0000000 --- a/example/dac/discover_board.h +++ /dev/null @@ -1,61 +0,0 @@ - /** - ****************************************************************************** - * @file discover_board.h - * @author Microcontroller Division - * @version V1.0.2 - * @date September-2011 - * @brief Input/Output defines - ****************************************************************************** - * @copy - * - * 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 __DISCOVER_BOARD_H -#define __DISCOVER_BOARD_H - -/* Includes ------------------------------------------------------------------*/ -/* #include "stm32l1xx.h" */ - -#define bool _Bool -#define FALSE 0 -#define TRUE !FALSE - -/* MACROs for SET, RESET or TOGGLE Output port */ - -#define GPIO_HIGH(a,b) a->BSRRL = b -#define GPIO_LOW(a,b) a->BSRRH = b -#define GPIO_TOGGLE(a,b) a->ODR ^= b - -#define USERBUTTON_GPIO_PORT GPIOA -#define USERBUTTON_GPIO_PIN GPIO_Pin_0 -#define USERBUTTON_GPIO_CLK RCC_AHBPeriph_GPIOA - -#define LD_GPIO_PORT GPIOB -#define LD_GREEN_GPIO_PIN GPIO_Pin_7 -#define LD_BLUE_GPIO_PIN GPIO_Pin_6 -#define LD_GPIO_PORT_CLK RCC_AHBPeriph_GPIOB - -#define CTN_GPIO_PORT GPIOC -#define CTN_CNTEN_GPIO_PIN GPIO_Pin_13 -#define CTN_GPIO_CLK RCC_AHBPeriph_GPIOC - -#define WAKEUP_GPIO_PORT GPIOA - -#define IDD_MEASURE_PORT GPIOA -#define IDD_MEASURE GPIO_Pin_4 - - -#endif - - -/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ diff --git a/example/dac/main.c b/example/dac/main.c deleted file mode 100644 index 1f89d33..0000000 --- a/example/dac/main.c +++ /dev/null @@ -1,242 +0,0 @@ -/* base headers */ -#include "stdint.h" - -/* libstm32l_discovery headers */ -#include "stm32l1xx_gpio.h" -#include "stm32l1xx_adc.h" -#include "stm32l1xx_dac.h" -#include "stm32l1xx_lcd.h" -#include "stm32l1xx_rcc.h" -#include "stm32l1xx_rtc.h" -#include "stm32l1xx_exti.h" -#include "stm32l1xx_pwr.h" -#include "stm32l1xx_flash.h" -#include "stm32l1xx_syscfg.h" -#include "stm32l1xx_dbgmcu.h" - -/* board specific macros */ -#include "discover_board.h" - - -/* hardware configuration */ - -#if CONFIG_STM32VL_DISCOVERY - -# define GPIOC 0x40011000 /* port C */ -# define GPIOC_CRH (GPIOC + 0x04) /* port configuration register high */ -# define GPIOC_ODR (GPIOC + 0x0c) /* port output data register */ - -# define LED_BLUE (1 << 8) /* port C, pin 8 */ -# define LED_GREEN (1 << 9) /* port C, pin 9 */ - -static inline void setup_leds(void) -{ - *(volatile uint32_t*)GPIOC_CRH = 0x44444411; -} - -static inline void switch_leds_on(void) -{ - *(volatile uint32_t*)GPIOC_ODR = LED_BLUE | LED_GREEN; -} - -static inline void switch_leds_off(void) -{ - *(volatile uint32_t*)GPIOC_ODR = 0; -} - -#elif CONFIG_STM32L_DISCOVERY - -# define GPIOB_MODER (GPIOB + 0x00) /* port mode register */ -# define GPIOB_ODR (GPIOB + 0x14) /* port output data register */ - -# define LED_BLUE (1 << 6) /* port B, pin 6 */ -# define LED_GREEN (1 << 7) /* port B, pin 7 */ - -static inline void setup_leds(void) -{ - /* configure port 6 and 7 as output */ - *(volatile uint32_t*)GPIOB_MODER |= (1 << (7 * 2)) | (1 << (6 * 2)); -} - -static inline void switch_leds_on(void) -{ - GPIO_HIGH(LD_GPIO_PORT, LD_GREEN_GPIO_PIN); - GPIO_HIGH(LD_GPIO_PORT, LD_BLUE_GPIO_PIN); -} - -static inline void switch_leds_off(void) -{ - GPIO_LOW(LD_GPIO_PORT, LD_GREEN_GPIO_PIN); - GPIO_LOW(LD_GPIO_PORT, LD_BLUE_GPIO_PIN); -} - -#endif /* otherwise, error */ - - -#define delay() \ -do { \ - volatile unsigned int i; \ - for (i = 0; i < 1000000; ++i) \ - __asm__ __volatile__ ("nop\n\t":::"memory"); \ -} while (0) - - -static void RCC_Configuration(void) -{ - /* HSI is 16mhz RC clock directly fed to SYSCLK (rm00038, figure 9) */ - - /* enable the HSI clock (high speed internal) */ - RCC_HSICmd(ENABLE); - - /* wail til HSI ready */ - while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET) - {} - - /* at startup, SYSCLK driven by MSI. set to HSI */ - RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); - - /* set MSI to 4mhz */ - RCC_MSIRangeConfig(RCC_MSIRange_6); - - /* turn HSE off */ - RCC_HSEConfig(RCC_HSE_OFF); - if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) - { - while (1) ; - } -} - - -static void RTC_Configuration(void) -{ - /* Allow access to the RTC */ - PWR_RTCAccessCmd(ENABLE); - - /* Reset Backup Domain */ - RCC_RTCResetCmd(ENABLE); - RCC_RTCResetCmd(DISABLE); - - /* LSE Enable */ - RCC_LSEConfig(RCC_LSE_ON); - - /* Wait till LSE is ready */ - while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) - {} - - RCC_RTCCLKCmd(ENABLE); - - /* LCD Clock Source Selection */ - RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); - -} - -static void setup_dac1(void) -{ - /* see 10.2 notes */ - - static GPIO_InitTypeDef GPIO_InitStructure; - static DAC_InitTypeDef DAC_InitStructure; - - /* DAC clock path: - HSI (16mhz) -> SYSCLK -> HCLK(/1) -> PCLK1(/1) - */ - - /* set the AHB clock (HCLK) prescaler to 1 */ - RCC_HCLKConfig(RCC_SYSCLK_Div1); - - /* set the low speed APB clock (APB1, ie. PCLK1) prescaler to 1 */ - RCC_PCLK1Config(RCC_HCLK_Div1); - - /* enable DAC APB1 clock */ - /* signal connections: HSI(16mhz) -> SYSCLK -> AHB */ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE); - - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; /* GPIO_Pin_5 for channel 2 */ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - DAC_StructInit(&DAC_InitStructure); - DAC_InitStructure.DAC_Trigger = DAC_Trigger_None; -#if 0 /* triangle waveform generation */ - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle; - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1; -#else - DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; - DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; -#endif - DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable; - DAC_Init(DAC_Channel_1, &DAC_InitStructure); - - /* enable dac channel */ - DAC_Cmd(DAC_Channel_1, ENABLE); -} - -static inline void set_dac1_mv(unsigned int mv) -{ - /* mv the millivolts */ - - /* vref in millivolts */ - /* #define CONFIG_VREF 5000 */ -#define CONFIG_VREF 3000 - - /* resolution in bits */ -#define CONFIG_DAC_RES 12 - - const uint16_t n = (mv * (1 << (CONFIG_DAC_RES - 1))) / CONFIG_VREF; - DAC_SetChannel1Data(DAC_Align_12b_R, n); -} - -void main(void) -{ - static RCC_ClocksTypeDef RCC_Clocks; - static GPIO_InitTypeDef GPIO_InitStructure; - static uint16_t dac_value; - static unsigned int led_state = 0; - - /* Configure Clocks for Application need */ - RCC_Configuration(); - - /* Configure RTC Clocks */ - RTC_Configuration(); - -#if 0 - /* Set internal voltage regulator to 1.8v */ - PWR_VoltageScalingConfig(PWR_VoltageScaling_Range1); - /* Wait Until the Voltage Regulator is ready */ - while (PWR_GetFlagStatus(PWR_FLAG_VOS) != RESET) ; -#endif - - /* configure gpios */ - - /* Enable GPIOs clock */ - RCC_AHBPeriphClockCmd(LD_GPIO_PORT_CLK, ENABLE); - - /* Configure the GPIO_LED pins LD3 & LD4*/ - GPIO_InitStructure.GPIO_Pin = LD_GREEN_GPIO_PIN | LD_BLUE_GPIO_PIN; - 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_2MHz; - GPIO_Init(LD_GPIO_PORT, &GPIO_InitStructure); - GPIO_LOW(LD_GPIO_PORT, LD_GREEN_GPIO_PIN); - GPIO_LOW(LD_GPIO_PORT, LD_BLUE_GPIO_PIN); - - setup_dac1(); - - dac_value = 0; - - while (1) - { - DAC_SetChannel1Data(DAC_Align_12b_R, dac_value & 0xfff); - dac_value += 0x10; - - if (led_state & 1) switch_leds_on(); - else switch_leds_off(); - led_state ^= 1; - - delay(); - } -} diff --git a/example/dac/startup_stm32l1xx_md.s b/example/dac/startup_stm32l1xx_md.s deleted file mode 100644 index 9a8389c..0000000 --- a/example/dac/startup_stm32l1xx_md.s +++ /dev/null @@ -1,365 +0,0 @@ -/** - ****************************************************************************** - * @file startup_stm32l1xx_md.s - * @author MCD Application Team - * @version V1.0.0 - * @date 31-December-2010 - * @brief STM32L1xx Ultra Low Power Medium-density 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 - * - Branches to main in the C library (which eventually - * calls main()). - * After Reset the Cortex-M3 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 2010 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 - -.equ BootRAM, 0xF108F85F -/** - * @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.*/ -/* let main do the system initialization */ - 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 - .word WWDG_IRQHandler - .word PVD_IRQHandler - .word TAMPER_STAMP_IRQHandler - .word RTC_WKUP_IRQHandler - .word FLASH_IRQHandler - .word RCC_IRQHandler - .word EXTI0_IRQHandler - .word EXTI1_IRQHandler - .word EXTI2_IRQHandler - .word EXTI3_IRQHandler - .word EXTI4_IRQHandler - .word DMA1_Channel1_IRQHandler - .word DMA1_Channel2_IRQHandler - .word DMA1_Channel3_IRQHandler - .word DMA1_Channel4_IRQHandler - .word DMA1_Channel5_IRQHandler - .word DMA1_Channel6_IRQHandler - .word DMA1_Channel7_IRQHandler - .word ADC1_IRQHandler - .word USB_HP_IRQHandler - .word USB_LP_IRQHandler - .word DAC_IRQHandler - .word COMP_IRQHandler - .word EXTI9_5_IRQHandler - .word LCD_IRQHandler - .word TIM9_IRQHandler - .word TIM10_IRQHandler - .word TIM11_IRQHandler - .word TIM2_IRQHandler - .word TIM3_IRQHandler - .word TIM4_IRQHandler - .word I2C1_EV_IRQHandler - .word I2C1_ER_IRQHandler - .word I2C2_EV_IRQHandler - .word I2C2_ER_IRQHandler - .word SPI1_IRQHandler - .word SPI2_IRQHandler - .word USART1_IRQHandler - .word USART2_IRQHandler - .word USART3_IRQHandler - .word EXTI15_10_IRQHandler - .word RTC_Alarm_IRQHandler - .word USB_FS_WKUP_IRQHandler - .word TIM6_IRQHandler - .word TIM7_IRQHandler - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word BootRAM /* @0x108. This is for boot in RAM mode for - STM32L15x ULtra Low Power Medium-density devices. */ - -/******************************************************************************* -* -* 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 TAMPER_STAMP_IRQHandler - .thumb_set TAMPER_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_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler - - .weak USB_HP_IRQHandler - .thumb_set USB_HP_IRQHandler,Default_Handler - - .weak USB_LP_IRQHandler - .thumb_set USB_LP_IRQHandler,Default_Handler - - .weak DAC_IRQHandler - .thumb_set DAC_IRQHandler,Default_Handler - - .weak COMP_IRQHandler - .thumb_set COMP_IRQHandler,Default_Handler - - .weak EXTI9_5_IRQHandler - .thumb_set EXTI9_5_IRQHandler,Default_Handler - - .weak LCD_IRQHandler - .thumb_set LCD_IRQHandler,Default_Handler - - .weak TIM9_IRQHandler - .thumb_set TIM9_IRQHandler,Default_Handler - - .weak TIM10_IRQHandler - .thumb_set TIM10_IRQHandler,Default_Handler - - .weak TIM11_IRQHandler - .thumb_set TIM11_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 USB_FS_WKUP_IRQHandler - .thumb_set USB_FS_WKUP_IRQHandler,Default_Handler - - .weak TIM6_IRQHandler - .thumb_set TIM6_IRQHandler,Default_Handler - - .weak TIM7_IRQHandler - .thumb_set TIM7_IRQHandler,Default_Handler - -/******************** (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE***/ - diff --git a/example/dac/stm32_flash.ld b/example/dac/stm32_flash.ld deleted file mode 100644 index 146b16e..0000000 --- a/example/dac/stm32_flash.ld +++ /dev/null @@ -1,173 +0,0 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for STM32L152RB Device with -** 128KByte FLASH, 16KByte 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 = 0x20004000; /* end of 16K 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 = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K - RW_EEPROM (rw) : ORIGIN = 0x08080000, LENGTH = 32 -} - -/* 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) } - - .DataFlash (NOLOAD): {*(.DataFlash)} >RW_EEPROM -} diff --git a/example/dac/system_stm32l1xx.c b/example/dac/system_stm32l1xx.c deleted file mode 100644 index 6deab32..0000000 --- a/example/dac/system_stm32l1xx.c +++ /dev/null @@ -1,367 +0,0 @@ -/** - ****************************************************************************** - * @file system_stm32l1xx.c - * @author MCD Application Team - * @version V1.0.0 - * @date 2-June-2011 - * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. - * This file contains the system clock configuration for STM32L1xx Ultra - * Low Medium-density devices, and is generated by the clock configuration - * tool "STM32L1xx_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_stm32l1xx_md.s" file. - * - * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used - * by the user application to setup the SysTick - * timer or configure other parameters. - * - * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must - * be called whenever the core clock is changed - * during program execution. - * - * 2. After each device reset the MSI (2.1 MHz Range) is used as system clock source. - * Then SystemInit() function is called, in "startup_stm32l1xx_md.s" file, to - * configure the system clock before to branch to main program. - * - * 3. If the system clock source selected by user fails to startup, the SystemInit() - * function will do nothing and MSI still used as system clock source. User can - * add some code to deal with this issue inside the SetSysClock() function. - * - * 4. The default value of HSE crystal is set to 8MHz, refer to "HSE_VALUE" define - * in "stm32l1xx.h" file. When HSE is used as system clock source, directly or - * through PLL, and you are using different crystal you have to adapt the HSE - * value to your own configuration. - * - * 5. This file configures the system clock as follows: - *============================================================================= - * System Clock Configuration - *============================================================================= - * System clock source | HSI - *----------------------------------------------------------------------------- - * SYSCLK | 16000000 Hz - *----------------------------------------------------------------------------- - * HCLK | 16000000 Hz - *----------------------------------------------------------------------------- - * AHB Prescaler | 1 - *----------------------------------------------------------------------------- - * APB1 Prescaler | 1 - *----------------------------------------------------------------------------- - * APB2 Prescaler | 1 - *----------------------------------------------------------------------------- - * HSE Frequency | 8000000 Hz - *----------------------------------------------------------------------------- - * PLL DIV | Not Used - *----------------------------------------------------------------------------- - * PLL MUL | Not Used - *----------------------------------------------------------------------------- - * VDD | 3.3 V - *----------------------------------------------------------------------------- - * Vcore | 1.8 V (Range 1) - *----------------------------------------------------------------------------- - * Flash Latency | 0 WS - *----------------------------------------------------------------------------- - * Require 48MHz for USB clock | Disabled - *----------------------------------------------------------------------------- - *============================================================================= - ****************************************************************************** - * @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 2010 STMicroelectronics

- ****************************************************************************** - */ - -/** @addtogroup CMSIS - * @{ - */ - -/** @addtogroup stm32l1xx_system - * @{ - */ - -/** @addtogroup STM32L1xx_System_Private_Includes - * @{ - */ - -#include "stm32l1xx.h" - -/** - * @} - */ - -/** @addtogroup STM32L1xx_System_Private_TypesDefinitions - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32L1xx_System_Private_Defines - * @{ - */ -/*!< Uncomment the following line if you need to relocate your vector Table in - Internal SRAM. */ -/* #define VECT_TAB_SRAM */ -#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. - This value must be a multiple of 0x200. */ -/** - * @} - */ - -/** @addtogroup STM32L1xx_System_Private_Macros - * @{ - */ - -/** - * @} - */ - -/** @addtogroup STM32L1xx_System_Private_Variables - * @{ - */ -uint32_t SystemCoreClock = 16000000; -__I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48}; -__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; - -/** - * @} - */ - -/** @addtogroup STM32L1xx_System_Private_FunctionPrototypes - * @{ - */ - -static void SetSysClock(void); - -/** - * @} - */ - -/** @addtogroup STM32L1xx_System_Private_Functions - * @{ - */ - -/** - * @brief Setup the microcontroller system. - * Initialize the Embedded Flash Interface, the PLL and update the - * SystemCoreClock variable. - * @param None - * @retval None - */ -void SystemInit (void) -{ - /*!< Set MSION bit */ - RCC->CR |= (uint32_t)0x00000100; - - /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */ - RCC->CFGR &= (uint32_t)0x88FFC00C; - - /*!< Reset HSION, HSEON, CSSON and PLLON bits */ - RCC->CR &= (uint32_t)0xEEFEFFFE; - - /*!< Reset HSEBYP bit */ - RCC->CR &= (uint32_t)0xFFFBFFFF; - - /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */ - RCC->CFGR &= (uint32_t)0xFF02FFFF; - - /*!< Disable all interrupts */ - RCC->CIR = 0x00000000; - - /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */ - SetSysClock(); - -#ifdef VECT_TAB_SRAM - SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ -#else - SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ -#endif -} - -/** - * @brief Update SystemCoreClock according to Clock Register Values - * @note - The system frequency computed by this function is not the real - * frequency in the chip. It is calculated based on the predefined - * constant and the selected clock source: - * - * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI - * value as defined by the MSI range. - * - * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) - * - * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) - * - * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) - * or HSI_VALUE(*) multiplied/divided by the PLL factors. - * - * (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value - * 16 MHz) but the real value may vary depending on the variations - * in voltage and temperature. - * - * (**) HSE_VALUE is a constant defined in stm32l1xx.h file (default value - * 8 MHz), user has to ensure that HSE_VALUE is same as the real - * frequency of the crystal used. Otherwise, this function may - * have wrong result. - * - * - The result of this function could be not correct when using fractional - * value for HSE crystal. - * @param None - * @retval None - */ -void SystemCoreClockUpdate (void) -{ - uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, msirange = 0; - - /* Get SYSCLK source -------------------------------------------------------*/ - tmp = RCC->CFGR & RCC_CFGR_SWS; - - switch (tmp) - { - case 0x00: /* MSI used as system clock */ - msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13; - SystemCoreClock = (32768 * (1 << (msirange + 1))); - break; - case 0x04: /* HSI used as system clock */ - SystemCoreClock = HSI_VALUE; - break; - case 0x08: /* HSE used as system clock */ - SystemCoreClock = HSE_VALUE; - break; - case 0x0C: /* PLL used as system clock */ - /* Get PLL clock source and multiplication factor ----------------------*/ - pllmul = RCC->CFGR & RCC_CFGR_PLLMUL; - plldiv = RCC->CFGR & RCC_CFGR_PLLDIV; - pllmul = PLLMulTable[(pllmul >> 18)]; - plldiv = (plldiv >> 22) + 1; - - pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; - - if (pllsource == 0x00) - { - /* HSI oscillator clock selected as PLL clock entry */ - SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv); - } - else - { - /* HSE selected as PLL clock entry */ - SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv); - } - break; - default: /* MSI used as system clock */ - msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13; - SystemCoreClock = (32768 * (1 << (msirange + 1))); - break; - } - /* Compute HCLK clock frequency --------------------------------------------*/ - /* Get HCLK prescaler */ - tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; - /* HCLK clock frequency */ - SystemCoreClock >>= tmp; -} - -/** - * @brief Configures the System clock frequency, AHB/APBx prescalers and Flash - * settings. - * @note This function should be called only once the RCC clock configuration - * is reset to the default reset state (done in SystemInit() function). - * @param None - * @retval None - */ -static void SetSysClock(void) -{ - __IO uint32_t StartUpCounter = 0, HSIStatus = 0; - - /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ - /* Enable HSI */ - RCC->CR |= ((uint32_t)RCC_CR_HSION); - - /* Wait till HSI is ready and if Time out is reached exit */ - do - { - HSIStatus = RCC->CR & RCC_CR_HSIRDY; - } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT)); - - if ((RCC->CR & RCC_CR_HSIRDY) != RESET) - { - HSIStatus = (uint32_t)0x01; - } - else - { - HSIStatus = (uint32_t)0x00; - } - - if (HSIStatus == (uint32_t)0x01) - { - /* Flash 0 wait state */ - FLASH->ACR &= ~FLASH_ACR_LATENCY; - - /* Disable Prefetch Buffer */ - FLASH->ACR &= ~FLASH_ACR_PRFTEN; - - /* Disable 64-bit access */ - FLASH->ACR &= ~FLASH_ACR_ACC64; - - - /* Power enable */ - RCC->APB1ENR |= RCC_APB1ENR_PWREN; - - /* Select the Voltage Range 1 (1.8 V) */ - PWR->CR = PWR_CR_VOS_0; - - - /* Wait Until the Voltage Regulator is ready */ - while((PWR->CSR & PWR_CSR_VOSF) != RESET) - { - } - - /* HCLK = SYSCLK /1*/ - RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; - /* PCLK2 = HCLK /1*/ - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; - - /* PCLK1 = HCLK /1*/ - RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; - - /* Select HSI as system clock source */ - RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); - RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSI; - - /* Wait till HSI is used as system clock source */ - while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_HSI) - { - } - } - else - { - /* If HSI fails to start-up, the application will have wrong clock - configuration. User can add here some code to deal with this error */ - } -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/example/lcd/lcd.elf b/example/lcd/lcd.elf new file mode 100644 index 0000000..c14e244 Binary files /dev/null and b/example/lcd/lcd.elf differ diff --git a/example/libstm32l_discovery/build/libstm32l_discovery.a b/example/libstm32l_discovery/build/libstm32l_discovery.a new file mode 100644 index 0000000..4dfbfdb Binary files /dev/null and b/example/libstm32l_discovery/build/libstm32l_discovery.a differ diff --git a/flash/Makefile b/flash/Makefile index 9fa6743..6b70871 100644 --- a/flash/Makefile +++ b/flash/Makefile @@ -18,10 +18,10 @@ ifeq ($(CONFIG_USE_LIBSG),) CONFIG_USE_LIBSG=1 endif -ifneq ($(CONFIG_USE_LIBSG),0) -CFLAGS+=-DCONFIG_USE_LIBSG=1 -LDFLAGS+=-lsgutils2 -endif +#ifneq ($(CONFIG_USE_LIBSG),0) +#CFLAGS+=-DCONFIG_USE_LIBSG=1 +#LDFLAGS+=-lsgutils2 +#endif SRCS=main.c OBJS=$(SRCS:.c=.o) diff --git a/flash/TESTPAT.BIN b/flash/TESTPAT.BIN new file mode 100644 index 0000000..dbeac90 Binary files /dev/null and b/flash/TESTPAT.BIN differ diff --git a/flash/blink.bin b/flash/blink.bin new file mode 100644 index 0000000..314b6c0 Binary files /dev/null and b/flash/blink.bin differ diff --git a/flash/crap.txt b/flash/crap.txt new file mode 100644 index 0000000..3a72f09 --- /dev/null +++ b/flash/crap.txt @@ -0,0 +1,4625 @@ +SR:0 +CR:80000000 +CR:0 +CR:0 +SNB:2 0 +CR:2 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:0 +SR:0 +CR:2 +CR:2 +SNB:2 0 +CR:2 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:0 +SR:0 +CR:2 +CR:2 +SNB:2 0 +CR:2 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:0 +SR:0 +CR:2 +CR:2 +SNB:2 0 +CR:2 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:10000 +SR:0 +CR:2 +PSIZ:200 2 +CR:200 +CR:200 +0 pages written out of 4 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +1 pages written out of 4 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +2 pages written out of 4 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +3 pages written out of 4 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +SR:0 +CR:201 diff --git a/flash/demo16k.bin b/flash/demo16k.bin new file mode 100644 index 0000000..442fc20 Binary files /dev/null and b/flash/demo16k.bin differ diff --git a/flash/demo32k.bin b/flash/demo32k.bin new file mode 100644 index 0000000..f523782 Binary files /dev/null and b/flash/demo32k.bin differ diff --git a/flash/demofull.bin b/flash/demofull.bin new file mode 100644 index 0000000..b7e636b Binary files /dev/null and b/flash/demofull.bin differ diff --git a/flash/flash.exe b/flash/flash.exe new file mode 100644 index 0000000..76b45e2 Binary files /dev/null and b/flash/flash.exe differ diff --git a/flash/main.c b/flash/main.c index 46a8ce1..278d63d 100644 --- a/flash/main.c +++ b/flash/main.c @@ -111,6 +111,7 @@ int main(int ac, char** av) if (o.do_read == 0) /* write */ { + err = stlink_fwrite_flash(sl, o.filename, o.addr); if (err == -1) { diff --git a/flash/shit.bin b/flash/shit.bin new file mode 100644 index 0000000..1e6b956 Binary files /dev/null and b/flash/shit.bin differ diff --git a/flash/test.bin b/flash/test.bin new file mode 100644 index 0000000..1ae6a5e Binary files /dev/null and b/flash/test.bin differ diff --git a/gdbserver/gdb-server.c b/gdbserver/gdb-server.c index 67f0be0..e376eb4 100644 --- a/gdbserver/gdb-server.c +++ b/gdbserver/gdb-server.c @@ -35,15 +35,6 @@ static const char hex[] = "0123456789abcdef"; static const char* current_memory_map = NULL; -/* - * Chip IDs are explained in the appropriate programming manual for the - * DBGMCU_IDCODE register (0xE0042000) - */ - -#define CORE_M3_R1 0x1BA00477 -#define CORE_M3_R2 0x4BA00477 -#define CORE_M4_R0 0x2BA01477 - struct chip_params { uint32_t chip_id; char* description; @@ -59,7 +50,7 @@ struct chip_params { { 0x412, "F1 Low-density device", 0x1ffff7e0, 0x8000, 0x400, 0x2800, 0x1ffff000, 0x800 }, // table 1, pm0063 { 0x413, "F4 device", 0x1FFF7A10, - 0x100000, 0x20000, 0x30000, 0x1fff0000, 0x7800 }, // table 1, pm0081 + 0x100000, 0x4000, 0x30000, 0x1fff0000, 0x7800 }, // table 1, pm0081 { 0x414, "F1 High-density device", 0x1ffff7e0, 0x80000, 0x800, 0x10000, 0x1ffff000, 0x800 }, // table 3 pm0063 // This ignores the EEPROM! (and uses the page erase size, @@ -160,21 +151,15 @@ int main(int argc, char** argv) { stlink_enter_swd_mode(sl); } - uint32_t chip_id = stlink_chip_id(sl); - uint32_t core_id = stlink_core_id(sl); - - /* Fix chip_id for F4 */ - if (((chip_id & 0xFFF) == 0x411) && (core_id == CORE_M4_R0)) { - printf("Fixing wrong chip_id for STM32F4 Rev A errata\n"); - chip_id = 0x413; - } + stlink_identify_device(sl); + printf("Chip ID is %08x, Core ID is %08x.\n", sl->chip_id, sl->core_id); - printf("Chip ID is %08x, Core ID is %08x.\n", chip_id, core_id); + sl->verbose=0; const struct chip_params* params = NULL; for(int i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { - if(devices[i].chip_id == (chip_id & 0xFFF)) { + if(devices[i].chip_id == (sl->chip_id & 0xFFF)) { params = &devices[i]; break; } diff --git a/gdbserver/st-util.exe b/gdbserver/st-util.exe new file mode 100644 index 0000000..e002f75 Binary files /dev/null and b/gdbserver/st-util.exe differ diff --git a/src/stlink-common.c b/src/stlink-common.c index a44e6e0..ed4a197 100644 --- a/src/stlink-common.c +++ b/src/stlink-common.c @@ -57,6 +57,35 @@ void DD(stlink_t *sl, char *format, ...) { #define FLASH_CR_STRT 6 #define FLASH_CR_LOCK 7 + +//32L = 32F1 same CoreID as 32F4! +#define STM32L_FLASH_REGS_ADDR ((uint32_t)0x40023c00) +#define STM32L_FLASH_ACR (STM32L_FLASH_REGS_ADDR + 0x00) +#define STM32L_FLASH_PECR (STM32L_FLASH_REGS_ADDR + 0x04) +#define STM32L_FLASH_PDKEYR (STM32L_FLASH_REGS_ADDR + 0x08) +#define STM32L_FLASH_PEKEYR (STM32L_FLASH_REGS_ADDR + 0x0c) +#define STM32L_FLASH_PRGKEYR (STM32L_FLASH_REGS_ADDR + 0x10) +#define STM32L_FLASH_OPTKEYR (STM32L_FLASH_REGS_ADDR + 0x14) +#define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18) +#define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x0c) +#define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20) + + +//STM32F4 +#define FLASH_F4_REGS_ADDR ((uint32_t)0x40023c00) +#define FLASH_F4_KEYR (FLASH_F4_REGS_ADDR + 0x04) +#define FLASH_F4_OPT_KEYR (FLASH_F4_REGS_ADDR + 0x08) +#define FLASH_F4_SR (FLASH_F4_REGS_ADDR + 0x0c) +#define FLASH_F4_CR (FLASH_F4_REGS_ADDR + 0x10) +#define FLASH_F4_OPT_CR (FLASH_F4_REGS_ADDR + 0x14) +#define FLASH_F4_CR_STRT 16 +#define FLASH_F4_CR_LOCK 31 +#define FLASH_F4_CR_SER 1 +#define FLASH_F4_CR_SNB 3 +#define FLASH_F4_CR_SNB_MASK 0x38 +#define FLASH_F4_SR_BSY 16 + + void write_uint32(unsigned char* buf, uint32_t ui) { if (!is_bigendian()) { // le -> le (don't swap) buf[0] = ((unsigned char*) &ui)[0]; @@ -115,13 +144,20 @@ static inline uint32_t read_flash_obr(stlink_t *sl) { } static inline uint32_t read_flash_cr(stlink_t *sl) { - stlink_read_mem32(sl, FLASH_CR, sizeof (uint32_t)); + if(sl->chip_id==STM32F4_CHIP_ID) + stlink_read_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); + else + stlink_read_mem32(sl, FLASH_CR, sizeof (uint32_t)); + fprintf(stdout, "CR:%X\n", *(uint32_t*) sl->q_buf); return *(uint32_t*) sl->q_buf; } static inline unsigned int is_flash_locked(stlink_t *sl) { /* return non zero for true */ - return read_flash_cr(sl) & (1 << FLASH_CR_LOCK); + if(sl->chip_id==STM32F4_CHIP_ID) + return read_flash_cr(sl) & (1 << FLASH_F4_CR_LOCK); + else + return read_flash_cr(sl) & (1 << FLASH_CR_LOCK); } static void unlock_flash(stlink_t *sl) { @@ -130,12 +166,19 @@ static void unlock_flash(stlink_t *sl) { an invalid sequence results in a definitive lock of the FPEC block until next reset. */ + if(sl->chip_id==STM32F4_CHIP_ID) { + write_uint32(sl->q_buf, FLASH_KEY1); + stlink_write_mem32(sl, FLASH_F4_KEYR, sizeof (uint32_t)); + write_uint32(sl->q_buf, FLASH_KEY2); + stlink_write_mem32(sl, FLASH_F4_KEYR, sizeof (uint32_t)); + } + else { + write_uint32(sl->q_buf, FLASH_KEY1); + stlink_write_mem32(sl, FLASH_KEYR, sizeof (uint32_t)); + write_uint32(sl->q_buf, FLASH_KEY2); + stlink_write_mem32(sl, FLASH_KEYR, sizeof (uint32_t)); + } - write_uint32(sl->q_buf, FLASH_KEY1); - stlink_write_mem32(sl, FLASH_KEYR, sizeof (uint32_t)); - - write_uint32(sl->q_buf, FLASH_KEY2); - stlink_write_mem32(sl, FLASH_KEYR, sizeof (uint32_t)); } static int unlock_flash_if(stlink_t *sl) { @@ -151,24 +194,41 @@ static int unlock_flash_if(stlink_t *sl) { } static void lock_flash(stlink_t *sl) { - /* write to 1 only. reset by hw at unlock sequence */ - - const uint32_t n = read_flash_cr(sl) | (1 << FLASH_CR_LOCK); - - write_uint32(sl->q_buf, n); - stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + if(sl->chip_id==STM32F4_CHIP_ID) { + const uint32_t n = read_flash_cr(sl) | (1 << FLASH_F4_CR_LOCK); + write_uint32(sl->q_buf, n); + stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); + } + else { + /* write to 1 only. reset by hw at unlock sequence */ + const uint32_t n = read_flash_cr(sl) | (1 << FLASH_CR_LOCK); + write_uint32(sl->q_buf, n); + stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + } } + static void set_flash_cr_pg(stlink_t *sl) { - const uint32_t n = 1 << FLASH_CR_PG; - write_uint32(sl->q_buf, n); - stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + if(sl->chip_id==STM32F4_CHIP_ID) { + uint32_t x = read_flash_cr(sl); + x |= (1 << FLASH_CR_PG); + write_uint32(sl->q_buf, x); + stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); + } + else { + const uint32_t n = 1 << FLASH_CR_PG; + write_uint32(sl->q_buf, n); + stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + } } static void __attribute__((unused)) clear_flash_cr_pg(stlink_t *sl) { const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG); write_uint32(sl->q_buf, n); - stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + if(sl->chip_id==STM32F4_CHIP_ID) + stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); + else + stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); } static void set_flash_cr_per(stlink_t *sl) { @@ -196,10 +256,19 @@ static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) { } static void set_flash_cr_strt(stlink_t *sl) { - /* assume come on the flash_cr_per path */ - const uint32_t n = (1 << FLASH_CR_PER) | (1 << FLASH_CR_STRT); - write_uint32(sl->q_buf, n); - stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + if(sl->chip_id == STM32F4_CHIP_ID) + { + uint32_t x = read_flash_cr(sl); + x |= (1 << FLASH_F4_CR_STRT); + write_uint32(sl->q_buf, x); + stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); + } + else { + /* assume come on the flash_cr_per path */ + const uint32_t n = (1 << FLASH_CR_PER) | (1 << FLASH_CR_STRT); + write_uint32(sl->q_buf, n); + stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t)); + } } static inline uint32_t read_flash_acr(stlink_t *sl) { @@ -208,12 +277,19 @@ static inline uint32_t read_flash_acr(stlink_t *sl) { } static inline uint32_t read_flash_sr(stlink_t *sl) { - stlink_read_mem32(sl, FLASH_SR, sizeof (uint32_t)); - return *(uint32_t*) sl->q_buf; + if(sl->chip_id==STM32F4_CHIP_ID) + stlink_read_mem32(sl, FLASH_F4_SR, sizeof (uint32_t)); + else + stlink_read_mem32(sl, FLASH_SR, sizeof (uint32_t)); + //fprintf(stdout, "SR:%X\n", *(uint32_t*) sl->q_buf); + return *(uint32_t*) sl->q_buf; } static inline unsigned int is_flash_busy(stlink_t *sl) { - return read_flash_sr(sl) & (1 << FLASH_SR_BSY); + if(sl->chip_id==STM32F4_CHIP_ID) + return read_flash_sr(sl) & (1 << FLASH_F4_SR_BSY); + else + return read_flash_sr(sl) & (1 << FLASH_SR_BSY); } static void wait_flash_busy(stlink_t *sl) { @@ -243,6 +319,26 @@ static inline void write_flash_ar(stlink_t *sl, uint32_t n) { stlink_write_mem32(sl, FLASH_AR, sizeof (uint32_t)); } +static inline void write_flash_cr_psiz(stlink_t *sl, uint32_t n) { + uint32_t x = read_flash_cr(sl); + x &= ~(0x03 << 8); + x |= (n << 8); + fprintf(stdout, "PSIZ:%X %X\n", x, n); + write_uint32(sl->q_buf, x); + stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); +} + + +static inline void write_flash_cr_snb(stlink_t *sl, uint32_t n) { + uint32_t x = read_flash_cr(sl); + x &= ~FLASH_F4_CR_SNB_MASK; + x |= (n << FLASH_F4_CR_SNB); + x |= (1 << FLASH_F4_CR_SER); + fprintf(stdout, "SNB:%X %X\n", x, n); + write_uint32(sl->q_buf, x); + stlink_write_mem32(sl, FLASH_F4_CR, sizeof (uint32_t)); +} + #if 0 /* todo */ static void disable_flash_read_protection(stlink_t *sl) { @@ -290,11 +386,18 @@ uint32_t stlink_core_id(stlink_t *sl) { return sl->core_id; } -uint16_t stlink_chip_id(stlink_t *sl) { - stlink_read_mem32(sl, 0xE0042000, 4); +void stlink_identify_device(stlink_t *sl) { + uint32_t core_id=stlink_core_id(sl); + stlink_read_mem32(sl, 0xE0042000, 4); uint32_t chip_id = sl->q_buf[0] | (sl->q_buf[1] << 8) | (sl->q_buf[2] << 16) | (sl->q_buf[3] << 24); - return chip_id; + /* Fix chip_id for F4 */ + if (((chip_id & 0xFFF) == 0x411) && (core_id == CORE_M4_R0)) { + printf("Fixing wrong chip_id for STM32F4 Rev A errata\n"); + chip_id = 0x413; + } + sl->chip_id=chip_id; + sl->core_id=core_id; } /** @@ -702,23 +805,65 @@ int write_buffer_to_sram(stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, s return 0; } +uint32_t calculate_F4_sectornum(uint32_t flashaddr){ + flashaddr &= ~STM32_FLASH_BASE; //Page now holding the actual flash address + if (flashaddr<0x4000) return (0); + else if(flashaddr<0x8000) return(1); + else if(flashaddr<0xc000) return(2); + else if(flashaddr<0x10000) return(3); + else if(flashaddr<0x20000) return(4); + else return(flashaddr/0x20000)+4; + +} + +uint32_t calculate_sectorsize(stlink_t *sl, uint32_t flashaddr){ + if(sl->chip_id == STM32F4_CHIP_ID) { + uint32_t sector=calculate_F4_sectornum(flashaddr); + if (sector<4) return (0x4000); + else if(sector<5) return(0x10000); + else return(0x20000); + } + else return (sl->flash_pgsz); +} + int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) { /* page an addr in the page to erase */ - stlink_core_id(sl); - if (sl->core_id == STM32L_CORE_ID) + stlink_identify_device(sl); + + if (sl->chip_id == STM32F4_CHIP_ID) + { + /* wait for ongoing op to finish */ + wait_flash_busy(sl); + + /* unlock if locked */ + unlock_flash_if(sl); + + /* select the page to erase */ + //Page is passed to us as an addr, so calculate the actual page + uint32_t addr=page; + + page=calculate_F4_sectornum(addr); + + fprintf(stderr, "Erasing Sector:%u SectorSize:%u\n", page, calculate_sectorsize(sl, addr)); + write_flash_cr_snb(sl, page); + + /* start erase operation */ + set_flash_cr_strt(sl); + + /* wait for completion */ + wait_flash_busy(sl); + + /* relock the flash */ + //todo: fails to program if this is in + lock_flash(sl); + fprintf(stdout, "Erase Final CR:%X\n", read_flash_cr(sl)); + + } + + else if (sl->core_id == STM32L_CORE_ID) { -#define STM32L_FLASH_REGS_ADDR ((uint32_t)0x40023c00) -#define STM32L_FLASH_ACR (STM32L_FLASH_REGS_ADDR + 0x00) -#define STM32L_FLASH_PECR (STM32L_FLASH_REGS_ADDR + 0x04) -#define STM32L_FLASH_PDKEYR (STM32L_FLASH_REGS_ADDR + 0x08) -#define STM32L_FLASH_PEKEYR (STM32L_FLASH_REGS_ADDR + 0x0c) -#define STM32L_FLASH_PRGKEYR (STM32L_FLASH_REGS_ADDR + 0x10) -#define STM32L_FLASH_OPTKEYR (STM32L_FLASH_REGS_ADDR + 0x14) -#define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18) -#define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x0c) -#define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20) uint32_t val; @@ -814,8 +959,9 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) /* relock the flash */ lock_flash(sl); } + else { - fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + fprintf(stderr, "unknown device!\n"); return -1; } @@ -952,11 +1098,15 @@ int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { return res; } - int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned len) { size_t off; flash_loader_t fl; + stlink_identify_device(sl); + + fprintf(stdout, "WriteFlash - addr:%x len:%x\n", addr, len); + fprintf(stdout, "CoreID:%X ChipID:%X\n", sl->core_id, sl->chip_id); + /* check addr range is inside the flash */ if (addr < sl->flash_base) { fprintf(stderr, "addr too low\n"); @@ -976,165 +1126,206 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned } /* erase each page */ - for (off = 0; off < len; off += sl->flash_pgsz) { + for (off = 0; off < len; off += calculate_sectorsize(sl, addr + off) ) { /* addr must be an addr inside the page */ if (stlink_erase_flash_page(sl, addr + off) == -1) { - fprintf(stderr, "erase_flash_page(0x%zx) == -1\n", addr + off); + fprintf(stderr, "erase_flash_page(0x%zx) == -1\n", addr + off); return -1; } } - stlink_core_id(sl); - if (sl->core_id == STM32L_CORE_ID) - { - /* use fast word write. todo: half page. */ + if (sl->chip_id == STM32F4_CHIP_ID) { + /* todo: check write operation */ - uint32_t val; + /* First unlock the cr */ + unlock_flash_if(sl); -#if 0 /* todo: check write operation */ + /* set parallelisim to 32 bit*/ + write_flash_cr_psiz(sl, 2); - uint32_t nwrites = sl->flash_pgsz; + /* set programming mode */ + set_flash_cr_pg(sl); - redo_write: +#define PROGRESS_CHUNK_SIZE 0x1000 + /* write a word in program memory */ + for (off = 0; off < len; off += sizeof(uint32_t)) { + if (sl->verbose >= 1) { + if ((off & (PROGRESS_CHUNK_SIZE - 1)) == 0) { + /* show progress. writing procedure is slow + and previous errors are misleading */ + const uint32_t pgnum = (off / PROGRESS_CHUNK_SIZE)+1; + const uint32_t pgcount = len / PROGRESS_CHUNK_SIZE; + fprintf(stdout, "Writing %ukB chunk %u out of %u\n", PROGRESS_CHUNK_SIZE/1024, pgnum, pgcount); + } + } -#endif /* todo: check write operation */ + memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t)); + stlink_write_mem32(sl, addr + off, sizeof(uint32_t)); - /* disable pecr protection */ - write_uint32(sl->q_buf, 0x89abcdef); - stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t)); - write_uint32(sl->q_buf, 0x02030405); - stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t)); - - /* check pecr.pelock is cleared */ - stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); - val = read_uint32(sl->q_buf, 0); - if (val & (1 << 0)) - { - fprintf(stderr, "pecr.pelock not clear\n"); - return -1; - } + /* wait for sr.busy to be cleared */ + wait_flash_busy(sl); - /* unlock program memory */ - write_uint32(sl->q_buf, 0x8c9daebf); - stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t)); - write_uint32(sl->q_buf, 0x13141516); - stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t)); - - /* check pecr.prglock is cleared */ - stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); - val = read_uint32(sl->q_buf, 0); - if (val & (1 << 1)) - { - fprintf(stderr, "pecr.prglock not clear\n"); - return -1; - } + } + /* Relock flash */ + lock_flash(sl); + fprintf(stdout, "Final CR:%X\n", read_flash_cr(sl)); - /* write a word in program memory */ - for (off = 0; off < len; off += sizeof(uint32_t)) - { - if (sl->verbose >= 1) - { - if ((off & (sl->flash_pgsz - 1)) == 0) - { - /* show progress. writing procedure is slow - and previous errors are misleading */ - const uint32_t pgnum = off / sl->flash_pgsz; - const uint32_t pgcount = len / sl->flash_pgsz; - fprintf(stdout, "%u pages written out of %u\n", pgnum, pgcount); - } - } - memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t)); - stlink_write_mem32(sl, addr + off, sizeof(uint32_t)); - /* wait for sr.busy to be cleared */ - while (1) - { - stlink_read_mem32(sl, STM32L_FLASH_SR, sizeof(uint32_t)); - if ((read_uint32(sl->q_buf, 0) & (1 << 0)) == 0) break ; - } + } //STM32F4END + + else if (sl->core_id == STM32L_CORE_ID) { + /* use fast word write. todo: half page. */ + + uint32_t val; + +#if 0 /* todo: check write operation */ + + uint32_t nwrites = sl->flash_pgsz; + + redo_write: + +#endif /* todo: check write operation */ + + /* disable pecr protection */ + write_uint32(sl->q_buf, 0x89abcdef); + stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t)); + write_uint32(sl->q_buf, 0x02030405); + stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t)); + + /* check pecr.pelock is cleared */ + stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + val = read_uint32(sl->q_buf, 0); + if (val & (1 << 0)) { + fprintf(stderr, "pecr.pelock not clear\n"); + return -1; + } + + /* unlock program memory */ + write_uint32(sl->q_buf, 0x8c9daebf); + stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t)); + write_uint32(sl->q_buf, 0x13141516); + stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t)); + + /* check pecr.prglock is cleared */ + stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + val = read_uint32(sl->q_buf, 0); + if (val & (1 << 1)) { + fprintf(stderr, "pecr.prglock not clear\n"); + return -1; + } + + /* write a word in program memory */ + for (off = 0; off < len; off += sizeof(uint32_t)) { + if (sl->verbose >= 1) { + if ((off & (sl->flash_pgsz - 1)) == 0) { + /* show progress. writing procedure is slow + and previous errors are misleading */ + const uint32_t pgnum = off / sl->flash_pgsz; + const uint32_t pgcount = len / sl->flash_pgsz; + fprintf(stdout, "%u pages written out of %u\n", pgnum, pgcount); + } + } + + memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t)); + stlink_write_mem32(sl, addr + off, sizeof(uint32_t)); + + /* wait for sr.busy to be cleared */ + while (1) { + stlink_read_mem32(sl, STM32L_FLASH_SR, sizeof(uint32_t)); + if ((read_uint32(sl->q_buf, 0) & (1 << 0)) == 0) break ; + } #if 0 /* todo: check redo write operation */ - /* check written bytes. todo: should be on a per page basis. */ - stlink_read_mem32(sl, addr + off, sizeof(uint32_t)); - if (memcmp(sl->q_buf, base + off, sizeof(uint32_t))) - { - /* re erase the page and redo the write operation */ - uint32_t page; - uint32_t val; + /* check written bytes. todo: should be on a per page basis. */ + stlink_read_mem32(sl, addr + off, sizeof(uint32_t)); + if (memcmp(sl->q_buf, base + off, sizeof(uint32_t))) { + /* re erase the page and redo the write operation */ + uint32_t page; + uint32_t val; - /* fail if successive write count too low */ - if (nwrites < sl->flash_pgsz) { - fprintf(stderr, "writes operation failure count too high, aborting\n"); - return -1; - } + /* fail if successive write count too low */ + if (nwrites < sl->flash_pgsz) { + fprintf(stderr, "writes operation failure count too high, aborting\n"); + return -1; + } - nwrites = 0; + nwrites = 0; - /* assume addr aligned */ - if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1); - page = addr + off; + /* assume addr aligned */ + if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1); + page = addr + off; - fprintf(stderr, "invalid write @%x(%x): %x != %x. retrying.\n", - page, addr + off, read_uint32(base + off, 0), read_uint32(sl->q_buf, 0)); + fprintf(stderr, "invalid write @%x(%x): %x != %x. retrying.\n", + page, addr + off, read_uint32(base + off, 0), read_uint32(sl->q_buf, 0)); - /* reset lock bits */ - stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); - val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2); - write_uint32(sl->q_buf, val); - stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + /* reset lock bits */ + stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2); + write_uint32(sl->q_buf, val); + stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); - stlink_erase_flash_page(sl, page); + stlink_erase_flash_page(sl, page); - goto redo_write; - } + goto redo_write; + } - /* increment successive writes counter */ - ++nwrites; + /* increment successive writes counter */ + ++nwrites; #endif /* todo: check redo write operation */ + } + /* reset lock bits */ + stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2); + write_uint32(sl->q_buf, val); + stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + } - } - /* reset lock bits */ - stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); - val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2); - write_uint32(sl->q_buf, val); - stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); - } - else if (sl->core_id == STM32VL_CORE_ID) - { - /* flash loader initialization */ - if (init_flash_loader(sl, &fl) == -1) { - fprintf(stderr, "init_flash_loader() == -1\n"); - return -1; - } - /* write each page. above WRITE_BLOCK_SIZE fails? */ -#define WRITE_BLOCK_SIZE 0x40 - for (off = 0; off < len; off += WRITE_BLOCK_SIZE) - { - /* adjust last write size */ - size_t size = WRITE_BLOCK_SIZE; - if ((off + WRITE_BLOCK_SIZE) > len) size = len - off; - - /* unlock and set programming mode */ - unlock_flash_if(sl); - set_flash_cr_pg(sl); - - if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) { - fprintf(stderr, "run_flash_loader(0x%zx) == -1\n", addr + off); - return -1; - } - lock_flash(sl); + else if (sl->core_id == STM32VL_CORE_ID) { + /* flash loader initialization */ + if (init_flash_loader(sl, &fl) == -1) { + fprintf(stderr, "init_flash_loader() == -1\n"); + return -1; + } + /* write each page. above WRITE_BLOCK_SIZE fails? */ +#define WRITE_BLOCK_SIZE 0x40 + for (off = 0; off < len; off += WRITE_BLOCK_SIZE) { + /* adjust last write size */ + size_t size = WRITE_BLOCK_SIZE; + if ((off + WRITE_BLOCK_SIZE) > len) size = len - off; + + /* unlock and set programming mode */ + unlock_flash_if(sl); + set_flash_cr_pg(sl); + + if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) { + fprintf(stderr, "run_flash_loader(0x%zx) == -1\n", addr + off); + return -1; + } + lock_flash(sl); } - } else { - fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + } + + + + + else + { + fprintf(stderr, "unknown device!\n"); return -1; } + + + + +#if(0) + //todo: F4 Can't stlink_read_mem32 an entire sector, not enough ram! for (off = 0; off < len; off += sl->flash_pgsz) { size_t aligned_size; @@ -1147,15 +1338,20 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned if (aligned_size & (4 - 1)) aligned_size = (cmp_size + 4) & ~(4 - 1); + fprintf(stdout, "AlignedSize:%x\n", aligned_size); stlink_read_mem32(sl, addr + off, aligned_size); if (memcmp(sl->q_buf, base + off, cmp_size)) return -1; } +#endif return 0; } + + + int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { /* write the file in flash at addr */ diff --git a/src/stlink-common.h b/src/stlink-common.h index 2fe04e1..2230dca 100644 --- a/src/stlink-common.h +++ b/src/stlink-common.h @@ -81,6 +81,17 @@ extern "C" { #define STM32L_CORE_ID 0x2ba01477 #define STM32F4_CORE_ID 0x2ba01477 +/* + * Chip IDs are explained in the appropriate programming manual for the + * DBGMCU_IDCODE register (0xE0042000) + */ +#define CORE_M3_R1 0x1BA00477 +#define CORE_M3_R2 0x4BA00477 +#define CORE_M4_R0 0x2BA01477 + +/* using chip id for F4 ident, since core id is same as F1 */ +#define STM32F4_CHIP_ID 0x413 + /* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/ #define C_BUF_LEN 32 @@ -159,6 +170,7 @@ extern "C" { // transport layer verboseness: 0 for no debug info, 10 for lots int verbose; uint32_t core_id; + uint16_t chip_id; int core_stat; @@ -168,6 +180,10 @@ extern "C" { #define STM32_FLASH_SIZE (128 * 1024) #define STM32_FLASH_PGSZ 1024 #define STM32L_FLASH_PGSZ 256 + +#define STM32F4_FLASH_PGSZ 16384 +#define STM32F4_FLASH_SIZE (128 * 1024 * 8) + stm32_addr_t flash_base; size_t flash_size; size_t flash_pgsz; @@ -200,6 +216,7 @@ extern "C" { void stlink_exit_dfu_mode(stlink_t *sl); void stlink_close(stlink_t *sl); uint32_t stlink_core_id(stlink_t *sl); + void stlink_identify_device(stlink_t *sl); void stlink_reset(stlink_t *sl); void stlink_run(stlink_t *sl); void stlink_status(stlink_t *sl); diff --git a/src/stlink-usb.c b/src/stlink-usb.c index 4fb3a1c..63eddab 100644 --- a/src/stlink-usb.c +++ b/src/stlink-usb.c @@ -692,8 +692,26 @@ stlink_t* stlink_open_usb(const int verbose) { stlink_version(sl); /* per device family initialization */ - stlink_core_id(sl); - if (sl->core_id == STM32L_CORE_ID) { + stlink_identify_device(sl); + + if (sl->chip_id == STM32F4_CHIP_ID) { + + /* flash memory settings */ + sl->flash_base = STM32_FLASH_BASE; + sl->flash_size = STM32F4_FLASH_SIZE; + sl->flash_pgsz = STM32F4_FLASH_PGSZ; //Dummy, pages size is variable in this config + + /* system memory */ + sl->sys_base = STM32_SYSTEM_BASE; + sl->sys_size = STM32_SYSTEM_SIZE; + + /* sram memory settings */ + sl->sram_base = STM32_SRAM_BASE; + sl->sram_size = STM32_SRAM_SIZE; + + } + + else if (sl->core_id == STM32L_CORE_ID) { /* flash memory settings */ sl->flash_base = STM32_FLASH_BASE; @@ -708,7 +726,8 @@ stlink_t* stlink_open_usb(const int verbose) { sl->sram_base = STM32_SRAM_BASE; sl->sram_size = STM32L_SRAM_SIZE; - } else if (sl->core_id == STM32VL_CORE_ID) { + } + else if (sl->core_id == STM32VL_CORE_ID) { /* flash memory settings */ sl->flash_base = STM32_FLASH_BASE; @@ -723,11 +742,10 @@ stlink_t* stlink_open_usb(const int verbose) { sl->sram_base = STM32_SRAM_BASE; sl->sram_size = STM32_SRAM_SIZE; - } else { - + } + else { fprintf(stderr, "unknown coreid: %x\n", sl->core_id); goto on_libusb_error; - } error = 0; diff --git a/src/test_usb.c b/src/test_usb.c index 343e355..4901a8f 100644 --- a/src/test_usb.c +++ b/src/test_usb.c @@ -27,8 +27,9 @@ int main(int ac, char** av) { printf("-- mode after entering swd mode: %d\n", stlink_current_mode(sl)); - printf("-- chip id: %#x\n", stlink_chip_id(sl)); - printf("-- core_id: %#x\n", stlink_core_id(sl)); + stlink_identify_device(sl); + printf("-- chip id: %#x\n", sl->chip_id); + printf("-- core_id: %#x\n", sl->core_id); cortex_m3_cpuid_t cpuid; stlink_cpu_id(sl, &cpuid); diff --git a/test_usb.exe b/test_usb.exe new file mode 100644 index 0000000..8523d69 Binary files /dev/null and b/test_usb.exe differ diff --git a/usb.txt b/usb.txt new file mode 100644 index 0000000..e5ddf63 --- /dev/null +++ b/usb.txt @@ -0,0 +1,127 @@ +-- version +mode before doing anything: 2 +-- enter_swd_mode +-- mode after entering swd mode: 2 +data_len = 4 0x4 + 11 64 00 20 + +-- chip id: 0x6411 +data_len = 4 0x4 + 77 14 a0 2b + +-- core_id: 0x2ba01477 +data_len = 4 0x4 + 41 c2 0f 41 + +cpuid:impl_id = 0x41, variant = 0 +cpuid:part = 0xc24, rev = 0x1 +-- read_sram +data_len = 4 0x4 + 00 40 00 20 + +data_len = 4 0x4 + 55 0c 00 08 + +data_len = 4 0x4 + 99 0c 00 08 + +data_len = 4 0x4 + 99 0c 00 08 + +FP_CTRL +data_len = 4 0x4 + 60 02 00 00 + +data_len = 4 0x4 + 67 45 23 01 + +data_len = 4 0x4 + ef cd ab 89 + +data_len = 4 0x4 + 67 45 23 62 + +data_len = 4 0x4 + ef cd ab 75 + +-- status +-- reset +data_len = 2 0x2 + 80 00 + +data_len = 2 0x2 + 80 00 + +data_len = 2 0x2 + 80 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 67 45 23 01 + +data_len = 4 0x4 + ef cd ab 89 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 40 00 20 + +data_len = 4 0x4 + ff ff ff ff + +data_len = 4 0x4 + 78 56 34 12 + +data_len = 4 0x4 + 00 00 00 01 + +data_len = 4 0x4 + 00 40 00 20 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 4 0x4 + 00 00 00 00 + +data_len = 84 0x54 + 00 00 00 00 00 00 00 00 00 00 00 00 67 45 23 01 ef cd ab 89 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 20 ff ff ff ff 78 56 34 12 00 00 00 01 00 40 00 20 00 00 00 00 00 00 00 00 00 00 00 00 + +-- status +-- step +-- run +-- exit_debug_mode