From: Karl Palsson Date: Fri, 4 Nov 2011 02:51:15 +0000 (+0000) Subject: Merge branch 'master' of https://github.com/texane/stlink X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=c98c487fa52651505871de11d65bacaeaf1cac39;hp=52b626bd16ae76df6c40d93c1d10efd334f01cec;p=fw%2Fstlink Merge branch 'master' of https://github.com/texane/stlink Conflicts: Makefile doc/tutorial/tutorial.pdf example/blink/Makefile flash/main.c src/stlink-common.c src/stlink-usb.c Mostly whitespace conflicts it seems. --- diff --git a/AUTHORS b/AUTHORS index 0abaac6..8fbc20e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,4 +8,5 @@ h0rr0rrdrag@gmail.com mstempin@com1.fr bon@elektron.ikp.physik.tu-darmstadt.de nelsonjm@macpod.neta -ned@bike-nomad.com \ No newline at end of file +ned@bike-nomad.com +csamuelson@swingpal.com diff --git a/Makefile b/Makefile index 646dde1..d35b3c4 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ VPATH=src SOURCES_LIB=stlink-common.c stlink-usb.c stlink-sg.c uglylogging.c OBJS_LIB=$(SOURCES_LIB:.c=.o) TEST_PROGRAMS=test_usb test_sg -LDFLAGS=-lusb-1.0 -L. -lstlink +LDFLAGS=-L. -lstlink -lusb-1.0 CFLAGS+=-g CFLAGS+=-DDEBUG=1 diff --git a/TODO b/TODO index e415e57..2b0baf6 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,5 @@ . flash tool - . test support for reading - . writing is not working. refer to the specs, may have changed for stm32l - . then test with blink_flash example - . then update the documentation + . improve flash writing, still use word fast write... too slow . documentation . make README points to doc/tutorial diff --git a/doc/tutorial/tutorial.pdf b/doc/tutorial/tutorial.pdf index 70546cb..856977b 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 4aafa20..c3615df 100644 --- a/doc/tutorial/tutorial.tex +++ b/doc/tutorial/tutorial.tex @@ -90,8 +90,8 @@ It includes: \newpage - -\section{Building and running a program} +\section{Building and running a program in SRAM} +\paragraph{} A simple LED blinking example is provided in the example directory. It is built using:\\ \begin{small} \begin{lstlisting}[frame=tb] @@ -165,10 +165,9 @@ $> continue All the LEDs on the board should now be blinking in time (those leds are near the user and reset buttons). \newpage -\section{Reading and writing to flash} +\section{Building and flashing a program} \paragraph{} -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:\\ +FLASH memory reading and writing is done by a separate tool, as shown below:\\ \begin{small} \begin{lstlisting}[frame=tb] # change to the flash tool directory @@ -188,6 +187,49 @@ $> ./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} +\paragraph{} +CHIBIOS is an open source RTOS. More information can be found on the project website: +\begin{center} +http://www.chibios.org/dokuwiki/doku.php +\end{center} + +\paragraph{} +It supports several boards, including the STM32L DISCOVERY kit: +\begin{center} +http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:stm32l\_discovery +\end{center} + +\paragraph{} +The installation procedure is detailed below:\\ +\begin{small} +\begin{lstlisting}[frame=tb] +# checkout and build CHIBIOS for STM32L DISCOVERY kits +svn checkout https://chibios.svn.sourceforge.net/svnroot/chibios/trunk +cd chibios/trunk/demos/ARMCM3-STM32L152-DISCOVERY +PATH=$TOOLCHAIN_PATH:$PATH make + +# flash the image into STM32L +sudo ./flash write build/ch.bin 0x08000000 +\end{lstlisting} +\end{small} \newpage \section{Notes} diff --git a/example/blink_flash/Makefile b/example/blink_flash/Makefile index 7776471..4611731 100644 --- a/example/blink_flash/Makefile +++ b/example/blink_flash/Makefile @@ -4,11 +4,9 @@ BIN_IMAGE=blink.bin CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -CFLAGS=-O2 -mlittle-endian -mthumb - -CFLAGS=-g -O2 -mlittle-endian -mthumb +CFLAGS=-O3 -mlittle-endian -mthumb ifeq ($(CONFIG_STM32L_DISCOVERY), 1) - CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY + 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) @@ -16,18 +14,24 @@ else ifeq ($(CONFIG_STM32F4_DISCOVERY), 1) else $(error "must specify CONFIG_ for board!") endif - CFLAGS+=-ffreestanding -nostdlib -nostdinc +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 startup_stm32l1xx_md.s - $(CC) $(CFLAGS) $^ -o $@ +$(EXECUTABLE): main.c system_stm32l1xx.c startup_stm32l1xx_md.s + $(CC) $(CFLAGS) $^ -o $@ -L../libstm32l_discovery/build -lstm32l_discovery clean: rm -rf $(EXECUTABLE) diff --git a/example/blink_flash/discover_board.h b/example/blink_flash/discover_board.h new file mode 100644 index 0000000..d93a184 --- /dev/null +++ b/example/blink_flash/discover_board.h @@ -0,0 +1,61 @@ + /** + ****************************************************************************** + * @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/blink_flash/main.c b/example/blink_flash/main.c index e93fd72..d27ef7f 100644 --- a/example/blink_flash/main.c +++ b/example/blink_flash/main.c @@ -1,13 +1,23 @@ -/* missing type */ +/* base headers */ +#include "stdint.h" -typedef unsigned int uint32_t; +/* libstm32l_discovery headers */ +#include "stm32l1xx_gpio.h" +#include "stm32l1xx_adc.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 */ - -#define CONFIG_STM32L_DISCOVERY 1 -#define CONFIG_STM32VL_DISCOVERY 0 +/* hardware configuration */ #if CONFIG_STM32VL_DISCOVERY @@ -35,7 +45,6 @@ static inline void switch_leds_off(void) #elif CONFIG_STM32L_DISCOVERY -# define GPIOB 0x40020400 /* port B */ # define GPIOB_MODER (GPIOB + 0x00) /* port mode register */ # define GPIOB_ODR (GPIOB + 0x14) /* port output data register */ @@ -50,12 +59,14 @@ static inline void setup_leds(void) static inline void switch_leds_on(void) { - *(volatile uint32_t*)GPIOB_ODR = LED_BLUE | LED_GREEN; + 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) { - *(volatile uint32_t*)GPIOB_ODR = 0; + GPIO_LOW(LD_GPIO_PORT, LD_GREEN_GPIO_PIN); + GPIO_LOW(LD_GPIO_PORT, LD_BLUE_GPIO_PIN); } #endif /* otherwise, error */ @@ -63,14 +74,87 @@ static inline void switch_leds_off(void) #define delay() \ do { \ - register unsigned int i; \ + volatile unsigned int i; \ for (i = 0; i < 1000000; ++i) \ __asm__ __volatile__ ("nop\n\t":::"memory"); \ } while (0) + +static void RCC_Configuration(void) +{ + /* Enable HSI Clock */ + RCC_HSICmd(ENABLE); + + /*!< Wait till HSI is ready */ + while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET) + {} + + RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); + + RCC_MSIRangeConfig(RCC_MSIRange_6); + + 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); + +} + void main(void) { - setup_leds(); + static RCC_ClocksTypeDef RCC_Clocks; + static GPIO_InitTypeDef GPIO_InitStructure; + + /* Configure Clocks for Application need */ + RCC_Configuration(); + + /* Configure RTC Clocks */ + RTC_Configuration(); + + /* 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) ; + + /* 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); while (1) { diff --git a/example/blink_flash/startup_stm32l1xx_md.s b/example/blink_flash/startup_stm32l1xx_md.s index 4ec8203..9a8389c 100644 --- a/example/blink_flash/startup_stm32l1xx_md.s +++ b/example/blink_flash/startup_stm32l1xx_md.s @@ -62,7 +62,6 @@ defined in linker script */ .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: - /* Copy the data segment initializers from flash to SRAM */ movs r1, #0 b LoopCopyDataInit @@ -92,7 +91,7 @@ LoopFillZerobss: bcc FillZerobss /* Call the clock system intitialization function.*/ /* let main do the system initialization */ -/* bl SystemInit */ + bl SystemInit /* Call the application's entry point.*/ bl main bx lr diff --git a/example/dac/Makefile b/example/dac/Makefile new file mode 100644 index 0000000..84db69e --- /dev/null +++ b/example/dac/Makefile @@ -0,0 +1,43 @@ +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 new file mode 100644 index 0000000..d93a184 --- /dev/null +++ b/example/dac/discover_board.h @@ -0,0 +1,61 @@ + /** + ****************************************************************************** + * @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 new file mode 100644 index 0000000..1f89d33 --- /dev/null +++ b/example/dac/main.c @@ -0,0 +1,242 @@ +/* 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 new file mode 100644 index 0000000..9a8389c --- /dev/null +++ b/example/dac/startup_stm32l1xx_md.s @@ -0,0 +1,365 @@ +/** + ****************************************************************************** + * @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 new file mode 100644 index 0000000..146b16e --- /dev/null +++ b/example/dac/stm32_flash.ld @@ -0,0 +1,173 @@ +/* +***************************************************************************** +** +** 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 new file mode 100644 index 0000000..6deab32 --- /dev/null +++ b/example/dac/system_stm32l1xx.c @@ -0,0 +1,367 @@ +/** + ****************************************************************************** + * @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/flash/Makefile b/flash/Makefile index 8a30b41..9fa6743 100644 --- a/flash/Makefile +++ b/flash/Makefile @@ -12,7 +12,7 @@ CFLAGS+=-std=gnu99 CFLAGS+=-Wall -Wextra CFLAGS+=-I../src -LDFLAGS=-lusb-1.0 -L.. -lstlink +LDFLAGS=-L.. -lstlink -lusb-1.0 ifeq ($(CONFIG_USE_LIBSG),) CONFIG_USE_LIBSG=1 diff --git a/gdbserver/Makefile b/gdbserver/Makefile index a8d1b90..a10a0d8 100644 --- a/gdbserver/Makefile +++ b/gdbserver/Makefile @@ -9,7 +9,7 @@ OBJS = gdb-remote.o gdb-server.o CFLAGS+=-g -Wall -Werror -std=gnu99 -I../src CFLAGS+=-DCONFIG_USE_LIBUSB=1 -LDFLAGS=-lusb-1.0 -L.. -lstlink +LDFLAGS=-L.. -lstlink -lusb-1.0 ifeq ($(CONFIG_USE_LIBSG),) CONFIG_USE_LIBSG=1 diff --git a/src/stlink-common.c b/src/stlink-common.c index 8f3431a..f58c344 100644 --- a/src/stlink-common.c +++ b/src/stlink-common.c @@ -21,9 +21,9 @@ #define WLOG(format, args...) ugly_log(UWARN, LOG_TAG, format, ## args) #define fatal(format, args...) ugly_log(UFATAL, LOG_TAG, format, ## args) +/* todo: stm32l15xxx flash memory, pm0062 manual */ -/* FPEC flash controller interface, pm0063 manual - */ +/* stm32f FPEC flash controller interface, pm0063 manual */ #define FLASH_REGS_ADDR 0x40022000 #define FLASH_REGS_SIZE 0x28 @@ -78,7 +78,7 @@ uint32_t read_uint32(const unsigned char *c, const int pt) { char *p = (char *) &ui; if (!is_bigendian()) { // le -> le (don't swap) - p[0] = c[pt]; + p[0] = c[pt + 0]; p[1] = c[pt + 1]; p[2] = c[pt + 2]; p[3] = c[pt + 3]; @@ -86,7 +86,7 @@ uint32_t read_uint32(const unsigned char *c, const int pt) { p[0] = c[pt + 3]; p[1] = c[pt + 2]; p[2] = c[pt + 1]; - p[3] = c[pt]; + p[3] = c[pt + 0]; } return ui; } @@ -458,11 +458,11 @@ uint16_t read_uint16(const unsigned char *c, const int pt) { char *p = (char *) &ui; if (!is_bigendian()) { // le -> le (don't swap) - p[0] = c[pt]; + p[0] = c[pt + 0]; p[1] = c[pt + 1]; } else { p[0] = c[pt + 1]; - p[1] = c[pt]; + p[1] = c[pt + 0]; } return ui; } @@ -482,8 +482,6 @@ void stlink_core_stat(stlink_t *sl) { if (sl->q_len <= 0) return; - stlink_print_data(sl); - switch (sl->q_buf[0]) { case STLINK_CORE_RUNNING: sl->core_stat = STLINK_CORE_RUNNING; @@ -663,14 +661,16 @@ int stlink_fread(stlink_t* sl, const char* path, stm32_addr_t addr, size_t size) /* do the copy by 1k blocks */ for (off = 0; off < size; off += 1024) { size_t read_size = 1024; + size_t rounded_size; if ((off + read_size) > size) - read_size = off + read_size; + read_size = size - off; /* round size if needed */ - if (read_size & 3) - read_size = (read_size + 4) & ~(3); + rounded_size = read_size; + if (rounded_size & 3) + rounded_size = (rounded_size + 4) & ~(3); - stlink_read_mem32(sl, addr + off, read_size); + stlink_read_mem32(sl, addr + off, rounded_size); if (write(fd, sl->q_buf, read_size) != (ssize_t) read_size) { fprintf(stderr, "write() != read_size\n"); @@ -694,9 +694,97 @@ int write_buffer_to_sram(stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, s return 0; } -int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t page) { - /* page an addr in the page to erase */ +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) + { +#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; + + /* 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 (0x%x)\n", val); + 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 (0x%x)\n", val); + return -1; + } + + /* unused: unlock the option byte block */ +#if 0 + write_uint32(sl->q_buf, 0xfbead9c8); + stlink_write_mem32(sl, STM32L_FLASH_OPTKEYR, sizeof(uint32_t)); + write_uint32(sl->q_buf, 0x24252627); + stlink_write_mem32(sl, STM32L_FLASH_OPTKEYR, sizeof(uint32_t)); + + /* check pecr.optlock is cleared */ + stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t)); + val = read_uint32(sl->q_buf, 0); + if (val & (1 << 2)) + { + fprintf(stderr, "pecr.prglock not clear\n"); + return -1; + } +#endif + + /* set pecr.{erase,prog} */ + val |= (1 << 9) | (1 << 3); + write_uint32(sl->q_buf, val); + stlink_write_mem32(sl, STM32L_FLASH_PECR, 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 ; + } + /* write 0 to the first word of the page to be erased */ + memset(sl->q_buf, 0, sizeof(uint32_t)); + stlink_write_mem32(sl, page, 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) + { /* wait for ongoing op to finish */ wait_flash_busy(sl); @@ -717,10 +805,15 @@ 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); + return -1; + } - /* todo: verify the erased page */ + /* todo: verify the erased page */ - return 0; + return 0; } int stlink_erase_flash_mass(stlink_t *sl) { @@ -764,7 +857,7 @@ int init_flash_loader(stlink_t *sl, flash_loader_t* fl) { int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) { /* from openocd, contrib/loaders/flash/stm32.s */ - static const uint8_t loader_code[] = { + static const uint8_t loader_code_stm32vl[] = { 0x08, 0x4c, /* ldr r4, STM32_FLASH_BASE */ 0x1c, 0x44, /* add r4, r3 */ /* write_half_word: */ @@ -785,11 +878,51 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) { 0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */ }; - memcpy(sl->q_buf, loader_code, sizeof (loader_code)); - stlink_write_mem32(sl, sl->sram_base, sizeof (loader_code)); + static const uint8_t loader_code_stm32l[] = { + + /* openocd.git/contrib/loaders/flash/stm32lx.S + r0, input, dest addr + r1, input, source addr + r2, input, word count + r3, output, word count + */ + + 0x00, 0x23, + 0x04, 0xe0, + + 0x51, 0xf8, 0x04, 0xcb, + 0x40, 0xf8, 0x04, 0xcb, + 0x01, 0x33, + + 0x93, 0x42, + 0xf8, 0xd3, + 0x00, 0xbe + }; + + const uint8_t* loader_code; + size_t loader_size; + + if (sl->core_id == STM32L_CORE_ID) /* stm32l */ + { + loader_code = loader_code_stm32l; + loader_size = sizeof(loader_code_stm32l); + } + else if (sl->core_id == STM32VL_CORE_ID) + { + loader_code = loader_code_stm32vl; + loader_size = sizeof(loader_code_stm32vl); + } + else + { + fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + return -1; + } + + memcpy(sl->q_buf, loader_code, loader_size); + stlink_write_mem32(sl, sl->sram_base, loader_size); *addr = sl->sram_base; - *size = sizeof (loader_code); + *size = loader_size; /* success */ return 0; @@ -811,11 +944,6 @@ int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { return res; } -// The stlink_fwrite_flash should not muck with mmapped files inside itself, -// and should use this function instead. (Hell, what's the reason behind mmap -// there?!) But, as it is not actually used anywhere, nobody cares. - -#define WRITE_BLOCK_SIZE 0x40 int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned len) { size_t off; @@ -834,25 +962,169 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned } else if ((addr & 1) || (len & 1)) { fprintf(stderr, "unaligned addr or size\n"); return -1; + } else if (addr & (sl->flash_pgsz - 1)) { + fprintf(stderr, "addr not a multiple of pagesize, not supported\n"); + return -1; } - /* flash loader initialization */ - if (init_flash_loader(sl, &fl) == -1) { + /* erase each page */ + for (off = 0; off < len; off += sl->flash_pgsz) { + /* 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); + return -1; + } + } + + stlink_core_id(sl); + 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; + + /* 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; + + /* 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)); + + /* 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); + + goto redo_write; + } + + /* 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)); + } + 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? */ - for (off = 0; off < len; off += WRITE_BLOCK_SIZE) { + /* 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; + 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; + 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); + return -1; } for (off = 0; off < len; off += sl->flash_pgsz) { @@ -879,109 +1151,91 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { /* write the file in flash at addr */ - int error = -1; - size_t off; + int err; mapped_file_t mf = MAPPED_FILE_INITIALIZER; - flash_loader_t fl; if (map_file(&mf, path) == -1) { fprintf(stderr, "map_file() == -1\n"); return -1; } - /* check addr range is inside the flash */ - if (addr < sl->flash_base) { - fprintf(stderr, "addr too low\n"); - goto on_error; - } else if ((addr + mf.len) < addr) { - fprintf(stderr, "addr overruns\n"); - goto on_error; - } else if ((addr + mf.len) > (sl->flash_base + sl->flash_size)) { - fprintf(stderr, "addr too high\n"); - goto on_error; - } else if ((addr & 1) || (mf.len & 1)) { - /* todo */ - fprintf(stderr, "unaligned addr or size\n"); - goto on_error; - } + err = stlink_write_flash(sl, addr, mf.base, mf.len); - /* erase each page. todo: mass erase faster? */ - for (off = 0; off < mf.len; off += sl->flash_pgsz) { - /* 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); - goto on_error; - } - } - - /* flash loader initialization */ - if (init_flash_loader(sl, &fl) == -1) { - fprintf(stderr, "init_flash_loader() == -1\n"); - goto on_error; - } - - /* write each page. above WRITE_BLOCK_SIZE fails? */ -#define WRITE_BLOCK_SIZE 0x40 - for (off = 0; off < mf.len; off += WRITE_BLOCK_SIZE) { - /* adjust last write size */ - size_t size = WRITE_BLOCK_SIZE; - if ((off + WRITE_BLOCK_SIZE) > mf.len) - size = mf.len - off; - - if (run_flash_loader(sl, &fl, addr + off, mf.base + off, size) == -1) { - fprintf(stderr, "run_flash_loader(0x%zx) == -1\n", addr + off); - goto on_error; - } - } - - /* check the file ha been written */ - if (check_file(sl, &mf, addr) == -1) { - fprintf(stderr, "check_file() == -1\n"); - goto on_error; - } - - /* success */ - error = 0; - -on_error: unmap_file(&mf); - return error; + + return err; } int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) { - const size_t count = size / sizeof (uint16_t); + + reg rr; if (write_buffer_to_sram(sl, fl, buf, size) == -1) { fprintf(stderr, "write_buffer_to_sram() == -1\n"); return -1; } - /* setup core */ - stlink_write_reg(sl, fl->buf_addr, 0); /* source */ - stlink_write_reg(sl, target, 1); /* target */ - stlink_write_reg(sl, count, 2); /* count (16 bits half words) */ - stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */ - stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ + if (sl->core_id == STM32L_CORE_ID) { - /* unlock and set programming mode */ - unlock_flash_if(sl); - set_flash_cr_pg(sl); + size_t count = size / sizeof(uint32_t); + if (size % sizeof(uint32_t)) ++count; + + /* setup core */ + stlink_write_reg(sl, target, 0); /* target */ + stlink_write_reg(sl, fl->buf_addr, 1); /* source */ + stlink_write_reg(sl, count, 2); /* count (32 bits words) */ + stlink_write_reg(sl, 0, 3); /* output count */ + stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ + + } else if (sl->core_id == STM32VL_CORE_ID) { + + size_t count = size / sizeof(uint16_t); + if (size % sizeof(uint16_t)) ++count; + + /* setup core */ + stlink_write_reg(sl, fl->buf_addr, 0); /* source */ + stlink_write_reg(sl, target, 1); /* target */ + stlink_write_reg(sl, count, 2); /* count (16 bits half words) */ + stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */ + stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */ + + } else { + fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + return -1; + } /* run loader */ - stlink_run(sl); + stlink_step(sl); - while (is_core_halted(sl) == 0) - ; + /* wait until done (reaches breakpoint) */ + while (is_core_halted(sl) == 0) ; - lock_flash(sl); + /* check written byte count */ + if (sl->core_id == STM32L_CORE_ID) { - /* not all bytes have been written */ - reg rr; - stlink_read_reg(sl, 2, &rr); - if (rr.r[2] != 0) { + size_t count = size / sizeof(uint32_t); + if (size % sizeof(uint32_t)) ++count; + + stlink_read_reg(sl, 3, &rr); + if (rr.r[3] != count) { + fprintf(stderr, "write error, count == %u\n", rr.r[3]); + return -1; + } + + } else if (sl->core_id == STM32VL_CORE_ID) { + + stlink_read_reg(sl, 2, &rr); + if (rr.r[2] != 0) { fprintf(stderr, "write error, count == %u\n", rr.r[2]); return -1; + } + + } else { + + fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + return -1; + } return 0; -} \ No newline at end of file +} diff --git a/src/stlink-common.h b/src/stlink-common.h index 18e1c0c..bcd60aa 100644 --- a/src/stlink-common.h +++ b/src/stlink-common.h @@ -76,6 +76,11 @@ extern "C" { #define CM3_REG_FP_CTRL 0xE0002000 #define CM3_REG_FP_COMP0 0xE0002008 +/* cortex core ids */ +#define STM32VL_CORE_ID 0x1ba01477 +#define STM32L_CORE_ID 0x2ba01477 +#define STM32F4_CORE_ID 0x2ba01477 + /* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/ #define C_BUF_LEN 32 @@ -162,6 +167,7 @@ extern "C" { #define STM32_FLASH_BASE 0x08000000 #define STM32_FLASH_SIZE (128 * 1024) #define STM32_FLASH_PGSZ 1024 +#define STM32L_FLASH_PGSZ 256 stm32_addr_t flash_base; size_t flash_size; size_t flash_pgsz; diff --git a/src/stlink-usb.c b/src/stlink-usb.c index a816769..785f7be 100644 --- a/src/stlink-usb.c +++ b/src/stlink-usb.c @@ -599,19 +599,6 @@ stlink_t* stlink_open_usb(const int verbose) { sl->core_stat = STLINK_CORE_STAT_UNKNOWN; - /* flash memory settings */ - sl->flash_base = STM32_FLASH_BASE; - sl->flash_size = STM32_FLASH_SIZE; - sl->flash_pgsz = STM32_FLASH_PGSZ; - - /* 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 = STM32L_SRAM_SIZE; - if (libusb_init(&(slu->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); goto on_error; @@ -675,11 +662,57 @@ stlink_t* stlink_open_usb(const int verbose) { slu->cmd_len = (slu->protocoll == 1)? STLINK_SG_SIZE: STLINK_CMD_SIZE; /* success */ + if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { ILOG("-- exit_dfu_mode\n"); stlink_exit_dfu_mode(sl); } + + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { + stlink_enter_swd_mode(sl); + } + stlink_version(sl); + + /* per device family initialization */ + stlink_core_id(sl); + if (sl->core_id == STM32L_CORE_ID) { + + /* flash memory settings */ + sl->flash_base = STM32_FLASH_BASE; + sl->flash_size = STM32_FLASH_SIZE; + sl->flash_pgsz = STM32L_FLASH_PGSZ; + + /* 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 = STM32L_SRAM_SIZE; + + } else if (sl->core_id == STM32VL_CORE_ID) { + + /* flash memory settings */ + sl->flash_base = STM32_FLASH_BASE; + sl->flash_size = STM32_FLASH_SIZE; + sl->flash_pgsz = STM32_FLASH_PGSZ; + + /* 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 { + + fprintf(stderr, "unknown coreid: %x\n", sl->core_id); + goto on_libusb_error; + + } + error = 0; on_libusb_error: