libstlink.a
test_usb
test_sg
+gdbserver/st-utils
\ No newline at end of file
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
-
+# make ... for both libusb and libsg
+#
+# make CONFIG_USE_LIBSG=0 ...
+# for just libusb
+#
VPATH=src
-SOURCES_LIB=stlink-common.c stlink-usb.c stlink-sg.c
+SOURCES_LIB=stlink-common.c stlink-usb.c
OBJS_LIB=$(SOURCES_LIB:.c=.o)
+TEST_PROGRAMS=test_usb
+LDFLAGS=-lusb-1.0 -L. -lstlink
+
+ifeq ($(CONFIG_USE_LIBSG),)
+CONFIG_USE_LIBSG=1
+endif
+
+ifneq ($(CONFIG_USE_LIBSG),0)
+SOURCES_LIB+=stlink-sg.c
+CFLAGS+=-DCONFIG_USE_LIBSG=1
+LDFLAGS+=-lsgutils2
+TEST_PROGRAMS+=test_sg
+endif
CFLAGS+=-g
-CFLAGS+=-DCONFIG_USE_LIBUSB
-CFLAGS+=-DCONFIG_USE_LIBSG
-CFLAGS+=-DDEBUG
+CFLAGS+=-DCONFIG_USE_LIBUSB=1
+CFLAGS+=-DDEBUG=1
CFLAGS+=-std=gnu99
CFLAGS+=-Wall -Wextra
-LDFLAGS=-lstlink -lusb-1.0 -lsgutils2 -L.
LIBRARY=libstlink.a
-all: $(LIBRARY) test_usb test_sg
+all: $(LIBRARY) flash gdbserver $(TEST_PROGRAMS)
$(LIBRARY): $(OBJS_LIB)
@echo "objs are $(OBJS_LIB)"
rm -rf $(LIBRARY)
rm -rf test_usb*
rm -rf test_sg*
+
+distclean: clean
+ $(MAKE) -C flash clean
+ $(MAKE) -C gdbserver clean
-.PHONY: clean all
+flash:
+ $(MAKE) -C flash CONFIG_USE_LIBSG="$(CONFIG_USE_LIBSG)"
+
+gdbserver:
+ $(MAKE) -C gdbserver
+
+.PHONY: clean all flash gdbserver
-. flash writing is not working from GDB
-add a standalone application, flash/
+. 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
-. add a startup.S based example
+. documentation
+ . make README points to doc/tutorial
. remove libsg dependency using:
https://github.com/afaerber/stlink/tree/master/libstlink
. compile and test a realtime kernel, for instance:
-http://www.chibios.org/dokuwiki/doku.php?id=start
+http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:stm32l_discovery
+svn checkout https://chibios.svn.sourceforge.net/svnroot/chibios/trunk ;
+cd chibios/trunk/demos/ARMCM3-STM32L152-DISCOVERY ;
+make ;
(v1 uses SCSI passthru commands, while v2 uses raw USB).
\paragraph{}
-Before continuing, the following dependencies are required:
+Before continuing, the following dependencies must be met:
\begin{itemize}
\item libusb-1.0
-\item libsg2
+\item libsgutils2 (optionnal)
\end{itemize}
+\paragraph{}
+STLINK should run on any system meeting the above constraints.
+
\paragraph{}
The STLINK software source code is retrieved using:\\
\begin{small}
\begin{lstlisting}[frame=tb]
-git clone https://github.com/texane/stlink stlink.git
+$> git clone https://github.com/texane/stlink stlink.git
\end{lstlisting}
\end{small}
\paragraph{}
-The GDB server is called st-util and is built using:\\
+Everything can be built from the top directory:\\
\begin{small}
\begin{lstlisting}[frame=tb]
-$> cd stlink.git;
-$> make ;
-$> cd gdbserver ;
-$> make ;
+$> cd stlink.git
+$> make CONFIG_USE_LIBSG=0
\end{lstlisting}
\end{small}
+It includes:
+\begin{itemize}
+\item a communication library (stlink.git/libstlink.a),
+\item a GDB server (stlink.git/gdbserver/st-util),
+\item a flash manipulation tool (stlink.git/flash/flash).
+\end{itemize}
\newpage
A simple LED blinking example is provided in the example directory. It is built using:\\
\begin{small}
\begin{lstlisting}[frame=tb]
+# update the make option accordingly to your architecture
cd stlink.git/example/blink ;
-PATH=$TOOLCHAIN_PATH/bin:$PATH make ;
+PATH=$TOOLCHAIN_PATH/bin:$PATH make CONFIG_STM32L_DISCOVERY=1;
\end{lstlisting}
\end{small}
$> sudo ./st-util /dev/sg2
# STM32L discovery kit
-$> sudo ./st-util
+# 2 dummy command line arguments needed, will be fixed soon
+$> sudo ./st-util fu bar
\end{lstlisting}
\end{small}
The board BLUE and GREEN leds should be blinking (those leds are near the user and reset buttons).
+\newpage
+\section{Reading and writing to flash}
+\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:\\
+\begin{small}
+\begin{lstlisting}[frame=tb]
+# change to the flash tool directory
+$> cd stlink.git/flash ;
+
+# stlinkv1 command to read 4096 from flash into out.bin
+$> ./flash read /dev/sg2 out.bin 0x8000000 4096
+
+# stlinkv2 command
+$> ./flash read out.bin 0x8000000 4096
+
+# stlinkv1 command to write the file in.bin into flash
+$> ./flash write /dev/sg2 in.bin 0x8000000
+
+# stlinkv2 command
+$> ./flash write in.bin 0x8000000
+\end{lstlisting}
+\end{small}
+
+
\newpage
\section{Notes}
\end{lstlisting}
\end{small}
+\subsection{STM32VL support}
+\paragraph{}
+It seems support for STM32VL is quite broken. If it does not work, try build STLINK using libsg:
+\begin{small}
+\begin{lstlisting}[frame=tb]
+$> cd stlink.git
+$> make CONFIG_USE_LIBSG=1
+\end{lstlisting}
+\end{small}
+
+
\newpage
\section{References}
\begin{itemize}
CC=arm-none-eabi-gcc
OBJCOPY=arm-none-eabi-objcopy
-CFLAGS=-O2 -mlittle-endian -mthumb -g
-CFLAGS+=-mcpu=cortex-m3 -ffreestanding -nostdlib -nostdinc
+CFLAGS=-g -O2 -mlittle-endian -mthumb
+ifeq ($(CONFIG_STM32L_DISCOVERY), 1)
+ CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY
+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
+endif
+ CFLAGS+=-ffreestanding -nostdlib -nostdinc
# to run from SRAM
CFLAGS+=-Wl,-Ttext,0x20000000 -Wl,-e,0x20000000
/* hardware configuration */
-#define CONFIG_STM32L_DISCOVERY 1
-#define CONFIG_STM32VL_DISCOVERY 0
-
-
#if CONFIG_STM32VL_DISCOVERY
# define GPIOC 0x40011000 /* port C */
*(volatile uint32_t*)GPIOB_ODR = 0;
}
+#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 */
+
+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_ORANGE | LED_RED | LED_BLUE;
+}
+
+static inline void switch_leds_off(void)
+{
+ *(volatile uint32_t*)GPIOD_ODR = 0;
+}
+
+#else
+#error "Architecture must be defined!"
#endif /* otherwise, error */
--- /dev/null
+EXECUTABLE=blink.elf
+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
+ifeq ($(CONFIG_STM32L_DISCOVERY), 1)
+ CFLAGS+=-mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY
+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
+
+all: $(BIN_IMAGE)
+
+$(BIN_IMAGE): $(EXECUTABLE)
+ $(OBJCOPY) -O binary $^ $@
+
+$(EXECUTABLE): main.c startup_stm32l1xx_md.s
+ $(CC) $(CFLAGS) $^ -o $@
+
+clean:
+ rm -rf $(EXECUTABLE)
+ rm -rf $(BIN_IMAGE)
+
+.PHONY: all clean
--- /dev/null
+/* missing type */
+
+typedef unsigned int uint32_t;
+
+
+/* hardware configuration */
+
+#define CONFIG_STM32L_DISCOVERY 1
+#define CONFIG_STM32VL_DISCOVERY 0
+
+
+#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 0x40020400 /* port B */
+# 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)
+{
+ *(volatile uint32_t*)GPIOB_ODR = LED_BLUE | LED_GREEN;
+}
+
+static inline void switch_leds_off(void)
+{
+ *(volatile uint32_t*)GPIOB_ODR = 0;
+}
+
+#endif /* otherwise, error */
+
+
+#define delay() \
+do { \
+ register unsigned int i; \
+ for (i = 0; i < 1000000; ++i) \
+ __asm__ __volatile__ ("nop\n\t":::"memory"); \
+} while (0)
+
+void main(void)
+{
+ setup_leds();
+
+ while (1)
+ {
+ switch_leds_on();
+ delay();
+ switch_leds_off();
+ delay();
+ }
+}
--- /dev/null
+/**\r
+ ******************************************************************************\r
+ * @file startup_stm32l1xx_md.s\r
+ * @author MCD Application Team\r
+ * @version V1.0.0\r
+ * @date 31-December-2010\r
+ * @brief STM32L1xx Ultra Low Power Medium-density Devices vector table for \r
+ * RIDE7 toolchain.\r
+ * This module performs:\r
+ * - Set the initial SP\r
+ * - Set the initial PC == Reset_Handler,\r
+ * - Set the vector table entries with the exceptions ISR address\r
+ * - Branches to main in the C library (which eventually\r
+ * calls main()).\r
+ * After Reset the Cortex-M3 processor is in Thread mode,\r
+ * priority is Privileged, and the Stack is set to Main.\r
+ *******************************************************************************\r
+ * @attention\r
+ *\r
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
+ *\r
+ * <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>\r
+ ******************************************************************************* \r
+ */\r
+ \r
+ .syntax unified\r
+ .cpu cortex-m3\r
+ .fpu softvfp\r
+ .thumb\r
+\r
+.global g_pfnVectors\r
+.global Default_Handler\r
+\r
+/* start address for the initialization values of the .data section. \r
+defined in linker script */\r
+.word _sidata\r
+/* start address for the .data section. defined in linker script */ \r
+.word _sdata\r
+/* end address for the .data section. defined in linker script */\r
+.word _edata\r
+/* start address for the .bss section. defined in linker script */\r
+.word _sbss\r
+/* end address for the .bss section. defined in linker script */\r
+.word _ebss\r
+\r
+.equ BootRAM, 0xF108F85F\r
+/**\r
+ * @brief This is the code that gets called when the processor first\r
+ * starts execution following a reset event. Only the absolutely\r
+ * necessary set is performed, after which the application\r
+ * supplied main() routine is called. \r
+ * @param None\r
+ * @retval : None\r
+*/\r
+\r
+ .section .text.Reset_Handler\r
+ .weak Reset_Handler\r
+ .type Reset_Handler, %function\r
+Reset_Handler:\r
+\r
+/* Copy the data segment initializers from flash to SRAM */ \r
+ movs r1, #0\r
+ b LoopCopyDataInit\r
+\r
+CopyDataInit:\r
+ ldr r3, =_sidata\r
+ ldr r3, [r3, r1]\r
+ str r3, [r0, r1]\r
+ adds r1, r1, #4\r
+ \r
+LoopCopyDataInit:\r
+ ldr r0, =_sdata\r
+ ldr r3, =_edata\r
+ adds r2, r0, r1\r
+ cmp r2, r3\r
+ bcc CopyDataInit\r
+ ldr r2, =_sbss\r
+ b LoopFillZerobss\r
+/* Zero fill the bss segment. */ \r
+FillZerobss:\r
+ movs r3, #0\r
+ str r3, [r2], #4\r
+ \r
+LoopFillZerobss:\r
+ ldr r3, = _ebss\r
+ cmp r2, r3\r
+ bcc FillZerobss\r
+/* Call the clock system intitialization function.*/\r
+/* let main do the system initialization */\r
+/* bl SystemInit */\r
+/* Call the application's entry point.*/\r
+ bl main\r
+ bx lr\r
+.size Reset_Handler, .-Reset_Handler\r
+\r
+/**\r
+ * @brief This is the code that gets called when the processor receives an \r
+ * unexpected interrupt. This simply enters an infinite loop, preserving\r
+ * the system state for examination by a debugger.\r
+ *\r
+ * @param None \r
+ * @retval None \r
+*/\r
+ .section .text.Default_Handler,"ax",%progbits\r
+Default_Handler:\r
+Infinite_Loop:\r
+ b Infinite_Loop\r
+ .size Default_Handler, .-Default_Handler\r
+/*******************************************************************************\r
+*\r
+* The minimal vector table for a Cortex M3. Note that the proper constructs\r
+* must be placed on this to ensure that it ends up at physical address\r
+* 0x0000.0000.\r
+*******************************************************************************/ \r
+ .section .isr_vector,"a",%progbits\r
+ .type g_pfnVectors, %object\r
+ .size g_pfnVectors, .-g_pfnVectors\r
+ \r
+ \r
+g_pfnVectors:\r
+ .word _estack\r
+ .word Reset_Handler\r
+ .word NMI_Handler\r
+ .word HardFault_Handler\r
+ .word MemManage_Handler\r
+ .word BusFault_Handler\r
+ .word UsageFault_Handler\r
+ .word 0\r
+ .word 0\r
+ .word 0\r
+ .word 0\r
+ .word SVC_Handler\r
+ .word DebugMon_Handler\r
+ .word 0\r
+ .word PendSV_Handler\r
+ .word SysTick_Handler\r
+ .word WWDG_IRQHandler\r
+ .word PVD_IRQHandler\r
+ .word TAMPER_STAMP_IRQHandler\r
+ .word RTC_WKUP_IRQHandler\r
+ .word FLASH_IRQHandler\r
+ .word RCC_IRQHandler\r
+ .word EXTI0_IRQHandler\r
+ .word EXTI1_IRQHandler\r
+ .word EXTI2_IRQHandler\r
+ .word EXTI3_IRQHandler\r
+ .word EXTI4_IRQHandler\r
+ .word DMA1_Channel1_IRQHandler\r
+ .word DMA1_Channel2_IRQHandler\r
+ .word DMA1_Channel3_IRQHandler\r
+ .word DMA1_Channel4_IRQHandler\r
+ .word DMA1_Channel5_IRQHandler\r
+ .word DMA1_Channel6_IRQHandler\r
+ .word DMA1_Channel7_IRQHandler\r
+ .word ADC1_IRQHandler\r
+ .word USB_HP_IRQHandler\r
+ .word USB_LP_IRQHandler\r
+ .word DAC_IRQHandler\r
+ .word COMP_IRQHandler\r
+ .word EXTI9_5_IRQHandler\r
+ .word LCD_IRQHandler\r
+ .word TIM9_IRQHandler\r
+ .word TIM10_IRQHandler\r
+ .word TIM11_IRQHandler\r
+ .word TIM2_IRQHandler\r
+ .word TIM3_IRQHandler\r
+ .word TIM4_IRQHandler\r
+ .word I2C1_EV_IRQHandler\r
+ .word I2C1_ER_IRQHandler\r
+ .word I2C2_EV_IRQHandler\r
+ .word I2C2_ER_IRQHandler\r
+ .word SPI1_IRQHandler\r
+ .word SPI2_IRQHandler\r
+ .word USART1_IRQHandler\r
+ .word USART2_IRQHandler\r
+ .word USART3_IRQHandler\r
+ .word EXTI15_10_IRQHandler\r
+ .word RTC_Alarm_IRQHandler\r
+ .word USB_FS_WKUP_IRQHandler\r
+ .word TIM6_IRQHandler\r
+ .word TIM7_IRQHandler\r
+ .word 0\r
+ .word 0\r
+ .word 0\r
+ .word 0\r
+ .word 0\r
+ .word BootRAM /* @0x108. This is for boot in RAM mode for \r
+ STM32L15x ULtra Low Power Medium-density devices. */\r
+ \r
+/*******************************************************************************\r
+*\r
+* Provide weak aliases for each Exception handler to the Default_Handler. \r
+* As they are weak aliases, any function with the same name will override \r
+* this definition.\r
+*\r
+*******************************************************************************/\r
+ \r
+ .weak NMI_Handler\r
+ .thumb_set NMI_Handler,Default_Handler\r
+\r
+ .weak HardFault_Handler\r
+ .thumb_set HardFault_Handler,Default_Handler\r
+\r
+ .weak MemManage_Handler\r
+ .thumb_set MemManage_Handler,Default_Handler\r
+\r
+ .weak BusFault_Handler\r
+ .thumb_set BusFault_Handler,Default_Handler\r
+\r
+ .weak UsageFault_Handler\r
+ .thumb_set UsageFault_Handler,Default_Handler\r
+\r
+ .weak SVC_Handler\r
+ .thumb_set SVC_Handler,Default_Handler\r
+\r
+ .weak DebugMon_Handler\r
+ .thumb_set DebugMon_Handler,Default_Handler\r
+\r
+ .weak PendSV_Handler\r
+ .thumb_set PendSV_Handler,Default_Handler\r
+\r
+ .weak SysTick_Handler\r
+ .thumb_set SysTick_Handler,Default_Handler\r
+\r
+ .weak WWDG_IRQHandler\r
+ .thumb_set WWDG_IRQHandler,Default_Handler\r
+\r
+ .weak PVD_IRQHandler\r
+ .thumb_set PVD_IRQHandler,Default_Handler\r
+\r
+ .weak TAMPER_STAMP_IRQHandler\r
+ .thumb_set TAMPER_STAMP_IRQHandler,Default_Handler\r
+\r
+ .weak RTC_WKUP_IRQHandler\r
+ .thumb_set RTC_WKUP_IRQHandler,Default_Handler\r
+\r
+ .weak FLASH_IRQHandler\r
+ .thumb_set FLASH_IRQHandler,Default_Handler\r
+\r
+ .weak RCC_IRQHandler\r
+ .thumb_set RCC_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI0_IRQHandler\r
+ .thumb_set EXTI0_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI1_IRQHandler\r
+ .thumb_set EXTI1_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI2_IRQHandler\r
+ .thumb_set EXTI2_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI3_IRQHandler\r
+ .thumb_set EXTI3_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI4_IRQHandler\r
+ .thumb_set EXTI4_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel1_IRQHandler\r
+ .thumb_set DMA1_Channel1_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel2_IRQHandler\r
+ .thumb_set DMA1_Channel2_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel3_IRQHandler\r
+ .thumb_set DMA1_Channel3_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel4_IRQHandler\r
+ .thumb_set DMA1_Channel4_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel5_IRQHandler\r
+ .thumb_set DMA1_Channel5_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel6_IRQHandler\r
+ .thumb_set DMA1_Channel6_IRQHandler,Default_Handler\r
+\r
+ .weak DMA1_Channel7_IRQHandler\r
+ .thumb_set DMA1_Channel7_IRQHandler,Default_Handler\r
+\r
+ .weak ADC1_IRQHandler\r
+ .thumb_set ADC1_IRQHandler,Default_Handler\r
+\r
+ .weak USB_HP_IRQHandler\r
+ .thumb_set USB_HP_IRQHandler,Default_Handler\r
+\r
+ .weak USB_LP_IRQHandler\r
+ .thumb_set USB_LP_IRQHandler,Default_Handler\r
+\r
+ .weak DAC_IRQHandler\r
+ .thumb_set DAC_IRQHandler,Default_Handler\r
+\r
+ .weak COMP_IRQHandler\r
+ .thumb_set COMP_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI9_5_IRQHandler\r
+ .thumb_set EXTI9_5_IRQHandler,Default_Handler\r
+\r
+ .weak LCD_IRQHandler\r
+ .thumb_set LCD_IRQHandler,Default_Handler\r
+ \r
+ .weak TIM9_IRQHandler\r
+ .thumb_set TIM9_IRQHandler,Default_Handler\r
+\r
+ .weak TIM10_IRQHandler\r
+ .thumb_set TIM10_IRQHandler,Default_Handler\r
+\r
+ .weak TIM11_IRQHandler\r
+ .thumb_set TIM11_IRQHandler,Default_Handler\r
+\r
+ .weak TIM2_IRQHandler\r
+ .thumb_set TIM2_IRQHandler,Default_Handler\r
+\r
+ .weak TIM3_IRQHandler\r
+ .thumb_set TIM3_IRQHandler,Default_Handler\r
+\r
+ .weak TIM4_IRQHandler\r
+ .thumb_set TIM4_IRQHandler,Default_Handler\r
+\r
+ .weak I2C1_EV_IRQHandler\r
+ .thumb_set I2C1_EV_IRQHandler,Default_Handler\r
+\r
+ .weak I2C1_ER_IRQHandler\r
+ .thumb_set I2C1_ER_IRQHandler,Default_Handler\r
+\r
+ .weak I2C2_EV_IRQHandler\r
+ .thumb_set I2C2_EV_IRQHandler,Default_Handler\r
+\r
+ .weak I2C2_ER_IRQHandler\r
+ .thumb_set I2C2_ER_IRQHandler,Default_Handler\r
+\r
+ .weak SPI1_IRQHandler\r
+ .thumb_set SPI1_IRQHandler,Default_Handler\r
+\r
+ .weak SPI2_IRQHandler\r
+ .thumb_set SPI2_IRQHandler,Default_Handler\r
+\r
+ .weak USART1_IRQHandler\r
+ .thumb_set USART1_IRQHandler,Default_Handler\r
+\r
+ .weak USART2_IRQHandler\r
+ .thumb_set USART2_IRQHandler,Default_Handler\r
+\r
+ .weak USART3_IRQHandler\r
+ .thumb_set USART3_IRQHandler,Default_Handler\r
+\r
+ .weak EXTI15_10_IRQHandler\r
+ .thumb_set EXTI15_10_IRQHandler,Default_Handler\r
+\r
+ .weak RTC_Alarm_IRQHandler\r
+ .thumb_set RTC_Alarm_IRQHandler,Default_Handler\r
+\r
+ .weak USB_FS_WKUP_IRQHandler\r
+ .thumb_set USB_FS_WKUP_IRQHandler,Default_Handler\r
+\r
+ .weak TIM6_IRQHandler\r
+ .thumb_set TIM6_IRQHandler,Default_Handler\r
+\r
+ .weak TIM7_IRQHandler\r
+ .thumb_set TIM7_IRQHandler,Default_Handler\r
+\r
+/******************** (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE***/\r
+\r
--- /dev/null
+/*
+*****************************************************************************
+**
+** 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 \93as is,\94 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
+}
--- /dev/null
+/**\r
+ ******************************************************************************\r
+ * @file system_stm32l1xx.c\r
+ * @author MCD Application Team\r
+ * @version V1.0.0\r
+ * @date 2-June-2011\r
+ * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.\r
+ * This file contains the system clock configuration for STM32L1xx Ultra\r
+ * Low Medium-density devices, and is generated by the clock configuration\r
+ * tool "STM32L1xx_Clock_Configuration_V1.0.0.xls".\r
+ * \r
+ * 1. This file provides two functions and one global variable to be called from \r
+ * user application:\r
+ * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier\r
+ * and Divider factors, AHB/APBx prescalers and Flash settings),\r
+ * depending on the configuration made in the clock xls tool. \r
+ * This function is called at startup just after reset and \r
+ * before branch to main program. This call is made inside\r
+ * the "startup_stm32l1xx_md.s" file.\r
+ * \r
+ * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used\r
+ * by the user application to setup the SysTick \r
+ * timer or configure other parameters.\r
+ * \r
+ * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must\r
+ * be called whenever the core clock is changed\r
+ * during program execution. \r
+ * \r
+ * 2. After each device reset the MSI (2.1 MHz Range) is used as system clock source.\r
+ * Then SystemInit() function is called, in "startup_stm32l1xx_md.s" file, to\r
+ * configure the system clock before to branch to main program. \r
+ * \r
+ * 3. If the system clock source selected by user fails to startup, the SystemInit()\r
+ * function will do nothing and MSI still used as system clock source. User can \r
+ * add some code to deal with this issue inside the SetSysClock() function. \r
+ * \r
+ * 4. The default value of HSE crystal is set to 8MHz, refer to "HSE_VALUE" define\r
+ * in "stm32l1xx.h" file. When HSE is used as system clock source, directly or\r
+ * through PLL, and you are using different crystal you have to adapt the HSE\r
+ * value to your own configuration.\r
+ * \r
+ * 5. This file configures the system clock as follows: \r
+ *=============================================================================\r
+ * System Clock Configuration\r
+ *=============================================================================\r
+ * System clock source | HSI\r
+ *----------------------------------------------------------------------------- \r
+ * SYSCLK | 16000000 Hz\r
+ *----------------------------------------------------------------------------- \r
+ * HCLK | 16000000 Hz\r
+ *----------------------------------------------------------------------------- \r
+ * AHB Prescaler | 1\r
+ *----------------------------------------------------------------------------- \r
+ * APB1 Prescaler | 1\r
+ *----------------------------------------------------------------------------- \r
+ * APB2 Prescaler | 1\r
+ *----------------------------------------------------------------------------- \r
+ * HSE Frequency | 8000000 Hz\r
+ *----------------------------------------------------------------------------- \r
+ * PLL DIV | Not Used\r
+ *----------------------------------------------------------------------------- \r
+ * PLL MUL | Not Used\r
+ *----------------------------------------------------------------------------- \r
+ * VDD | 3.3 V\r
+ *----------------------------------------------------------------------------- \r
+ * Vcore | 1.8 V (Range 1)\r
+ *----------------------------------------------------------------------------- \r
+ * Flash Latency | 0 WS\r
+ *----------------------------------------------------------------------------- \r
+ * Require 48MHz for USB clock | Disabled\r
+ *----------------------------------------------------------------------------- \r
+ *=============================================================================\r
+ ****************************************************************************** \r
+ * @attention\r
+ *\r
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS\r
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE\r
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY\r
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING\r
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE\r
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.\r
+ *\r
+ * <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>\r
+ ****************************************************************************** \r
+ */\r
+\r
+/** @addtogroup CMSIS\r
+ * @{\r
+ */\r
+\r
+/** @addtogroup stm32l1xx_system\r
+ * @{\r
+ */ \r
+ \r
+/** @addtogroup STM32L1xx_System_Private_Includes\r
+ * @{\r
+ */\r
+\r
+#include "stm32l1xx.h"\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/** @addtogroup STM32L1xx_System_Private_TypesDefinitions\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/** @addtogroup STM32L1xx_System_Private_Defines\r
+ * @{\r
+ */\r
+/*!< Uncomment the following line if you need to relocate your vector Table in\r
+ Internal SRAM. */ \r
+/* #define VECT_TAB_SRAM */\r
+#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. \r
+ This value must be a multiple of 0x200. */\r
+/**\r
+ * @}\r
+ */\r
+\r
+/** @addtogroup STM32L1xx_System_Private_Macros\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/** @addtogroup STM32L1xx_System_Private_Variables\r
+ * @{\r
+ */\r
+uint32_t SystemCoreClock = 16000000;\r
+__I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48};\r
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/** @addtogroup STM32L1xx_System_Private_FunctionPrototypes\r
+ * @{\r
+ */\r
+\r
+static void SetSysClock(void);\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/** @addtogroup STM32L1xx_System_Private_Functions\r
+ * @{\r
+ */\r
+\r
+/**\r
+ * @brief Setup the microcontroller system.\r
+ * Initialize the Embedded Flash Interface, the PLL and update the \r
+ * SystemCoreClock variable.\r
+ * @param None\r
+ * @retval None\r
+ */\r
+void SystemInit (void)\r
+{\r
+ /*!< Set MSION bit */\r
+ RCC->CR |= (uint32_t)0x00000100;\r
+\r
+ /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */\r
+ RCC->CFGR &= (uint32_t)0x88FFC00C;\r
+ \r
+ /*!< Reset HSION, HSEON, CSSON and PLLON bits */\r
+ RCC->CR &= (uint32_t)0xEEFEFFFE;\r
+\r
+ /*!< Reset HSEBYP bit */\r
+ RCC->CR &= (uint32_t)0xFFFBFFFF;\r
+\r
+ /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */\r
+ RCC->CFGR &= (uint32_t)0xFF02FFFF;\r
+\r
+ /*!< Disable all interrupts */\r
+ RCC->CIR = 0x00000000;\r
+ \r
+ /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */\r
+ SetSysClock();\r
+\r
+#ifdef VECT_TAB_SRAM\r
+ SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */\r
+#else\r
+ SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */\r
+#endif\r
+}\r
+\r
+/**\r
+ * @brief Update SystemCoreClock according to Clock Register Values\r
+ * @note - The system frequency computed by this function is not the real \r
+ * frequency in the chip. It is calculated based on the predefined \r
+ * constant and the selected clock source:\r
+ * \r
+ * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI \r
+ * value as defined by the MSI range.\r
+ * \r
+ * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)\r
+ * \r
+ * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)\r
+ * \r
+ * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) \r
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.\r
+ * \r
+ * (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value\r
+ * 16 MHz) but the real value may vary depending on the variations\r
+ * in voltage and temperature. \r
+ * \r
+ * (**) HSE_VALUE is a constant defined in stm32l1xx.h file (default value\r
+ * 8 MHz), user has to ensure that HSE_VALUE is same as the real\r
+ * frequency of the crystal used. Otherwise, this function may\r
+ * have wrong result.\r
+ * \r
+ * - The result of this function could be not correct when using fractional\r
+ * value for HSE crystal. \r
+ * @param None\r
+ * @retval None\r
+ */\r
+void SystemCoreClockUpdate (void)\r
+{\r
+ uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, msirange = 0;\r
+\r
+ /* Get SYSCLK source -------------------------------------------------------*/\r
+ tmp = RCC->CFGR & RCC_CFGR_SWS;\r
+ \r
+ switch (tmp)\r
+ {\r
+ case 0x00: /* MSI used as system clock */\r
+ msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;\r
+ SystemCoreClock = (32768 * (1 << (msirange + 1)));\r
+ break;\r
+ case 0x04: /* HSI used as system clock */\r
+ SystemCoreClock = HSI_VALUE;\r
+ break;\r
+ case 0x08: /* HSE used as system clock */\r
+ SystemCoreClock = HSE_VALUE;\r
+ break;\r
+ case 0x0C: /* PLL used as system clock */\r
+ /* Get PLL clock source and multiplication factor ----------------------*/\r
+ pllmul = RCC->CFGR & RCC_CFGR_PLLMUL;\r
+ plldiv = RCC->CFGR & RCC_CFGR_PLLDIV;\r
+ pllmul = PLLMulTable[(pllmul >> 18)];\r
+ plldiv = (plldiv >> 22) + 1;\r
+ \r
+ pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;\r
+\r
+ if (pllsource == 0x00)\r
+ {\r
+ /* HSI oscillator clock selected as PLL clock entry */\r
+ SystemCoreClock = (((HSI_VALUE) * pllmul) / plldiv);\r
+ }\r
+ else\r
+ {\r
+ /* HSE selected as PLL clock entry */\r
+ SystemCoreClock = (((HSE_VALUE) * pllmul) / plldiv);\r
+ }\r
+ break;\r
+ default: /* MSI used as system clock */\r
+ msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE) >> 13;\r
+ SystemCoreClock = (32768 * (1 << (msirange + 1)));\r
+ break;\r
+ }\r
+ /* Compute HCLK clock frequency --------------------------------------------*/\r
+ /* Get HCLK prescaler */\r
+ tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];\r
+ /* HCLK clock frequency */\r
+ SystemCoreClock >>= tmp;\r
+}\r
+\r
+/**\r
+ * @brief Configures the System clock frequency, AHB/APBx prescalers and Flash \r
+ * settings.\r
+ * @note This function should be called only once the RCC clock configuration \r
+ * is reset to the default reset state (done in SystemInit() function). \r
+ * @param None\r
+ * @retval None\r
+ */\r
+static void SetSysClock(void)\r
+{\r
+ __IO uint32_t StartUpCounter = 0, HSIStatus = 0;\r
+ \r
+ /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/\r
+ /* Enable HSI */\r
+ RCC->CR |= ((uint32_t)RCC_CR_HSION);\r
+ \r
+ /* Wait till HSI is ready and if Time out is reached exit */\r
+ do\r
+ {\r
+ HSIStatus = RCC->CR & RCC_CR_HSIRDY;\r
+ } while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));\r
+\r
+ if ((RCC->CR & RCC_CR_HSIRDY) != RESET)\r
+ {\r
+ HSIStatus = (uint32_t)0x01;\r
+ }\r
+ else\r
+ {\r
+ HSIStatus = (uint32_t)0x00;\r
+ }\r
+ \r
+ if (HSIStatus == (uint32_t)0x01)\r
+ {\r
+ /* Flash 0 wait state */\r
+ FLASH->ACR &= ~FLASH_ACR_LATENCY;\r
+ \r
+ /* Disable Prefetch Buffer */\r
+ FLASH->ACR &= ~FLASH_ACR_PRFTEN;\r
+\r
+ /* Disable 64-bit access */\r
+ FLASH->ACR &= ~FLASH_ACR_ACC64;\r
+ \r
+\r
+ /* Power enable */\r
+ RCC->APB1ENR |= RCC_APB1ENR_PWREN;\r
+ \r
+ /* Select the Voltage Range 1 (1.8 V) */\r
+ PWR->CR = PWR_CR_VOS_0;\r
+ \r
+ \r
+ /* Wait Until the Voltage Regulator is ready */\r
+ while((PWR->CSR & PWR_CSR_VOSF) != RESET)\r
+ {\r
+ }\r
+ \r
+ /* HCLK = SYSCLK /1*/\r
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;\r
+ /* PCLK2 = HCLK /1*/\r
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;\r
+ \r
+ /* PCLK1 = HCLK /1*/\r
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;\r
+ \r
+ /* Select HSI as system clock source */\r
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));\r
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSI;\r
+\r
+ /* Wait till HSI is used as system clock source */\r
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_HSI)\r
+ {\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* If HSI fails to start-up, the application will have wrong clock\r
+ configuration. User can add here some code to deal with this error */\r
+ }\r
+}\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/**\r
+ * @}\r
+ */\r
+\r
+/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/\r
+# make ... for both libusb and libsg
+#
+# make CONFIG_USE_LIBSG=0 ...
+# for just libusb
+#
+CC=gcc
+
CFLAGS+=-g
-CFLAGS+=-DCONFIG_USE_LIBUSB
-CFLAGS+=-DCONFIG_USE_LIBSG
+CFLAGS+=-DCONFIG_USE_LIBUSB=1
CFLAGS+=-DDEBUG
CFLAGS+=-std=gnu99
CFLAGS+=-Wall -Wextra
CFLAGS+=-I../src
-LDFLAGS=-L.. -lstlink -lusb-1.0 -lsgutils2
+LDFLAGS=-lusb-1.0 -L.. -lstlink
+
+ifeq ($(CONFIG_USE_LIBSG),)
+CONFIG_USE_LIBSG=1
+endif
+
+ifneq ($(CONFIG_USE_LIBSG),0)
+CFLAGS+=-DCONFIG_USE_LIBSG=1
+LDFLAGS+=-lsgutils2
+endif
SRCS=main.c
OBJS=$(SRCS:.c=.o)
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
#include "stlink-common.h"
-int main(int ac, char** av)
+struct opts
{
- /* stlinkv1 command line: ./flash /dev/sgX path addr */
- /* stlinkv2 command line: ./flash path addr */
-
- stlink_t* sl = NULL;
+ unsigned int do_read;
+ const char* devname;
+ const char* filename;
stm32_addr_t addr;
- const char* path;
- int err;
+ size_t size;
+};
+
+static void usage(void)
+{
+ puts("stlinkv1 command line: ./flash {read|write} /dev/sgX path addr <size>");
+ puts("stlinkv2 command line: ./flash {read|write} path addr <size>");
+}
+
+static int get_opts(struct opts* o, int ac, char** av)
+{
+ /* stlinkv1 command line: ./flash {read|write} /dev/sgX path addr <size> */
+ /* stlinkv2 command line: ./flash {read|write} path addr <size> */
+
+ unsigned int i = 0;
+
+ if (ac < 3) return -1;
- if (ac == 4) /* stlinkv1 */
+ /* stlinkv2 */
+ o->devname = NULL;
+
+ if (strcmp(av[0], "read") == 0)
{
- static const int scsi_verbose = 2;
- sl = stlink_quirk_open(av[1], scsi_verbose);
- path = av[2];
- addr = strtoul(av[3], NULL, 16);
+ o->do_read = 1;
+
+ /* stlinkv1 mode */
+ if (ac == 5)
+ {
+ o->devname = av[1];
+ i = 1;
+ }
+
+ o->size = strtoul(av[i + 3], NULL, 10);
}
- else if (ac == 3) /* stlinkv2 */
+ else if (strcmp(av[0], "write") == 0)
{
- sl = stlink_open_usb(NULL, 10);
- path = av[1];
- addr = strtoul(av[2], NULL, 16);
+ o->do_read = 0;
+
+ /* stlinkv1 mode */
+ if (ac == 4)
+ {
+ o->devname = av[1];
+ i = 1;
+ }
}
- else /* invalid */
+ else
+ {
+ return -1;
+ }
+
+ o->filename = av[i + 1];
+ o->addr = strtoul(av[i + 2], NULL, 16);
+
+ return 0;
+}
+
+
+int main(int ac, char** av)
+{
+ stlink_t* sl = NULL;
+ struct opts o;
+ int err = -1;
+
+ if (get_opts(&o, ac - 1, av + 1) == -1)
{
printf("invalid command line\n");
+ usage();
goto on_error;
}
- if (sl == NULL) goto on_error;
-
- err = stlink_fwrite_flash(sl, path, addr);
- if (err == -1)
+ if (o.devname != NULL) /* stlinkv1 */
{
- printf("stlink_fwrite_flash() == -1\n");
+#if CONFIG_USE_LIBSG
+ static const int scsi_verbose = 2;
+ sl = stlink_quirk_open(o.devname, scsi_verbose);
+ if (sl == NULL) goto on_error;
+#else
+ printf("not compiled for use with STLink/V1");
goto on_error;
+#endif
+ }
+ else /* stlinkv2 */
+ {
+ sl = stlink_open_usb(10);
+ if (sl == NULL) goto on_error;
}
+ if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE)
+ stlink_exit_dfu_mode(sl);
+
+ if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
+ stlink_enter_swd_mode(sl);
+
+ stlink_reset(sl);
+
+ if (o.do_read == 0) /* write */
+ {
+ err = stlink_fwrite_flash(sl, o.filename, o.addr);
+ if (err == -1)
+ {
+ printf("stlink_fwrite_flash() == -1\n");
+ goto on_error;
+ }
+ }
+ else /* read */
+ {
+ err = stlink_fread(sl, o.filename, o.addr, o.size);
+ if (err == -1)
+ {
+ printf("stlink_fread() == -1\n");
+ goto on_error;
+ }
+ }
+
+ /* success */
+ err = 0;
+
on_error:
if (sl != NULL) stlink_close(sl);
+# make ... for both libusb and libsg
+#
+# make CONFIG_USE_LIBSG=0 ...
+# for just libusb
+#
PRG := st-util
OBJS = gdb-remote.o gdb-server.o
CFLAGS+=-g -Wall -Werror -std=gnu99 -I../src
-CFLAGS+=-DCONFIG_USE_LIBUSB
-CFLAGS+=-DCONFIG_USE_LIBSG
-LIBS := -lstlink -lusb-1.0 -lsgutils2
-LDFLAGS+=$(LIBS) -L..
+CFLAGS+=-DCONFIG_USE_LIBUSB=1
+LDFLAGS=-lusb-1.0 -L.. -lstlink
+ifeq ($(CONFIG_USE_LIBSG),)
+CONFIG_USE_LIBSG=1
+endif
+
+ifneq ($(CONFIG_USE_LIBSG),0)
+CFLAGS+=-DCONFIG_USE_LIBSG=1
+LDFLAGS+=-lsgutils2
+endif
all: $(PRG)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <signal.h>
#include <stlink-common.h>
#define FLASH_PAGE_MASK (~((1 << 10) - 1))
#define FLASH_SIZE (FLASH_PAGE * 128)
+volatile int do_exit = 0;
+void ctrl_c(int sig)
+{
+ do_exit = 1;
+}
+
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;
{ 0x410, "F1 Medium-density device", 0x1ffff7e0,
0x20000, 0x400, 0x5000, 0x1ffff000, 0x800 }, // table 2, pm0063
{ 0x411, "F2 device", 0, /* No flash size register found in the docs*/
- 0x100000, 0x20000, 0x20000, 0x1ff00000, 0x7800 }, // table 1, pm0059
+ 0x100000, 0x20000, 0x20000, 0x1fff0000, 0x7800 }, // table 1, pm0059
{ 0x412, "F1 Low-density device", 0x1ffff7e0,
0x8000, 0x400, 0x2800, 0x1ffff000, 0x800 }, // table 1, pm0063
{ 0x413, "F4 device", 0x1FFF7A10,
- 0x100000, 0x20000, 0x20000, 0x1ff00000, 0x7800 }, // table 1, pm0081
+ 0x100000, 0x20000, 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,
switch(argc) {
- default: {
- fprintf(stderr, HelpStr, NULL);
- return 1;
- }
-
case 3 : {
//sl = stlink_quirk_open(argv[2], 0);
- // FIXME - hardcoded to usb....
- sl = stlink_open_usb(argv[2], 10);
+ // FIXME - hardcoded to usb....
+ sl = stlink_open_usb(10);
if(sl == NULL) return 1;
break;
}
}
}
+#if CONFIG_USE_LIBSG
case 1 : { // Search ST-LINK (from /dev/sg0 to /dev/sg99)
const int DevNumMax = 99;
int ExistDevCount = 0;
}
break;
}
+#endif
+
+ default: {
+ fprintf(stderr, HelpStr, NULL);
+ return 1;
+ }
}
- if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
- stlink_exit_dfu_mode(sl);
- }
+ if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
+ stlink_exit_dfu_mode(sl);
+ }
if(stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) {
stlink_enter_swd_mode(sl);
}
uint32_t chip_id = stlink_chip_id(sl);
- printf("Chip ID is %08x.\n", chip_id);
+ 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;
+ }
+
+ printf("Chip ID is %08x, Core ID is %08x.\n", chip_id, core_id);
const struct chip_params* params = NULL;
while(serve(sl, port) == 0);
+ /* Switch back to mass storage mode before closing. */
+ stlink_run(sl);
+ stlink_exit_debug_mode(sl);
stlink_close(sl);
return 0;
printf("Listening at *:%d...\n", port);
+ (void) signal (SIGINT, ctrl_c);
int client = accept(sock, NULL, NULL);
+ signal (SIGINT, SIG_DFL);
if(client < 0) {
perror("accept");
return 1;
/* sram settings */
#define STM32_SRAM_BASE 0x20000000
#define STM32_SRAM_SIZE (8 * 1024)
+#define STM32L_SRAM_SIZE (16 * 1024)
stm32_addr_t sram_base;
size_t sram_size;
#include <sys/stat.h>
#include <sys/mman.h>
+#include "stlink-common.h"
+
+#if CONFIG_USE_LIBSG
// sgutils2 (apt-get install libsgutils2-dev)
#include <scsi/sg_lib.h>
#include <scsi/sg_pt.h>
-
-#include "stlink-common.h"
#include "stlink-sg.h"
+#endif
// Suspends execution of the calling process for
-#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stlink-common.h"
#include "stlink-usb.h"
+enum SCSI_Generic_Direction {SG_DXFER_TO_DEV=0, SG_DXFER_FROM_DEV=0x80};
+
void _stlink_usb_close(stlink_t* sl) {
struct stlink_libusb * const handle = sl->backend_data;
// maybe we couldn't even get the usb device?
if (handle->rep_trans != NULL)
libusb_free_transfer(handle->rep_trans);
- if (handle->usb_handle != NULL)
+ if (handle->usb_handle != NULL) {
libusb_close(handle->usb_handle);
+ }
libusb_exit(handle->libusb_ctx);
free(handle);
return 0;
}
-ssize_t send_recv(struct stlink_libusb* handle,
+ssize_t send_recv(struct stlink_libusb* handle, int terminate,
unsigned char* txbuf, size_t txsize,
unsigned char* rxbuf, size_t rxsize) {
/* note: txbuf and rxbuf can point to the same area */
+ int res = 0;
libusb_fill_bulk_transfer(handle->req_trans, handle->usb_handle,
handle->ep_req,
0
);
- printf("submit_wait(req)\n");
-
if (submit_wait(handle, handle->req_trans)) return -1;
/* send_only */
- if (rxsize == 0) return 0;
-
- /* read the response */
-
- libusb_fill_bulk_transfer(handle->rep_trans, handle->usb_handle,
- handle->ep_rep, rxbuf, rxsize, NULL, NULL, 0);
-
- printf("submit_wait(rep)\n");
-
- if (submit_wait(handle, handle->rep_trans)) return -1;
+ if (rxsize != 0) {
+
+ /* read the response */
+
+ libusb_fill_bulk_transfer(handle->rep_trans, handle->usb_handle,
+ handle->ep_rep, rxbuf, rxsize, NULL, NULL, 0);
+
+ if (submit_wait(handle, handle->rep_trans)) return -1;
+ res = handle->rep_trans->actual_length;
+ }
+ if ((handle->protocoll == 1) && terminate) {
+ /* Read the SG reply */
+ unsigned char sg_buf[13];
+ libusb_fill_bulk_transfer
+ (handle->rep_trans, handle->usb_handle,
+ handle->ep_rep, sg_buf, 13, NULL, NULL, 0);
+ res = submit_wait(handle, handle->rep_trans);
+ /* The STLink doesn't seem to evaluate the sequence number */
+ handle->sg_transfer_idx++;
+ if (res ) return -1;
+ }
return handle->rep_trans->actual_length;
}
static inline int send_only
-(struct stlink_libusb* handle, unsigned char* txbuf, size_t txsize) {
- return send_recv(handle, txbuf, txsize, NULL, 0);
+(struct stlink_libusb* handle, int terminate,
+ unsigned char* txbuf, size_t txsize) {
+ return send_recv(handle, terminate, txbuf, txsize, NULL, 0);
}
-// KARL - fixme, common code! (or, one per backend)
-// candidate for common code...
-
-
-static int is_stlink_device(libusb_device * dev) {
+/* Search for a STLINK device, either any or teh one with the given PID
+ * Return the protocoll version
+ */
+static int is_stlink_device(libusb_device * dev, uint16_t pid) {
struct libusb_device_descriptor desc;
+ int version;
if (libusb_get_device_descriptor(dev, &desc))
return 0;
- printf("device: 0x%04x, 0x%04x\n", desc.idVendor, desc.idProduct);
-
if (desc.idVendor != USB_ST_VID)
return 0;
- if (desc.idProduct != USB_STLINK_32L_PID)
+ if ((desc.idProduct != USB_STLINK_32L_PID) &&
+ (desc.idProduct != USB_STLINK_PID ))
+ return 0;
+
+ if(pid && (pid != desc.idProduct))
return 0;
+ if (desc.idProduct == USB_STLINK_PID )
+ version = 1;
+ else
+ version = 2;
- return 1;
+ return version;
+}
+
+static int fill_command
+(stlink_t * sl, enum SCSI_Generic_Direction dir, uint32_t len) {
+ struct stlink_libusb * const slu = sl->backend_data;
+ unsigned char* const cmd = sl->c_buf;
+ int i = 0;
+ memset(cmd, 0, sizeof (sl->c_buf));
+ if(slu->protocoll == 1) {
+ cmd[i++] = 'U';
+ cmd[i++] = 'S';
+ cmd[i++] = 'B';
+ cmd[i++] = 'C';
+ write_uint32(&cmd[i], slu->sg_transfer_idx);
+ write_uint32(&cmd[i + 4], len);
+ i += 8;
+ cmd[i++] = (dir == SG_DXFER_FROM_DEV)?0x80:0;
+ cmd[i++] = 0; /* Logical unit */
+ cmd[i++] = 0xa; /* Command length */
+ }
+ return i;
}
void _stlink_usb_version(stlink_t *sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ uint32_t rep_len = 6;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_GET_VERSION;
- buf[1] = 0x80;
+ cmd[i++] = STLINK_GET_VERSION;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 6);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
}
-
-#if 1 /* DEBUG */
- {
- ssize_t i;
- for (i = 0; i < size; ++i) printf("%02x", buf[i]);
- printf("\n");
- }
-#endif /* DEBUG */
}
void _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char *cmd_buf = sl->c_buf;
-
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_DEBUG_COMMAND;
- cmd_buf[1] = STLINK_DEBUG_WRITEMEM_32BIT;
- write_uint32(cmd_buf + 2, addr);
- write_uint16(cmd_buf + 6, len);
- send_only(slu, cmd_buf, STLINK_CMD_SIZE);
-
-#if Q_BUF_LEN < UINT16_MAX
- assert(len < sizeof(sl->q_buf)); // makes a compiler warning? always true?
-#endif
- assert((len & 3) == 0);
- send_only(slu, buf, len);
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
+
+ int i = fill_command(sl, SG_DXFER_TO_DEV, len);
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_WRITEMEM_32BIT;
+ write_uint32(&cmd[i], addr);
+ write_uint16(&cmd[i + 4], len);
+ send_only(slu, 0, cmd, slu->cmd_len);
+ send_only(slu, 1, data, len);
}
void _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char *cmd_buf = sl->c_buf;
-
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_DEBUG_COMMAND;
- cmd_buf[1] = STLINK_DEBUG_WRITEMEM_8BIT;
- write_uint32(cmd_buf + 2, addr);
- write_uint16(cmd_buf + 6, len);
- send_only(slu, cmd_buf, STLINK_CMD_SIZE);
-
-#if Q_BUF_LEN < UINT16_MAX
- assert(len < sizeof(sl->q_buf)); // makes a compiler warning? always true?
-#endif
- send_only(slu, buf, len);
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
+
+ int i = fill_command(sl, SG_DXFER_TO_DEV, 0);
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_WRITEMEM_8BIT;
+ write_uint32(&cmd[i], addr);
+ write_uint16(&cmd[i + 4], len);
+ send_only(slu, 0, cmd, slu->cmd_len);
+ send_only(slu, 1, data, len);
}
int _stlink_usb_current_mode(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
+ unsigned char* const data = sl->q_buf;
ssize_t size;
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_GET_CURRENT_MODE;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 2);
+ int rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+
+ cmd[i++] = STLINK_GET_CURRENT_MODE;
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return -1;
void _stlink_usb_core_id(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
+ unsigned char* const data = sl->q_buf;
ssize_t size;
+ int rep_len = 4;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_READCOREID;
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_READCOREID;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 4);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
}
- sl->core_id = read_uint32(buf, 0);
+ sl->core_id = read_uint32(data, 0);
}
void _stlink_usb_status(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_GETSTATUS;
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_GETSTATUS;
-
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 2);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
}
-
- /* todo: stlink_core_stat */
-
- // FIXME - decode into sl->core_stat
-#if 1 /* DEBUG */
- printf("status == 0x%x\n", buf[0]);
-#endif /* DEBUG */
-
}
void _stlink_usb_force_debug(stlink_t *sl) {
struct stlink_libusb *slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
-
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_FORCEDEBUG;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 2);
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_FORCEDEBUG;
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
}
}
-
void _stlink_usb_enter_swd_mode(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ const int rep_len = 0;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_ENTER;
+ cmd[i++] = STLINK_DEBUG_ENTER_SWD;
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_SWD_ENTER;
- buf[2] = STLINK_DEBUG_ENTER_SWD;
-
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 2);
+ size = send_only(slu, 1, cmd, slu->cmd_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
void _stlink_usb_exit_dfu_mode(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DFU_COMMAND;
- buf[1] = STLINK_DFU_EXIT;
+ cmd[i++] = STLINK_DFU_COMMAND;
+ cmd[i++] = STLINK_DFU_EXIT;
- size = send_only(slu, buf, 16);
+ size = send_only(slu, 1, cmd, slu->cmd_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
*/
void _stlink_usb_reset(stlink_t * sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_RESETSYS;
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_RESETSYS;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, sizeof (sl->q_buf));
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
void _stlink_usb_step(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_STEPCORE;
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_STEPCORE;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 2);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
*/
void _stlink_usb_run(stlink_t* sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_RUNCORE;
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_RUNCORE;
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, 2);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
}
-
}
void _stlink_usb_exit_debug_mode(stlink_t *sl) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, 0);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_EXIT;
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_EXIT;
- size = send_only(slu, buf, 16);
+ size = send_only(slu, 1, cmd, slu->cmd_len);
if (size == -1) {
printf("[!] send_only\n");
return;
void _stlink_usb_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, len);
- /* assume len < sizeof(sl->q_buf) */
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_READMEM_32BIT;
+ write_uint32(&cmd[i], addr);
+ write_uint16(&cmd[i + 4], len);
- memset(buf, 0, sizeof (sl->q_buf));
- buf[0] = STLINK_DEBUG_COMMAND;
- buf[1] = STLINK_DEBUG_READMEM_32BIT;
- write_uint32(buf + 2, addr);
- /* windows usb logs show only one byte is used for length ... */
- // Presumably, this is because usb transfers can't be 16 bits worth of bytes long...
- assert (len < 256);
- buf[6] = (uint8_t) len;
-
- size = send_recv(slu, buf, STLINK_CMD_SIZE, buf, len);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, len);
if (size == -1) {
printf("[!] send_recv\n");
return;
stlink_print_data(sl);
}
-
-#if 1 /* stlinkv1 */
-
void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char* const cmd_buf = sl->c_buf;
+ unsigned char* const cmd = sl->c_buf;
+ unsigned char* const data = sl->q_buf;
ssize_t size;
- int i;
+ uint32_t rep_len = 84;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_DEBUG_COMMAND;
- cmd_buf[1] = STLINK_DEBUG_READALLREGS;
- size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 84);
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_READALLREGS;
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
DD(sl, "rw2 = 0x%08x\n", read_uint32(sl->q_buf, 80));
}
-#else /* stlinkv2 */
-
-static void _stlink_usb_read_all_regs(stlink_t *sl, reg *regp) {
- struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char* const cmd_buf = sl->c_buf;
- ssize_t size;
- int i;
-
-#define STLINK_JTAG_COMMAND 0xf2
-#define STLINK_JTAG_READALLREGS2 0x3a
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_JTAG_COMMAND;
- cmd_buf[1] = STLINK_JTAG_READALLREGS2;
- size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 84);
-
- if (size == -1) {
- printf("[!] send_recv\n");
- return;
- }
-
- sl->q_len = (size_t) size;
-
- for(i=0; i<16; i++)
- regp->r[i]= read_uint32(sl->q_buf, i*4);
-
- regp->xpsr = read_uint32(sl->q_buf, 64);
- regp->main_sp = read_uint32(sl->q_buf, 68);
- regp->process_sp = read_uint32(sl->q_buf, 72);
- regp->rw = read_uint32(sl->q_buf, 76);
- regp->rw2 = read_uint32(sl->q_buf, 80);
-}
-
-#endif /* stlinkv1 */
-
void _stlink_usb_read_reg(stlink_t *sl, int r_idx, reg *regp) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char* const cmd_buf = sl->c_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
uint32_t r;
+ uint32_t rep_len = 4;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_DEBUG_COMMAND;
- cmd_buf[1] = STLINK_DEBUG_READREG;
- cmd_buf[2] = (uint8_t) r_idx;
- size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 4);
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_READREG;
+ cmd[i++] = (uint8_t) r_idx;
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
regp->process_sp = r;
break;
case 19:
- regp->rw = r; //XXX ?(primask, basemask etc.)
+ regp->rw = r; /* XXX ?(primask, basemask etc.) */
break;
case 20:
- regp->rw2 = r; //XXX ?(primask, basemask etc.)
+ regp->rw2 = r; /* XXX ?(primask, basemask etc.) */
break;
default:
regp->r[r_idx] = r;
}
}
-
-#if 1 /* stlinkv1 */
-
void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char *cmd_buf = sl->c_buf;
+ unsigned char* const data = sl->q_buf;
+ unsigned char* const cmd = sl->c_buf;
ssize_t size;
-
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_DEBUG_COMMAND;
- cmd_buf[1] = STLINK_DEBUG_WRITEREG;
- cmd_buf[2] = idx;
- write_uint32(cmd_buf + 3, reg);
- size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 2);
+ uint32_t rep_len = 2;
+ int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len);
+
+ cmd[i++] = STLINK_DEBUG_COMMAND;
+ cmd[i++] = STLINK_DEBUG_WRITEREG;
+ cmd[i++] = idx;
+ write_uint32(&cmd[i], reg);
+ size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len);
if (size == -1) {
printf("[!] send_recv\n");
return;
stlink_print_data(sl);
}
-#else /* stlinkv2 */
-
-void _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) {
- struct stlink_libusb * const slu = sl->backend_data;
- unsigned char* const buf = sl->q_buf;
- unsigned char *cmd_buf = sl->c_buf;
- ssize_t size;
-
-#define STLINK_JTAG_WRITEREG2 0x34
- memset(cmd_buf, 0, STLINK_CMD_SIZE);
- cmd_buf[0] = STLINK_JTAG_COMMAND;
- cmd_buf[1] = STLINK_JTAG_WRITEREG2;
- cmd_buf[2] = idx;
- write_uint32(cmd_buf + 3, reg);
- size = send_recv(slu, cmd_buf, STLINK_CMD_SIZE, buf, 2);
- if (size == -1) {
- printf("[!] send_recv\n");
- return;
- }
- sl->q_len = (size_t) size;
- stlink_print_data(sl);
-}
-
-#endif /* stlinkv1 */
-
-
stlink_backend_t _stlink_usb_backend = {
_stlink_usb_close,
_stlink_usb_exit_debug_mode,
};
-stlink_t* stlink_open_usb(const char *dev_name, const int verbose) {
+stlink_t* stlink_open_usb(const int verbose) {
stlink_t* sl = NULL;
struct stlink_libusb* slu = NULL;
-
- /* unused */
- dev_name = dev_name;
+ int error = -1;
+ libusb_device** devs = NULL;
+ libusb_device* dev;
+ ssize_t i;
+ ssize_t count;
+ int config;
+ char *iSerial = NULL;
sl = malloc(sizeof (stlink_t));
slu = malloc(sizeof (struct stlink_libusb));
if (sl == NULL) goto on_error;
if (slu == NULL) goto on_error;
+ memset(sl, 0, sizeof (stlink_t));
+ memset(slu, 0, sizeof (struct stlink_libusb));
sl->verbose = verbose;
+ sl->backend = &_stlink_usb_backend;
+ sl->backend_data = slu;
- if (slu->libusb_ctx != NULL) {
- fprintf(stderr, "reopening with an existing context? undefined behaviour!\n");
- goto on_error;
- } else {
- if (libusb_init(&(slu->libusb_ctx))) {
- fprintf(stderr, "failed to init libusb context, wrong version of libraries?\n");
- goto on_error;
- }
- }
+ sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
- int error = -1;
+ /* flash memory settings */
+ sl->flash_base = STM32_FLASH_BASE;
+ sl->flash_size = STM32_FLASH_SIZE;
+ sl->flash_pgsz = STM32_FLASH_PGSZ;
- libusb_device** devs = NULL;
- libusb_device* dev;
- ssize_t i;
- ssize_t count;
- int 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 = STM32L_SRAM_SIZE;
+ if (libusb_init(&(slu->libusb_ctx))) {
+ fprintf(stderr, "failed to init libusb context, wrong version of libraries?\n");
+ goto on_error;
+ }
+
count = libusb_get_device_list(slu->libusb_ctx, &devs);
if (count < 0) {
printf("libusb_get_device_list\n");
for (i = 0; i < count; ++i) {
dev = devs[i];
- if (is_stlink_device(dev)) break;
+ slu->protocoll = is_stlink_device(dev, 0);
+ if (slu->protocoll > 0) break;
}
- if (i == count) return NULL;
+ if (i == count) goto on_libusb_error;
if (libusb_open(dev, &(slu->usb_handle))) {
printf("libusb_open()\n");
goto on_libusb_error;
}
+
+ if (iSerial) {
+ unsigned char serial[256];
+ struct libusb_device_descriptor desc;
+ int r;
+
+ r = libusb_get_device_descriptor(dev, &desc);
+ if (r<0) {
+ printf("Can't get descriptor to match Iserial\n");
+ goto on_libusb_error;
+ }
+ r = libusb_get_string_descriptor_ascii
+ (slu->usb_handle, desc.iSerialNumber, serial, 256);
+ if (r<0) {
+ printf("Can't get Serialnumber to match Iserial\n");
+ goto on_libusb_error;
+ }
+ if (strcmp((char*)serial, iSerial)) {
+ printf("Mismatch in serial numbers, dev %s vs given %s\n",
+ serial, iSerial);
+ goto on_libusb_error;
+ }
+ }
+
+ if (libusb_kernel_driver_active(slu->usb_handle, 0) == 1) {
+ int r;
+
+ r = libusb_detach_kernel_driver(slu->usb_handle, 0);
+ if (r<0)
+ printf("libusb_detach_kernel_driver(() error %s\n", strerror(-r));
+ goto on_libusb_error;
+ }
if (libusb_get_configuration(slu->usb_handle, &config)) {
/* this may fail for a previous configured device */
slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
- /* libusb_reset_device(slu->usb_handle); */
+ slu->sg_transfer_idx = 0;
+ slu->cmd_len = (slu->protocoll == 1)? STLINK_SG_SIZE: STLINK_CMD_SIZE;
/* success */
+ if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) {
+ printf("-- exit_dfu_mode\n");
+ stlink_exit_dfu_mode(sl);
+ }
+ stlink_version(sl);
error = 0;
on_libusb_error:
if (devs != NULL) {
libusb_free_device_list(devs, 1);
- fprintf(stderr, "freed libusb device list\n");
}
if (error == -1) {
return NULL;
}
- sl->backend = &_stlink_usb_backend;
- sl->backend_data = slu;
/* success */
return sl;
#include <libusb-1.0/libusb.h>
#include "stlink-common.h"
+#define STLINK_SG_SIZE 31
#define STLINK_CMD_SIZE 16
#if defined(CONFIG_USE_LIBUSB)
struct libusb_transfer* rep_trans;
unsigned int ep_req;
unsigned int ep_rep;
+ int protocoll;
+ unsigned int sg_transfer_idx;
+ unsigned int cmd_len;
};
#else
#error "it's all bad!"
#endif
- stlink_t* stlink_open_usb(const char *dev_name, const int verbose);
+ stlink_t* stlink_open_usb(const int verbose);
#ifdef __cplusplus
#include <stdio.h>
#include <stdlib.h>
+#if CONFIG_USE_LIBSG
#include <scsi/sg_lib.h>
#include <scsi/sg_pt.h>
+#endif
#include "stlink-common.h"
int main(int argc, char *argv[]) {
//fflush(stderr); fflush(stdout);
return EXIT_SUCCESS;
-}
\ No newline at end of file
+}
ac = ac;
av = av;
- sl = stlink_open_usb(NULL, 10);
+ sl = stlink_open_usb(10);
if (sl != NULL) {
printf("-- version\n");
stlink_version(sl);