├── .gitignore ├── README.md ├── spi.v ├── spi_driver.pcf ├── spi_driver.sdc ├── spi_driver.v ├── spi_tb.v └── stm32-spi-test ├── .gitignore ├── CMakeLists.txt ├── build.sh ├── debug.c ├── debug.h ├── delay.c ├── delay.h ├── gcc_stm32.cmake ├── interrupts.c ├── main.c ├── openocd.cfg ├── openocd.telnet.cfg ├── platform_config.h ├── run-cmake.sh ├── stm32_flash.ld.in ├── stm32f10x_conf.h ├── system_stm32f10x.c ├── time.c ├── time.h └── upload.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | This is a simple SPI slave device for FPGAs. The project file is for a Lattice iCEblink40 development board. 3 | The STM32 test driver is for an STM32F103 ARM microcontroller. 4 | -------------------------------------------------------------------------------- /spi.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module SPI_slave(clk, sck, mosi, miso, ssel, byteReceived, receivedData, dataNeeded, dataToSend); 4 | input wire clk; 5 | input wire sck; 6 | input wire mosi; 7 | output wire miso; 8 | input wire ssel; 9 | output reg byteReceived = 1'b0; 10 | output reg[7:0] receivedData = 8'b00000000; 11 | output wire dataNeeded; 12 | input wire[7:0] dataToSend; 13 | 14 | reg[1:0] sckr; 15 | reg[1:0] mosir; 16 | reg[2:0] bitcnt; // SPI is 8-bits, so we need a 3 bits counter to count the bits as they come in 17 | reg[7:0] dataToSendBuffer; 18 | 19 | wire ssel_active = ~ssel; 20 | 21 | always @(posedge clk) begin 22 | if(~ssel_active) 23 | sckr <= 2'b00; 24 | else 25 | sckr <= { sckr[0], sck }; 26 | end 27 | wire sck_risingEdge = (sckr == 2'b01); 28 | wire sck_fallingEdge = (sckr == 2'b10); 29 | 30 | always @(posedge clk) begin 31 | if(~ssel_active) 32 | mosir <= 2'b00; 33 | else 34 | mosir <= { mosir[0], mosi }; 35 | end 36 | wire mosi_data = mosir[1]; 37 | 38 | always @(posedge clk) begin 39 | if(~ssel_active) begin 40 | bitcnt <= 3'b000; 41 | receivedData <= 8'h00; 42 | end 43 | else if(sck_risingEdge) begin 44 | bitcnt <= bitcnt + 3'b001; 45 | receivedData <= { receivedData[6:0], mosi_data }; 46 | end 47 | end 48 | 49 | always @(posedge clk) 50 | byteReceived <= ssel_active && sck_risingEdge && (bitcnt == 3'b111); 51 | 52 | always @(posedge clk) begin 53 | if(~ssel_active) 54 | dataToSendBuffer <= 8'h00; 55 | else if(bitcnt == 3'b000) 56 | dataToSendBuffer <= dataToSend; 57 | else if(sck_fallingEdge) 58 | dataToSendBuffer <= { dataToSendBuffer[6:0], 1'b0}; 59 | end 60 | 61 | assign dataNeeded = ssel_active && (bitcnt == 3'b000); 62 | assign miso = dataToSendBuffer[7]; 63 | endmodule 64 | -------------------------------------------------------------------------------- /spi_driver.pcf: -------------------------------------------------------------------------------- 1 | set_io CLK_3_33_MHZ 13 2 | 3 | set_io sck 19 4 | set_io mosi 16 5 | set_io miso 15 6 | set_io ssel 100 7 | 8 | set_io leds[0] 59 9 | set_io leds[1] 56 10 | set_io leds[2] 53 11 | set_io leds[3] 51 12 | set_io leds[4] 26 13 | set_io leds[5] 27 14 | set_io leds[6] 28 15 | set_io leds[7] 29 16 | 17 | -------------------------------------------------------------------------------- /spi_driver.sdc: -------------------------------------------------------------------------------- 1 | #create_clock -period 10.000 -name clk1 [ get_nets CLK_3P3_MHZ ] 2 | define_clock {CLK_3_33_MHZ} -name {CLK_3_33_MHZ} -freq 3.33 -clockgroup default_clkgroup_0 3 | -------------------------------------------------------------------------------- /spi_driver.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module SPI_driver(CLK_3_33_MHZ, sck, mosi, miso, ssel, leds); 4 | input wire CLK_3_33_MHZ; 5 | input wire sck; 6 | input wire mosi; 7 | output wire miso; 8 | input wire ssel; 9 | output wire[7:0] leds; 10 | 11 | wire byteReceived; 12 | wire[7:0] receivedData; 13 | wire dataNeeded; 14 | reg[7:0] dataToSend; 15 | reg[7:0] receivedDataBuffer; 16 | 17 | SPI_slave spi_slave(CLK_3_33_MHZ, sck, mosi, miso, ssel, byteReceived, receivedData, dataNeeded, dataToSend); 18 | 19 | always @(posedge CLK_3_33_MHZ) begin 20 | if(byteReceived) 21 | receivedDataBuffer <= receivedData; 22 | end 23 | 24 | always @(posedge CLK_3_33_MHZ) begin 25 | if(dataNeeded) 26 | dataToSend <= receivedDataBuffer; 27 | end 28 | 29 | assign leds = receivedDataBuffer; 30 | 31 | endmodule -------------------------------------------------------------------------------- /spi_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module SPI_slave_tb; 4 | reg clk; 5 | reg sck; 6 | reg mosi; 7 | wire miso; 8 | reg ssel; 9 | wire byteReceived; 10 | wire[7:0] receivedData; 11 | reg[7:0] expectedData; 12 | wire dataNeeded; 13 | reg[7:0] dataToSend; 14 | reg[7:0] expectedDataToSend; 15 | reg[7:0] misoData; 16 | 17 | SPI_slave spi_slave(clk, sck, mosi, miso, ssel, byteReceived, receivedData, dataNeeded, dataToSend); 18 | 19 | initial 20 | begin 21 | sck = 1'b0; 22 | mosi = 1'b0; 23 | ssel = 1'b1; 24 | misoData = 8'h00; 25 | 26 | #10 ssel = 1'b0; 27 | 28 | expectedData = 8'b11111111; 29 | expectedDataToSend = 8'hff; 30 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 0 31 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 1 32 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 2 33 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 3 34 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 4 35 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 5 36 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 6 37 | #10 mosi = 1'b1; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 7 38 | #10 39 | $display("assertEquals(misoData,0x%h,0x%h)", expectedDataToSend, misoData); 40 | 41 | expectedData = 8'b00000000; 42 | expectedDataToSend = 8'h00; 43 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 0 44 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 1 45 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 2 46 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 3 47 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 4 48 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 5 49 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 6 50 | #10 mosi = 1'b0; #10 sck = 1'b0; #10 sck = 1'b1; #10 misoData <= { misoData[6:0], miso }; // bit 7 51 | #10 52 | $display("assertEquals(misoData,0x%h,0x%h)", expectedDataToSend, misoData); 53 | 54 | #100 $finish; 55 | end 56 | 57 | always @(*) begin 58 | if(byteReceived) 59 | $display("assertEquals(receivedData,%b,%b)", receivedData, expectedData); 60 | end 61 | 62 | always @(*) begin 63 | if(dataNeeded) 64 | dataToSend = expectedDataToSend; 65 | end 66 | 67 | always 68 | begin 69 | clk = 1'b0; 70 | forever 71 | #1 clk = ~clk; 72 | end 73 | endmodule 74 | -------------------------------------------------------------------------------- /stm32-spi-test/.gitignore: -------------------------------------------------------------------------------- 1 | *-cache.lib 2 | *.bak 3 | *.bck 4 | *.lib~ 5 | *-bak 6 | build/ 7 | *-swp 8 | nbproject/ 9 | .idea/ 10 | 11 | -------------------------------------------------------------------------------- /stm32-spi-test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(stm32-ft312d-test) 2 | 3 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 4 | ENABLE_LANGUAGE(ASM) 5 | 6 | IF(NOT STM32_USB_FS_DEVICE_LIB_DIR) 7 | SET(STM32_USB_FS_DEVICE_LIB_DIR "/opt/STM32_USB-FS-Device_Lib_V4.0.0") 8 | MESSAGE(STATUS "No STM32_USB_FS_DEVICE_LIB_DIR specified, using default: " ${STM32_USB_FS_DEVICE_LIB_DIR}) 9 | ENDIF() 10 | 11 | SET(CMSIS_FIND_LIBS "cmsis_ld") 12 | SET(CMSIS_STARTUP_SOURCE "${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/CMSIS/Device/ST/STM32F10x/Source/Templates/gcc_ride7/startup_stm32f10x_ld.s") 13 | SET(STM32_CHIP_DEF "STM32F10X_LD") 14 | SET(STACK_ADDRESS "0x20005000") 15 | SET(FLASH_SIZE "128K") 16 | SET(RAM_SIZE "20K") 17 | SET(MIN_STACK_SIZE "0x200") 18 | SET(MIN_HEAP_SIZE "0") 19 | SET(EXT_RAM_SIZE "0K") 20 | SET(FLASH_ORIGIN "0x08000000") 21 | SET(RAM_ORIGIN "0x20000000") 22 | SET(EXT_RAM_ORIGIN "0x60000000") 23 | 24 | CONFIGURE_FILE(stm32_flash.ld.in ${CMAKE_CURRENT_BINARY_DIR}/stm32_flash.ld) 25 | 26 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -D${STM32_CHIP_DEF}") 27 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -D${STM32_CHIP_DEF}") 28 | SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_BINARY_DIR}/stm32_flash.ld ${CMAKE_EXE_LINKER_FLAGS}") 29 | 30 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_STDPERIPH_DRIVER") 31 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_STDPERIPH_DRIVER") 32 | 33 | INCLUDE_DIRECTORIES( 34 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/CMSIS/Device/ST/STM32F10x/Include/ 35 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/CMSIS/Include/ 36 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/inc/ 37 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32_USB-FS-Device_Driver/inc/ 38 | ${CMAKE_CURRENT_SOURCE_DIR} 39 | ) 40 | 41 | SET(PROJECT_SOURCES 42 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c 43 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rcc.c 44 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_usart.c 45 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c 46 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_spi.c 47 | ${STM32_USB_FS_DEVICE_LIB_DIR}/Libraries/STM32F10x_StdPeriph_Driver/src/misc.c 48 | system_stm32f10x.c 49 | main.c 50 | debug.c 51 | time.c 52 | delay.c 53 | interrupts.c 54 | ) 55 | 56 | ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}.elf ${PROJECT_SOURCES} ${CMSIS_STARTUP_SOURCE}) 57 | TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME}.elf ${CMSIS_LIBRARIES} ${StdPeriphLib_LIBRARIES}) 58 | 59 | ADD_CUSTOM_TARGET(${CMAKE_PROJECT_NAME}.hex DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Oihex ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.hex) 60 | ADD_CUSTOM_TARGET(${CMAKE_PROJECT_NAME}.bin DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Obinary ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.bin) 61 | ADD_CUSTOM_TARGET(${CMAKE_PROJECT_NAME}.list DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJDUMP} -x -S ${CMAKE_PROJECT_NAME}.elf > ${CMAKE_PROJECT_NAME}.list) 62 | 63 | -------------------------------------------------------------------------------- /stm32-spi-test/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | mkdir -p build 4 | cd build 5 | rm stm32-ft312d-test.elf || echo "Cannot remove. stm32-ft312d-test.elf not build?" 6 | make stm32-ft312d-test.bin && \ 7 | make stm32-ft312d-test.list 8 | -------------------------------------------------------------------------------- /stm32-spi-test/debug.c: -------------------------------------------------------------------------------- 1 | 2 | #include "platform_config.h" 3 | #include "debug.h" 4 | #ifdef DEBUG_ENABLE_USB 5 | #include "usb.h" 6 | #endif 7 | #include 8 | #include 9 | 10 | #define TO_HEX(i) ( (((i) & 0xf) <= 9) ? ('0' + ((i) & 0xf)) : ('A' - 10 + ((i) & 0xf)) ) 11 | 12 | char* itoa(int32_t value, char* result, int base); 13 | char* uitoa(uint32_t value, char* result, int base); 14 | 15 | void debug_setup() { 16 | USART_InitTypeDef usartInitStructure; 17 | GPIO_InitTypeDef gpioInitStructure; 18 | NVIC_InitTypeDef nvicInitStructure; 19 | 20 | RCC_APB2PeriphClockCmd(DEBUG_LED_RCC, ENABLE); 21 | gpioInitStructure.GPIO_Pin = DEBUG_LED_PIN; 22 | gpioInitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 23 | gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz; 24 | GPIO_Init(DEBUG_LED_PORT, &gpioInitStructure); 25 | 26 | /* Enable the USART1 Interrupt */ 27 | nvicInitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ; 28 | nvicInitStructure.NVIC_IRQChannelPreemptionPriority = 3; 29 | nvicInitStructure.NVIC_IRQChannelSubPriority = 3; 30 | nvicInitStructure.NVIC_IRQChannelCmd = ENABLE; 31 | NVIC_Init(&nvicInitStructure); 32 | 33 | usartInitStructure.USART_BaudRate = DEBUG_USART_BAUD; 34 | usartInitStructure.USART_WordLength = USART_WordLength_8b; 35 | usartInitStructure.USART_Parity = USART_Parity_No; 36 | usartInitStructure.USART_StopBits = USART_StopBits_1; 37 | usartInitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 38 | usartInitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 39 | 40 | /* Enable clocks */ 41 | RCC_APB2PeriphClockCmd(DEBUG_USART_RCC, ENABLE); 42 | 43 | /* Configure USART Tx as alternate function push-pull */ 44 | gpioInitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 45 | gpioInitStructure.GPIO_Pin = DEBUG_USART_TX_PIN; 46 | gpioInitStructure.GPIO_Speed = GPIO_Speed_50MHz; 47 | GPIO_Init(DEBUG_USART_TX, &gpioInitStructure); 48 | 49 | /* Configure USART Rx as input floating */ 50 | gpioInitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 51 | gpioInitStructure.GPIO_Pin = DEBUG_USART_RX_PIN; 52 | GPIO_Init(DEBUG_USART_RX, &gpioInitStructure); 53 | 54 | /* USART configuration */ 55 | USART_Init(DEBUG_USART, &usartInitStructure); 56 | 57 | /* Enable USART */ 58 | USART_Cmd(DEBUG_USART, ENABLE); 59 | 60 | /* Enable the USART interrupts */ 61 | USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE); 62 | USART_ITConfig(DEBUG_USART, USART_IT_TXE, DISABLE); 63 | } 64 | 65 | void debug_led_set(int v) { 66 | if (v) { 67 | GPIO_SetBits(DEBUG_LED_PORT, DEBUG_LED_PIN); 68 | } else { 69 | GPIO_ResetBits(DEBUG_LED_PORT, DEBUG_LED_PIN); 70 | } 71 | } 72 | 73 | void debug_write_line(const char* str) { 74 | debug_write(str); 75 | debug_write_ch('\n'); 76 | } 77 | 78 | void debug_write_bytes(const uint8_t *data, uint16_t len) { 79 | for (uint16_t i = 0; i < len; i++) { 80 | debug_write_ch((char) data[i]); 81 | } 82 | } 83 | 84 | void debug_write(const char* str) { 85 | const char *p = str; 86 | while (*p) { 87 | debug_write_ch(*p); 88 | p++; 89 | } 90 | } 91 | 92 | void debug_write_ch(char ch) { 93 | USART_SendData(DEBUG_USART, ch); 94 | while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET); 95 | 96 | #ifdef DEBUG_ENABLE_USB 97 | if (g_usb_initialized) { 98 | usb_write((const uint8_t *) &ch, 1); 99 | } 100 | #endif 101 | } 102 | 103 | void debug_write_u8(uint8_t val, uint8_t base) { 104 | if (base == 16) { 105 | debug_write_ch(TO_HEX(val >> 4)); 106 | debug_write_ch(TO_HEX(val >> 0)); 107 | } else { 108 | char buffer[20]; 109 | uitoa(val, buffer, base); 110 | debug_write(buffer); 111 | } 112 | } 113 | 114 | void debug_write_u16(uint16_t val, uint8_t base) { 115 | if (base == 16) { 116 | debug_write_ch(TO_HEX(val >> 12)); 117 | debug_write_ch(TO_HEX(val >> 8)); 118 | debug_write_ch(TO_HEX(val >> 4)); 119 | debug_write_ch(TO_HEX(val >> 0)); 120 | } else { 121 | char buffer[20]; 122 | uitoa(val, buffer, base); 123 | debug_write(buffer); 124 | } 125 | } 126 | 127 | void debug_write_u32(uint32_t val, uint8_t base) { 128 | if (base == 16) { 129 | debug_write_ch(TO_HEX(val >> 28)); 130 | debug_write_ch(TO_HEX(val >> 24)); 131 | debug_write_ch(TO_HEX(val >> 20)); 132 | debug_write_ch(TO_HEX(val >> 16)); 133 | debug_write_ch(TO_HEX(val >> 12)); 134 | debug_write_ch(TO_HEX(val >> 8)); 135 | debug_write_ch(TO_HEX(val >> 4)); 136 | debug_write_ch(TO_HEX(val >> 0)); 137 | } else { 138 | char buffer[20]; 139 | uitoa(val, buffer, base); 140 | debug_write(buffer); 141 | } 142 | } 143 | 144 | void debug_write_i32(int32_t val, uint8_t base) { 145 | char buffer[20]; 146 | itoa(val, buffer, base); 147 | debug_write(buffer); 148 | } 149 | 150 | void debug_write_u8_array(uint8_t *p, int len) { 151 | for (int i = 0; i < len; i++) { 152 | debug_write_u8(p[i], 16); 153 | debug_write_ch(' '); 154 | } 155 | } 156 | 157 | char* itoa(int32_t value, char* result, int base) { 158 | // check that the base if valid 159 | if (base < 2 || base > 36) { 160 | *result = '\0'; 161 | return result; 162 | } 163 | 164 | char* ptr = result, *ptr1 = result, tmp_char; 165 | int tmp_value; 166 | 167 | do { 168 | tmp_value = value; 169 | value /= base; 170 | *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; 171 | } while (value); 172 | 173 | // Apply negative sign 174 | if (tmp_value < 0) { 175 | *ptr++ = '-'; 176 | } 177 | *ptr-- = '\0'; 178 | while (ptr1 < ptr) { 179 | tmp_char = *ptr; 180 | *ptr-- = *ptr1; 181 | *ptr1++ = tmp_char; 182 | } 183 | return result; 184 | } 185 | 186 | char* uitoa(uint32_t value, char* result, int base) { 187 | // check that the base if valid 188 | if (base < 2 || base > 36) { 189 | *result = '\0'; 190 | return result; 191 | } 192 | 193 | char* ptr = result, *ptr1 = result, tmp_char; 194 | int tmp_value; 195 | 196 | do { 197 | tmp_value = value; 198 | value /= base; 199 | *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; 200 | } while (value); 201 | 202 | *ptr-- = '\0'; 203 | while (ptr1 < ptr) { 204 | tmp_char = *ptr; 205 | *ptr-- = *ptr1; 206 | *ptr1++ = tmp_char; 207 | } 208 | return result; 209 | } 210 | -------------------------------------------------------------------------------- /stm32-spi-test/debug.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DEBUG_H 3 | #define DEBUG_H 4 | 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | void debug_setup(); 12 | void debug_led_set(int v); 13 | void debug_write_line(const char* str); 14 | void debug_write_bytes(const uint8_t *data, uint16_t len); 15 | void debug_write(const char* str); 16 | void debug_write_ch(char ch); 17 | void debug_write_u8(uint8_t val, uint8_t base); 18 | void debug_write_u8_array(uint8_t *p, int len); 19 | void debug_write_u16(uint16_t val, uint8_t base); 20 | void debug_write_u32(uint32_t val, uint8_t base); 21 | void debug_write_i32(int32_t val, uint8_t base); 22 | extern void debug_on_rx(uint8_t* data, uint16_t len); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | #endif /* DEBUG_H */ 29 | 30 | -------------------------------------------------------------------------------- /stm32-spi-test/delay.c: -------------------------------------------------------------------------------- 1 | 2 | #include "delay.h" 3 | 4 | void delay_ms(uint32_t ms) { 5 | volatile uint32_t i; 6 | for(i = ms; i != 0; i--) { 7 | delay_us(1000); 8 | } 9 | } 10 | 11 | void delay_us(uint32_t us) { 12 | volatile uint32_t i; 13 | for(i = (5 * us); i != 0; i--) {} 14 | } 15 | -------------------------------------------------------------------------------- /stm32-spi-test/delay.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DELAY_H 3 | #define DELAY_H 4 | 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | void delay_ms(uint32_t ms); 12 | void delay_us(uint32_t us); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* DELAY_H */ 19 | 20 | -------------------------------------------------------------------------------- /stm32-spi-test/gcc_stm32.cmake: -------------------------------------------------------------------------------- 1 | # GCC toolchain prefix 2 | IF(NOT TOOLCHAIN_PREFIX) 3 | SET(TOOLCHAIN_PREFIX "/opt/arm-2011.09") 4 | MESSAGE(STATUS "No TOOLCHAIN_PREFIX specified, using default: " ${TOOLCHAIN_PREFIX}) 5 | ENDIF() 6 | 7 | IF(NOT TARGET_TRIPLET) 8 | SET(TARGET_TRIPLET "arm-none-eabi") 9 | MESSAGE(STATUS "No TARGET_TRIPLET specified, using default: " ${TARGET_TRIPLET}) 10 | ENDIF() 11 | 12 | SET(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/bin) 13 | SET(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/${TARGET_TRIPLET}/include) 14 | SET(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/${TARGET_TRIPLET}/lib) 15 | 16 | SET(CMAKE_SYSTEM_NAME Generic CACHE INTERNAL "system name") 17 | SET(CMAKE_SYSTEM_PROCESSOR arm CACHE INTERNAL "processor") 18 | 19 | SET(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc CACHE INTERNAL "c compiler") 20 | SET(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-g++ CACHE INTERNAL "cxx compiler") 21 | SET(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-as CACHE INTERNAL "asm compiler") 22 | 23 | SET(CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objcopy CACHE INTERNAL "objcopy") 24 | SET(CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objdump CACHE INTERNAL "objdump") 25 | 26 | SET(CMAKE_C_FLAGS "-isystem ${TOOLCHAIN_INC_DIR} -mthumb -mcpu=cortex-m3 -fno-builtin -Wall -std=gnu99 -fdata-sections -ffunction-sections" CACHE INTERNAL "c compiler flags") 27 | SET(CMAKE_CXX_FLAGS "-isystem ${TOOLCHAIN_INC_DIR} -mthumb -mcpu=cortex-m3 -fno-builtin -Wall -fdata-sections -ffunction-sections" CACHE INTERNAL "cxx compiler flags") 28 | SET(CMAKE_ASM_FLAGS "-mthumb -mcpu=cortex-m3" CACHE INTERNAL "asm compiler flags") 29 | 30 | SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -gstabs+" CACHE INTERNAL "c debug compiler flags") 31 | SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -gstabs+" CACHE INTERNAL "cxx debug compiler flags") 32 | SET(CMAKE_ASM_FLAGS_DEBUG "-g -gstabs+" CACHE INTERNAL "asm debug compiler flags") 33 | 34 | SET(CMAKE_C_FLAGS_RELEASE "-Os -flto" CACHE INTERNAL "c release compiler flags") 35 | SET(CMAKE_CXX_FLAGS_RELEASE "-Os -flto" CACHE INTERNAL "cxx release compiler flags") 36 | SET(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags") 37 | 38 | SET(CMAKE_EXE_LINKER_FLAGS "-nostartfiles -Wl,--gc-sections -mthumb -mcpu=cortex-m3 -flto" CACHE INTERNAL "exe link flags") 39 | SET(CMAKE_MODULE_LINKER_FLAGS "-L${TOOLCHAIN_LIB_DIR} -mthumb -mcpu=cortex-m3 -flto" CACHE INTERNAL "module link flags") 40 | SET(CMAKE_SHARED_LINKER_FLAGS "-L${TOOLCHAIN_LIB_DIR} -mthumb -mcpu=cortex-m3 -flto" CACHE INTERNAL "shared link flags") 41 | 42 | SET(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/${TARGET_TRIPLET} CACHE INTERNAL "cross root directory") 43 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH CACHE INTERNAL "") 44 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE INTERNAL "") 45 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE INTERNAL "") 46 | -------------------------------------------------------------------------------- /stm32-spi-test/interrupts.c: -------------------------------------------------------------------------------- 1 | 2 | #include "time.h" 3 | 4 | void NMI_Handler() { 5 | } 6 | 7 | void HardFault_Handler() { 8 | } 9 | 10 | void MemManage_Handler() { 11 | } 12 | 13 | void BusFault_Handler() { 14 | } 15 | 16 | void UsageFault_Handler() { 17 | } 18 | 19 | void SVC_Handler() { 20 | } 21 | 22 | void DebugMon_Handler() { 23 | } 24 | 25 | void PendSV_Handler() { 26 | } 27 | 28 | void SysTick_Handler() { 29 | time_SysTick_Handler(); 30 | } 31 | -------------------------------------------------------------------------------- /stm32-spi-test/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include "debug.h" 6 | #include "time.h" 7 | #include "delay.h" 8 | #include "platform_config.h" 9 | 10 | void setup(); 11 | void loop(); 12 | void spi_setup(); 13 | void spi_ss_active(); 14 | void spi_ss_inactive(); 15 | 16 | uint8_t i; 17 | 18 | int main(void) { 19 | setup(); 20 | while (1) { 21 | loop(); 22 | } 23 | return 0; 24 | } 25 | 26 | void setup() { 27 | debug_setup(); 28 | time_setup(); 29 | spi_setup(); 30 | 31 | i = 0; 32 | 33 | debug_write_line("?END setup"); 34 | } 35 | 36 | void loop() { 37 | uint8_t data; 38 | 39 | debug_write("?loop "); 40 | debug_write_i32(i, 16); 41 | 42 | debug_led_set(1); 43 | delay_ms(500); 44 | debug_led_set(0); 45 | delay_ms(500); 46 | 47 | spi_ss_active(); 48 | SPI_I2S_SendData(SPIy, i); 49 | //while (SPI_I2S_GetFlagStatus(SPIy, SPI_I2S_FLAG_TXE) == RESET); 50 | while (SPI_I2S_GetFlagStatus(SPIy, SPI_I2S_FLAG_RXNE) == RESET); 51 | data = SPI_I2S_ReceiveData(SPIy); 52 | debug_write(" "); 53 | debug_write_i32(data, 16); 54 | spi_ss_inactive(); 55 | 56 | i++; 57 | debug_write_line(""); 58 | } 59 | 60 | void assert_failed(uint8_t* file, uint32_t line) { 61 | debug_write("-assert_failed: file "); 62 | debug_write((const char*) file); 63 | debug_write(" on line "); 64 | debug_write_u32(line, 10); 65 | debug_write_line(""); 66 | 67 | /* Infinite loop */ 68 | while (1) { 69 | } 70 | } 71 | 72 | void spi_setup() { 73 | SPI_InitTypeDef spiInit; 74 | GPIO_InitTypeDef gpioInit; 75 | 76 | RCC_APB2PeriphClockCmd(SPIy_GPIO_CLK | SPIy_CLK, ENABLE); 77 | 78 | GPIO_StructInit(&gpioInit); 79 | gpioInit.GPIO_Pin = SPIy_PIN_SCK | SPIy_PIN_MOSI; 80 | gpioInit.GPIO_Speed = GPIO_Speed_50MHz; 81 | gpioInit.GPIO_Mode = GPIO_Mode_AF_PP; 82 | GPIO_Init(SPIy_GPIO, &gpioInit); 83 | 84 | gpioInit.GPIO_Pin = SPIy_PIN_SS; 85 | gpioInit.GPIO_Mode = GPIO_Mode_Out_PP; 86 | GPIO_Init(SPIy_GPIO, &gpioInit); 87 | 88 | gpioInit.GPIO_Pin = SPIy_PIN_MISO; 89 | gpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING; 90 | GPIO_Init(SPIy_GPIO, &gpioInit); 91 | 92 | SPI_StructInit(&spiInit); 93 | spiInit.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 94 | spiInit.SPI_Mode = SPI_Mode_Master; 95 | spiInit.SPI_DataSize = SPI_DataSize_8b; 96 | spiInit.SPI_CPOL = SPI_CPOL_Low; 97 | spiInit.SPI_CPHA = SPI_CPHA_1Edge; 98 | spiInit.SPI_NSS = SPI_NSS_Soft; 99 | spiInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; 100 | spiInit.SPI_FirstBit = SPI_FirstBit_MSB; 101 | SPI_Init(SPIy, &spiInit); 102 | 103 | spi_ss_inactive(); 104 | 105 | SPI_Cmd(SPIy, ENABLE); 106 | } 107 | 108 | void spi_ss_active() { 109 | GPIO_ResetBits(SPIy_GPIO, SPIy_PIN_SS); 110 | } 111 | 112 | void spi_ss_inactive() { 113 | GPIO_SetBits(SPIy_GPIO, SPIy_PIN_SS); 114 | } 115 | -------------------------------------------------------------------------------- /stm32-spi-test/openocd.cfg: -------------------------------------------------------------------------------- 1 | telnet_port 4444 2 | gdb_port 3333 3 | 4 | # cat /opt/arm-linaro-eabi-4.6/share/openocd/scripts/interface/olimex-arm-usb-ocd.cfg >> ./openocd.cfg 5 | # 6 | # Olimex ARM-USB-OCD 7 | # 8 | # http://www.olimex.com/dev/arm-usb-ocd.html 9 | # 10 | interface ft2232 11 | ft2232_device_desc "Olimex OpenOCD JTAG" 12 | ft2232_layout olimex-jtag 13 | ft2232_vid_pid 0x15ba 0x0003 14 | 15 | # cat /opt/arm-linaro-eabi-4.6/share/openocd/scripts/target/stm32f1x.cfg >> openocd.cfg 16 | # script for stm32f1x family 17 | 18 | if { [info exists CHIPNAME] } { 19 | set _CHIPNAME $CHIPNAME 20 | } else { 21 | set _CHIPNAME stm32f1x 22 | } 23 | 24 | if { [info exists ENDIAN] } { 25 | set _ENDIAN $ENDIAN 26 | } else { 27 | set _ENDIAN little 28 | } 29 | 30 | # Work-area is a space in RAM used for flash programming 31 | # By default use 16kB 32 | if { [info exists WORKAREASIZE] } { 33 | set _WORKAREASIZE $WORKAREASIZE 34 | } else { 35 | set _WORKAREASIZE 0x4000 36 | } 37 | 38 | # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz 39 | adapter_khz 1000 40 | 41 | adapter_nsrst_delay 100 42 | jtag_ntrst_delay 100 43 | 44 | #jtag scan chain 45 | if { [info exists CPUTAPID] } { 46 | set _CPUTAPID $CPUTAPID 47 | } else { 48 | # See STM Document RM0008 49 | # Section 26.6.3 50 | set _CPUTAPID 0x3ba00477 51 | } 52 | jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID 53 | 54 | if { [info exists BSTAPID] } { 55 | # FIXME this never gets used to override defaults... 56 | set _BSTAPID $BSTAPID 57 | } else { 58 | # See STM Document RM0008 59 | # Section 29.6.2 60 | # Low density devices, Rev A 61 | set _BSTAPID1 0x06412041 62 | # Medium density devices, Rev A 63 | set _BSTAPID2 0x06410041 64 | # Medium density devices, Rev B and Rev Z 65 | set _BSTAPID3 0x16410041 66 | set _BSTAPID4 0x06420041 67 | # High density devices, Rev A 68 | set _BSTAPID5 0x06414041 69 | # Connectivity line devices, Rev A and Rev Z 70 | set _BSTAPID6 0x06418041 71 | # XL line devices, Rev A 72 | set _BSTAPID7 0x06430041 73 | # VL line devices, Rev A and Z In medium-density and high-density value line devices 74 | set _BSTAPID8 0x06420041 75 | # VL line devices, Rev A 76 | set _BSTAPID9 0x06428041 77 | 78 | } 79 | jtag newtap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ 80 | -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ 81 | -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \ 82 | -expected-id $_BSTAPID6 -expected-id $_BSTAPID7 \ 83 | -expected-id $_BSTAPID8 -expected-id $_BSTAPID9 84 | 85 | set _TARGETNAME $_CHIPNAME.cpu 86 | target create $_TARGETNAME cortex_m3 -endian $_ENDIAN -chain-position $_TARGETNAME 87 | 88 | $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 89 | 90 | # flash size will be probed 91 | set _FLASHNAME $_CHIPNAME.flash 92 | flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME 93 | 94 | # if srst is not fitted use SYSRESETREQ to 95 | # perform a soft reset 96 | cortex_m3 reset_config sysresetreq 97 | reset_config srst_only 98 | 99 | proc program_device () { 100 | reset halt 101 | wait_halt 102 | 103 | flash probe 0 104 | stm32f1x mass_erase 0 105 | sleep 10 106 | 107 | flash write_bank 0 build/stm32-ft312d-test.bin 0 108 | sleep 10 109 | 110 | reset run 111 | sleep 500 112 | 113 | shutdown 114 | } 115 | 116 | init 117 | jtag_reset 0 1 118 | reset init 119 | program_device () 120 | -------------------------------------------------------------------------------- /stm32-spi-test/openocd.telnet.cfg: -------------------------------------------------------------------------------- 1 | telnet_port 4444 2 | gdb_port 3333 3 | 4 | # 5 | # Olimex ARM-USB-OCD 6 | # 7 | # http://www.olimex.com/dev/arm-usb-ocd.html 8 | # 9 | 10 | interface ft2232 11 | ft2232_device_desc "Olimex OpenOCD JTAG" 12 | ft2232_layout olimex-jtag 13 | ft2232_vid_pid 0x15ba 0x0003 14 | 15 | # script for stm32f1x family 16 | 17 | if { [info exists CHIPNAME] } { 18 | set _CHIPNAME $CHIPNAME 19 | } else { 20 | set _CHIPNAME stm32f1x 21 | } 22 | 23 | if { [info exists ENDIAN] } { 24 | set _ENDIAN $ENDIAN 25 | } else { 26 | set _ENDIAN little 27 | } 28 | 29 | # Work-area is a space in RAM used for flash programming 30 | # By default use 16kB 31 | if { [info exists WORKAREASIZE] } { 32 | set _WORKAREASIZE $WORKAREASIZE 33 | } else { 34 | set _WORKAREASIZE 0x4000 35 | } 36 | 37 | # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz 38 | adapter_khz 1000 39 | 40 | adapter_nsrst_delay 100 41 | jtag_ntrst_delay 100 42 | 43 | #jtag scan chain 44 | if { [info exists CPUTAPID] } { 45 | set _CPUTAPID $CPUTAPID 46 | } else { 47 | # See STM Document RM0008 48 | # Section 26.6.3 49 | set _CPUTAPID 0x3ba00477 50 | } 51 | jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID 52 | 53 | if { [info exists BSTAPID] } { 54 | # FIXME this never gets used to override defaults... 55 | set _BSTAPID $BSTAPID 56 | } else { 57 | # See STM Document RM0008 58 | # Section 29.6.2 59 | # Low density devices, Rev A 60 | set _BSTAPID1 0x06412041 61 | # Medium density devices, Rev A 62 | set _BSTAPID2 0x06410041 63 | # Medium density devices, Rev B and Rev Z 64 | set _BSTAPID3 0x16410041 65 | set _BSTAPID4 0x06420041 66 | # High density devices, Rev A 67 | set _BSTAPID5 0x06414041 68 | # Connectivity line devices, Rev A and Rev Z 69 | set _BSTAPID6 0x06418041 70 | # XL line devices, Rev A 71 | set _BSTAPID7 0x06430041 72 | # VL line devices, Rev A and Z In medium-density and high-density value line devices 73 | set _BSTAPID8 0x06420041 74 | # VL line devices, Rev A 75 | set _BSTAPID9 0x06428041 76 | 77 | } 78 | jtag newtap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ 79 | -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ 80 | -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \ 81 | -expected-id $_BSTAPID6 -expected-id $_BSTAPID7 \ 82 | -expected-id $_BSTAPID8 -expected-id $_BSTAPID9 83 | 84 | set _TARGETNAME $_CHIPNAME.cpu 85 | target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME 86 | 87 | $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 88 | 89 | # flash size will be probed 90 | set _FLASHNAME $_CHIPNAME.flash 91 | flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME 92 | 93 | # if srst is not fitted use SYSRESETREQ to 94 | # perform a soft reset 95 | cortex_m reset_config sysresetreq 96 | 97 | -------------------------------------------------------------------------------- /stm32-spi-test/platform_config.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PLATFORM_CONFIG_H 3 | #define PLATFORM_CONFIG_H 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #define DEBUG_LED_RCC RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO 10 | #define DEBUG_LED_PORT GPIOA 11 | #define DEBUG_LED_PIN GPIO_Pin_0 12 | 13 | #define DEBUG_USART USART1 14 | #define DEBUG_USART_BAUD 57600 15 | #define DEBUG_USART_IRQ USART1_IRQn 16 | #define DEBUG_USART_RCC RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1 17 | #define DEBUG_USART_TX GPIOA 18 | #define DEBUG_USART_TX_PIN GPIO_Pin_9 19 | #define DEBUG_USART_RX GPIOA 20 | #define DEBUG_USART_RX_PIN GPIO_Pin_10 21 | 22 | #define SPIy SPI1 23 | #define SPIy_CLK RCC_APB2Periph_SPI1 24 | #define SPIy_GPIO GPIOA 25 | #define SPIy_GPIO_CLK RCC_APB2Periph_GPIOA 26 | #define SPIy_PIN_SCK GPIO_Pin_5 27 | #define SPIy_PIN_MISO GPIO_Pin_6 28 | #define SPIy_PIN_MOSI GPIO_Pin_7 29 | #define SPIy_PIN_SS GPIO_Pin_4 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* PLATFORM_CONFIG_H */ 36 | 37 | -------------------------------------------------------------------------------- /stm32-spi-test/run-cmake.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | rm -rf build 4 | mkdir -p build 5 | cd build 6 | cmake -DTOOLCHAIN_PREFIX=/opt/arm-linaro-eabi-4.6 -DCMAKE_TOOLCHAIN_FILE=../gcc_stm32.cmake -DCMAKE_INSTALL_PREFIX=/opt/arm-linaro-eabi-4.6/ -DCMAKE_BUILD_TYPE=Release -DSTM32_CHIP_TYPE=LD ../ 7 | -------------------------------------------------------------------------------- /stm32-spi-test/stm32_flash.ld.in: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | ** Linker script for STM32F10x devices 5 | ** 6 | ** Set heap size, stack size and stack location according 7 | ** to application requirements. 8 | ** 9 | ** Set memory bank area and size if external memory is used. 10 | ** 11 | ***************************************************************************** 12 | */ 13 | 14 | /* Entry Point */ 15 | ENTRY(Reset_Handler) 16 | 17 | /* Highest address of the user mode stack */ 18 | _estack = ${STACK_ADDRESS}; /* end of RAM */ 19 | 20 | /* Generate a link error if heap and stack don't fit into RAM */ 21 | _Min_Heap_Size = ${MIN_HEAP_SIZE}; /* required amount of heap */ 22 | _Min_Stack_Size = ${MIN_STACK_SIZE}; /* required amount of stack */ 23 | 24 | /* Specify the memory areas */ 25 | MEMORY 26 | { 27 | FLASH (rx) : ORIGIN = ${FLASH_ORIGIN}, LENGTH = ${FLASH_SIZE} 28 | RAM (xrw) : ORIGIN = ${RAM_ORIGIN}, LENGTH = ${RAM_SIZE} 29 | MEMORY_B1 (rx) : ORIGIN = ${EXT_RAM_ORIGIN}, LENGTH = ${EXT_RAM_SIZE} 30 | } 31 | 32 | /* Define output sections */ 33 | SECTIONS 34 | { 35 | /* The startup code goes first into FLASH */ 36 | .isr_vector : 37 | { 38 | . = ALIGN(4); 39 | KEEP(*(.isr_vector)) /* Startup code */ 40 | . = ALIGN(4); 41 | } >FLASH 42 | 43 | /* The program code and other data goes into FLASH */ 44 | .text : 45 | { 46 | . = ALIGN(4); 47 | *(.text) /* .text sections (code) */ 48 | *(.text*) /* .text* sections (code) */ 49 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 50 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 51 | *(.glue_7) /* glue arm to thumb code */ 52 | *(.glue_7t) /* glue thumb to arm code */ 53 | 54 | KEEP (*(.init)) 55 | KEEP (*(.fini)) 56 | 57 | . = ALIGN(4); 58 | _etext = .; /* define a global symbols at end of code */ 59 | } >FLASH 60 | 61 | 62 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 63 | .ARM : { 64 | __exidx_start = .; 65 | *(.ARM.exidx*) 66 | __exidx_end = .; 67 | } >FLASH 68 | 69 | .ARM.attributes : { *(.ARM.attributes) } > FLASH 70 | 71 | .preinit_array : 72 | { 73 | PROVIDE_HIDDEN (__preinit_array_start = .); 74 | KEEP (*(.preinit_array*)) 75 | PROVIDE_HIDDEN (__preinit_array_end = .); 76 | } >FLASH 77 | .init_array : 78 | { 79 | PROVIDE_HIDDEN (__init_array_start = .); 80 | KEEP (*(SORT(.init_array.*))) 81 | KEEP (*(.init_array*)) 82 | PROVIDE_HIDDEN (__init_array_end = .); 83 | } >FLASH 84 | .fini_array : 85 | { 86 | PROVIDE_HIDDEN (__fini_array_start = .); 87 | KEEP (*(.fini_array*)) 88 | KEEP (*(SORT(.fini_array.*))) 89 | PROVIDE_HIDDEN (__fini_array_end = .); 90 | } >FLASH 91 | 92 | /* used by the startup to initialize data */ 93 | _sidata = .; 94 | 95 | /* Initialized data sections goes into RAM, load LMA copy after code */ 96 | .data : AT ( _sidata ) 97 | { 98 | . = ALIGN(4); 99 | _sdata = .; /* create a global symbol at data start */ 100 | *(.data) /* .data sections */ 101 | *(.data*) /* .data* sections */ 102 | 103 | . = ALIGN(4); 104 | _edata = .; /* define a global symbol at data end */ 105 | } >RAM 106 | 107 | /* Uninitialized data section */ 108 | . = ALIGN(4); 109 | .bss : 110 | { 111 | /* This is used by the startup in order to initialize the .bss secion */ 112 | _sbss = .; /* define a global symbol at bss start */ 113 | __bss_start__ = _sbss; 114 | *(.bss) 115 | *(.bss*) 116 | *(COMMON) 117 | 118 | . = ALIGN(4); 119 | _ebss = .; /* define a global symbol at bss end */ 120 | __bss_end__ = _ebss; 121 | } >RAM 122 | 123 | PROVIDE ( end = _ebss ); 124 | PROVIDE ( _end = _ebss ); 125 | 126 | /* User_heap_stack section, used to check that there is enough RAM left */ 127 | ._user_heap_stack : 128 | { 129 | . = ALIGN(4); 130 | . = . + _Min_Heap_Size; 131 | . = . + _Min_Stack_Size; 132 | . = ALIGN(4); 133 | } >RAM 134 | 135 | /* MEMORY_bank1 section, code must be located here explicitly */ 136 | /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ 137 | .memory_b1_text : 138 | { 139 | *(.mb1text) /* .mb1text sections (code) */ 140 | *(.mb1text*) /* .mb1text* sections (code) */ 141 | *(.mb1rodata) /* read-only data (constants) */ 142 | *(.mb1rodata*) 143 | } >MEMORY_B1 144 | 145 | /* Remove information from the standard libraries */ 146 | /DISCARD/ : 147 | { 148 | libc.a ( * ) 149 | libm.a ( * ) 150 | libgcc.a ( * ) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /stm32-spi-test/stm32f10x_conf.h: -------------------------------------------------------------------------------- 1 | #ifndef __STM32F10x_CONF_H 2 | #define __STM32F10x_CONF_H 3 | 4 | #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) 5 | 6 | /* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */ 7 | 8 | // #include "stm32f10x_adc.h" 9 | // #include "stm32f10x_bkp.h" 10 | // #include "stm32f10x_can.h" 11 | // #include "stm32f10x_cec.h" 12 | // #include "stm32f10x_crc.h" 13 | // #include "stm32f10x_dac.h" 14 | // #include "stm32f10x_dbgmcu.h" 15 | // #include "stm32f10x_dma.h" 16 | // #include 17 | // #include "stm32f10x_flash.h" 18 | // #include "stm32f10x_fsmc.h" 19 | #include 20 | // #include "stm32f10x_i2c.h" 21 | // #include "stm32f10x_iwdg.h" 22 | // #include "stm32f10x_pwr.h" 23 | #include 24 | // #include "stm32f10x_rtc.h" 25 | // #include "stm32f10x_sdio.h" 26 | // #include "stm32f10x_spi.h" 27 | // #include 28 | // #include "stm32f10x_usart.h" 29 | // #include "stm32f10x_wwdg.h" 30 | // #include 31 | 32 | #endif -------------------------------------------------------------------------------- /stm32-spi-test/system_stm32f10x.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.c 4 | * @author MCD Application Team 5 | * @version V4.0.0 6 | * @date 21-January-2013 7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File. 8 | * 9 | * 1. This file provides two functions and one global variable to be called from 10 | * user application: 11 | * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier 12 | * factors, AHB/APBx prescalers and Flash settings). 13 | * This function is called at startup just after reset and 14 | * before branch to main program. This call is made inside 15 | * the "startup_stm32f10x_xx.s" file. 16 | * 17 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used 18 | * by the user application to setup the SysTick 19 | * timer or configure other parameters. 20 | * 21 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must 22 | * be called whenever the core clock is changed 23 | * during program execution. 24 | * 25 | * 2. After each device reset the HSI (8 MHz) is used as system clock source. 26 | * Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file, to 27 | * configure the system clock before to branch to main program. 28 | * 29 | * 3. If the system clock source selected by user fails to startup, the SystemInit() 30 | * function will do nothing and HSI still used as system clock source. User can 31 | * add some code to deal with this issue inside the SetSysClock() function. 32 | * 33 | * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on 34 | * the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file. 35 | * When HSE is used as system clock source, directly or through PLL, and you 36 | * are using different crystal you have to adapt the HSE value to your own 37 | * configuration. 38 | * 39 | ****************************************************************************** 40 | * @attention 41 | * 42 | *

© COPYRIGHT 2013 STMicroelectronics

43 | * 44 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); 45 | * You may not use this file except in compliance with the License. 46 | * You may obtain a copy of the License at: 47 | * 48 | * http://www.st.com/software_license_agreement_liberty_v2 49 | * 50 | * Unless required by applicable law or agreed to in writing, software 51 | * distributed under the License is distributed on an "AS IS" BASIS, 52 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 53 | * See the License for the specific language governing permissions and 54 | * limitations under the License. 55 | * 56 | ****************************************************************************** 57 | */ 58 | 59 | /** @addtogroup CMSIS 60 | * @{ 61 | */ 62 | 63 | /** @addtogroup stm32f10x_system 64 | * @{ 65 | */ 66 | 67 | /** @addtogroup STM32F10x_System_Private_Includes 68 | * @{ 69 | */ 70 | 71 | #include "stm32f10x.h" 72 | 73 | /** 74 | * @} 75 | */ 76 | 77 | /** @addtogroup STM32F10x_System_Private_TypesDefinitions 78 | * @{ 79 | */ 80 | 81 | /** 82 | * @} 83 | */ 84 | 85 | /** @addtogroup STM32F10x_System_Private_Defines 86 | * @{ 87 | */ 88 | 89 | /*!< Uncomment the line corresponding to the desired System clock (SYSCLK) 90 | frequency (after reset the HSI is used as SYSCLK source) 91 | 92 | IMPORTANT NOTE: 93 | ============== 94 | 1. After each device reset the HSI is used as System clock source. 95 | 96 | 2. Please make sure that the selected System clock doesn't exceed your device's 97 | maximum frequency. 98 | 99 | 3. If none of the define below is enabled, the HSI is used as System clock 100 | source. 101 | 102 | 4. The System clock configuration functions provided within this file assume that: 103 | - For Low, Medium and High density Value line devices an external 8MHz 104 | crystal is used to drive the System clock. 105 | - For Low, Medium and High density devices an external 8MHz crystal is 106 | used to drive the System clock. 107 | - For Connectivity line devices an external 25MHz crystal is used to drive 108 | the System clock. 109 | If you are using different crystal you have to adapt those functions accordingly. 110 | */ 111 | 112 | #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 113 | /* #define SYSCLK_FREQ_HSE HSE_VALUE */ 114 | #define SYSCLK_FREQ_24MHz 24000000 115 | #else 116 | /* #define SYSCLK_FREQ_HSE HSE_VALUE */ 117 | /* #define SYSCLK_FREQ_24MHz 24000000 */ 118 | /* #define SYSCLK_FREQ_36MHz 36000000 */ 119 | /* #define SYSCLK_FREQ_48MHz 48000000 */ 120 | /* #define SYSCLK_FREQ_56MHz 56000000 */ 121 | #define SYSCLK_FREQ_72MHz 72000000 122 | #endif 123 | 124 | /*!< Uncomment the following line if you need to use external SRAM mounted 125 | on STM3210E-EVAL board (STM32 High density and XL-density devices) or on 126 | STM32100E-EVAL board (STM32 High-density value line devices) as data memory */ 127 | #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) 128 | /* #define DATA_IN_ExtSRAM */ 129 | #endif 130 | 131 | /*!< Uncomment the following line if you need to relocate your vector Table in 132 | Internal SRAM. */ 133 | /* #define VECT_TAB_SRAM */ 134 | #define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field. 135 | This value must be a multiple of 0x200. */ 136 | 137 | 138 | /** 139 | * @} 140 | */ 141 | 142 | /** @addtogroup STM32F10x_System_Private_Macros 143 | * @{ 144 | */ 145 | 146 | /** 147 | * @} 148 | */ 149 | 150 | /** @addtogroup STM32F10x_System_Private_Variables 151 | * @{ 152 | */ 153 | 154 | /******************************************************************************* 155 | * Clock Definitions 156 | *******************************************************************************/ 157 | #ifdef SYSCLK_FREQ_HSE 158 | uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */ 159 | #elif defined SYSCLK_FREQ_24MHz 160 | uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */ 161 | #elif defined SYSCLK_FREQ_36MHz 162 | uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */ 163 | #elif defined SYSCLK_FREQ_48MHz 164 | uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */ 165 | #elif defined SYSCLK_FREQ_56MHz 166 | uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */ 167 | #elif defined SYSCLK_FREQ_72MHz 168 | uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */ 169 | #else /*!< HSI Selected as System Clock source */ 170 | uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) */ 171 | #endif 172 | 173 | __I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; 174 | /** 175 | * @} 176 | */ 177 | 178 | /** @addtogroup STM32F10x_System_Private_FunctionPrototypes 179 | * @{ 180 | */ 181 | 182 | static void SetSysClock(void); 183 | 184 | #ifdef SYSCLK_FREQ_HSE 185 | static void SetSysClockToHSE(void); 186 | #elif defined SYSCLK_FREQ_24MHz 187 | static void SetSysClockTo24(void); 188 | #elif defined SYSCLK_FREQ_36MHz 189 | static void SetSysClockTo36(void); 190 | #elif defined SYSCLK_FREQ_48MHz 191 | static void SetSysClockTo48(void); 192 | #elif defined SYSCLK_FREQ_56MHz 193 | static void SetSysClockTo56(void); 194 | #elif defined SYSCLK_FREQ_72MHz 195 | static void SetSysClockTo72(void); 196 | #endif 197 | 198 | #ifdef DATA_IN_ExtSRAM 199 | static void SystemInit_ExtMemCtl(void); 200 | #endif /* DATA_IN_ExtSRAM */ 201 | 202 | /** 203 | * @} 204 | */ 205 | 206 | /** @addtogroup STM32F10x_System_Private_Functions 207 | * @{ 208 | */ 209 | 210 | /** 211 | * @brief Setup the microcontroller system 212 | * Initialize the Embedded Flash Interface, the PLL and update the 213 | * SystemCoreClock variable. 214 | * @note This function should be used only after reset. 215 | * @param None 216 | * @retval None 217 | */ 218 | void SystemInit (void) 219 | { 220 | /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ 221 | /* Set HSION bit */ 222 | RCC->CR |= (uint32_t)0x00000001; 223 | 224 | /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ 225 | 226 | RCC->CFGR &= (uint32_t)0xF8FF0000; 227 | 228 | /* Reset HSEON, CSSON and PLLON bits */ 229 | RCC->CR &= (uint32_t)0xFEF6FFFF; 230 | 231 | /* Reset HSEBYP bit */ 232 | RCC->CR &= (uint32_t)0xFFFBFFFF; 233 | 234 | /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ 235 | RCC->CFGR &= (uint32_t)0xFF80FFFF; 236 | 237 | #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 238 | /* Disable all interrupts and clear pending bits */ 239 | RCC->CIR = 0x009F0000; 240 | 241 | /* Reset CFGR2 register */ 242 | RCC->CFGR2 = 0x00000000; 243 | #else 244 | /* Disable all interrupts and clear pending bits */ 245 | RCC->CIR = 0x009F0000; 246 | #endif /* STM32F10X_XX */ 247 | 248 | #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) 249 | #ifdef DATA_IN_ExtSRAM 250 | SystemInit_ExtMemCtl(); 251 | #endif /* DATA_IN_ExtSRAM */ 252 | #endif 253 | 254 | /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ 255 | /* Configure the Flash Latency cycles and enable prefetch buffer */ 256 | SetSysClock(); 257 | 258 | #ifdef VECT_TAB_SRAM 259 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ 260 | #else 261 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ 262 | #endif 263 | } 264 | 265 | /** 266 | * @brief Update SystemCoreClock variable according to Clock Register Values. 267 | * The SystemCoreClock variable contains the core clock (HCLK), it can 268 | * be used by the user application to setup the SysTick timer or configure 269 | * other parameters. 270 | * 271 | * @note Each time the core clock (HCLK) changes, this function must be called 272 | * to update SystemCoreClock variable value. Otherwise, any configuration 273 | * based on this variable will be incorrect. 274 | * 275 | * @note - The system frequency computed by this function is not the real 276 | * frequency in the chip. It is calculated based on the predefined 277 | * constant and the selected clock source: 278 | * 279 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) 280 | * 281 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) 282 | * 283 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 284 | * or HSI_VALUE(*) multiplied by the PLL factors. 285 | * 286 | * (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value 287 | * 8 MHz) but the real value may vary depending on the variations 288 | * in voltage and temperature. 289 | * 290 | * (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value 291 | * 8 MHz or 25 MHz, depending on the product used), user has to ensure 292 | * that HSE_VALUE is same as the real frequency of the crystal used. 293 | * Otherwise, this function may have wrong result. 294 | * 295 | * - The result of this function could be not correct when using fractional 296 | * value for HSE crystal. 297 | * @param None 298 | * @retval None 299 | */ 300 | void SystemCoreClockUpdate (void) 301 | { 302 | uint32_t tmp = 0, pllmull = 0, pllsource = 0; 303 | 304 | #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 305 | uint32_t prediv1factor = 0; 306 | #endif /* STM32F10X_LD_VL or STM32F10X_MD_VL or STM32F10X_HD_VL */ 307 | 308 | /* Get SYSCLK source -------------------------------------------------------*/ 309 | tmp = RCC->CFGR & RCC_CFGR_SWS; 310 | 311 | switch (tmp) 312 | { 313 | case 0x00: /* HSI used as system clock */ 314 | SystemCoreClock = HSI_VALUE; 315 | break; 316 | case 0x04: /* HSE used as system clock */ 317 | SystemCoreClock = HSE_VALUE; 318 | break; 319 | case 0x08: /* PLL used as system clock */ 320 | 321 | /* Get PLL clock source and multiplication factor ----------------------*/ 322 | pllmull = RCC->CFGR & RCC_CFGR_PLLMULL; 323 | pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; 324 | 325 | pllmull = ( pllmull >> 18) + 2; 326 | 327 | if (pllsource == 0x00) 328 | { 329 | /* HSI oscillator clock divided by 2 selected as PLL clock entry */ 330 | SystemCoreClock = (HSI_VALUE >> 1) * pllmull; 331 | } 332 | else 333 | { 334 | #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) 335 | prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1; 336 | /* HSE oscillator clock selected as PREDIV1 clock entry */ 337 | SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 338 | #else 339 | /* HSE selected as PLL clock entry */ 340 | if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET) 341 | {/* HSE oscillator clock divided by 2 */ 342 | SystemCoreClock = (HSE_VALUE >> 1) * pllmull; 343 | } 344 | else 345 | { 346 | SystemCoreClock = HSE_VALUE * pllmull; 347 | } 348 | #endif 349 | } 350 | 351 | break; 352 | 353 | default: 354 | SystemCoreClock = HSI_VALUE; 355 | break; 356 | } 357 | 358 | /* Compute HCLK clock frequency ----------------*/ 359 | /* Get HCLK prescaler */ 360 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; 361 | /* HCLK clock frequency */ 362 | SystemCoreClock >>= tmp; 363 | } 364 | 365 | /** 366 | * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. 367 | * @param None 368 | * @retval None 369 | */ 370 | static void SetSysClock(void) 371 | { 372 | #ifdef SYSCLK_FREQ_HSE 373 | SetSysClockToHSE(); 374 | #elif defined SYSCLK_FREQ_24MHz 375 | SetSysClockTo24(); 376 | #elif defined SYSCLK_FREQ_36MHz 377 | SetSysClockTo36(); 378 | #elif defined SYSCLK_FREQ_48MHz 379 | SetSysClockTo48(); 380 | #elif defined SYSCLK_FREQ_56MHz 381 | SetSysClockTo56(); 382 | #elif defined SYSCLK_FREQ_72MHz 383 | SetSysClockTo72(); 384 | #endif 385 | 386 | /* If none of the define above is enabled, the HSI is used as System clock 387 | source (default after reset) */ 388 | } 389 | 390 | /** 391 | * @brief Setup the external memory controller. Called in startup_stm32f10x.s 392 | * before jump to __main 393 | * @param None 394 | * @retval None 395 | */ 396 | #ifdef DATA_IN_ExtSRAM 397 | /** 398 | * @brief Setup the external memory controller. 399 | * Called in startup_stm32f10x_xx.s/.c before jump to main. 400 | * This function configures the external SRAM mounted on STM3210E-EVAL 401 | * board (STM32 High density devices). This SRAM will be used as program 402 | * data memory (including heap and stack). 403 | * @param None 404 | * @retval None 405 | */ 406 | void SystemInit_ExtMemCtl(void) 407 | { 408 | /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 409 | required, then adjust the Register Addresses */ 410 | 411 | /* Enable FSMC clock */ 412 | RCC->AHBENR = 0x00000114; 413 | 414 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */ 415 | RCC->APB2ENR = 0x000001E0; 416 | 417 | /* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/ 418 | /*---------------- SRAM Address lines configuration -------------------------*/ 419 | /*---------------- NOE and NWE configuration --------------------------------*/ 420 | /*---------------- NE3 configuration ----------------------------------------*/ 421 | /*---------------- NBL0, NBL1 configuration ---------------------------------*/ 422 | 423 | GPIOD->CRL = 0x44BB44BB; 424 | GPIOD->CRH = 0xBBBBBBBB; 425 | 426 | GPIOE->CRL = 0xB44444BB; 427 | GPIOE->CRH = 0xBBBBBBBB; 428 | 429 | GPIOF->CRL = 0x44BBBBBB; 430 | GPIOF->CRH = 0xBBBB4444; 431 | 432 | GPIOG->CRL = 0x44BBBBBB; 433 | GPIOG->CRH = 0x44444B44; 434 | 435 | /*---------------- FSMC Configuration ---------------------------------------*/ 436 | /*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/ 437 | 438 | FSMC_Bank1->BTCR[4] = 0x00001011; 439 | FSMC_Bank1->BTCR[5] = 0x00000200; 440 | } 441 | #endif /* DATA_IN_ExtSRAM */ 442 | 443 | #ifdef SYSCLK_FREQ_HSE 444 | /** 445 | * @brief Selects HSE as System clock source and configure HCLK, PCLK2 446 | * and PCLK1 prescalers. 447 | * @note This function should be used only after reset. 448 | * @param None 449 | * @retval None 450 | */ 451 | static void SetSysClockToHSE(void) 452 | { 453 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 454 | 455 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 456 | /* Enable HSE */ 457 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 458 | 459 | /* Wait till HSE is ready and if Time out is reached exit */ 460 | do 461 | { 462 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 463 | StartUpCounter++; 464 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 465 | 466 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 467 | { 468 | HSEStatus = (uint32_t)0x01; 469 | } 470 | else 471 | { 472 | HSEStatus = (uint32_t)0x00; 473 | } 474 | 475 | if (HSEStatus == (uint32_t)0x01) 476 | { 477 | 478 | #if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL 479 | /* Enable Prefetch Buffer */ 480 | FLASH->ACR |= FLASH_ACR_PRFTBE; 481 | 482 | /* Flash 0 wait state */ 483 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 484 | 485 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; 486 | #endif 487 | 488 | /* HCLK = SYSCLK */ 489 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 490 | 491 | /* PCLK2 = HCLK */ 492 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 493 | 494 | /* PCLK1 = HCLK */ 495 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 496 | 497 | /* Select HSE as system clock source */ 498 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 499 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE; 500 | 501 | /* Wait till HSE is used as system clock source */ 502 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04) 503 | { 504 | } 505 | } 506 | else 507 | { /* If HSE fails to start-up, the application will have wrong clock 508 | configuration. User can add here some code to deal with this error */ 509 | } 510 | } 511 | #elif defined SYSCLK_FREQ_24MHz 512 | /** 513 | * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 514 | * and PCLK1 prescalers. 515 | * @note This function should be used only after reset. 516 | * @param None 517 | * @retval None 518 | */ 519 | static void SetSysClockTo24(void) 520 | { 521 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 522 | 523 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 524 | /* Enable HSE */ 525 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 526 | 527 | /* Wait till HSE is ready and if Time out is reached exit */ 528 | do 529 | { 530 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 531 | StartUpCounter++; 532 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 533 | 534 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 535 | { 536 | HSEStatus = (uint32_t)0x01; 537 | } 538 | else 539 | { 540 | HSEStatus = (uint32_t)0x00; 541 | } 542 | 543 | if (HSEStatus == (uint32_t)0x01) 544 | { 545 | #if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL 546 | /* Enable Prefetch Buffer */ 547 | FLASH->ACR |= FLASH_ACR_PRFTBE; 548 | 549 | /* Flash 0 wait state */ 550 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 551 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; 552 | #endif 553 | 554 | /* HCLK = SYSCLK */ 555 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 556 | 557 | /* PCLK2 = HCLK */ 558 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 559 | 560 | /* PCLK1 = HCLK */ 561 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 562 | 563 | #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) 564 | /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ 565 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 566 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6); 567 | #else 568 | /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ 569 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 570 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6); 571 | #endif /* STM32F10X_XX */ 572 | 573 | /* Enable PLL */ 574 | RCC->CR |= RCC_CR_PLLON; 575 | 576 | /* Wait till PLL is ready */ 577 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 578 | { 579 | } 580 | 581 | /* Select PLL as system clock source */ 582 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 583 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 584 | 585 | /* Wait till PLL is used as system clock source */ 586 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 587 | { 588 | } 589 | } 590 | else 591 | { /* If HSE fails to start-up, the application will have wrong clock 592 | configuration. User can add here some code to deal with this error */ 593 | } 594 | } 595 | #elif defined SYSCLK_FREQ_36MHz 596 | /** 597 | * @brief Sets System clock frequency to 36MHz and configure HCLK, PCLK2 598 | * and PCLK1 prescalers. 599 | * @note This function should be used only after reset. 600 | * @param None 601 | * @retval None 602 | */ 603 | static void SetSysClockTo36(void) 604 | { 605 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 606 | 607 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 608 | /* Enable HSE */ 609 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 610 | 611 | /* Wait till HSE is ready and if Time out is reached exit */ 612 | do 613 | { 614 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 615 | StartUpCounter++; 616 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 617 | 618 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 619 | { 620 | HSEStatus = (uint32_t)0x01; 621 | } 622 | else 623 | { 624 | HSEStatus = (uint32_t)0x00; 625 | } 626 | 627 | if (HSEStatus == (uint32_t)0x01) 628 | { 629 | /* Enable Prefetch Buffer */ 630 | FLASH->ACR |= FLASH_ACR_PRFTBE; 631 | 632 | /* Flash 1 wait state */ 633 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 634 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; 635 | 636 | /* HCLK = SYSCLK */ 637 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 638 | 639 | /* PCLK2 = HCLK */ 640 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 641 | 642 | /* PCLK1 = HCLK */ 643 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; 644 | 645 | /* PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 MHz */ 646 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 647 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9); 648 | 649 | /* Enable PLL */ 650 | RCC->CR |= RCC_CR_PLLON; 651 | 652 | /* Wait till PLL is ready */ 653 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 654 | { 655 | } 656 | 657 | /* Select PLL as system clock source */ 658 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 659 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 660 | 661 | /* Wait till PLL is used as system clock source */ 662 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 663 | { 664 | } 665 | } 666 | else 667 | { /* If HSE fails to start-up, the application will have wrong clock 668 | configuration. User can add here some code to deal with this error */ 669 | } 670 | } 671 | #elif defined SYSCLK_FREQ_48MHz 672 | /** 673 | * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 674 | * and PCLK1 prescalers. 675 | * @note This function should be used only after reset. 676 | * @param None 677 | * @retval None 678 | */ 679 | static void SetSysClockTo48(void) 680 | { 681 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 682 | 683 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 684 | /* Enable HSE */ 685 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 686 | 687 | /* Wait till HSE is ready and if Time out is reached exit */ 688 | do 689 | { 690 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 691 | StartUpCounter++; 692 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 693 | 694 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 695 | { 696 | HSEStatus = (uint32_t)0x01; 697 | } 698 | else 699 | { 700 | HSEStatus = (uint32_t)0x00; 701 | } 702 | 703 | if (HSEStatus == (uint32_t)0x01) 704 | { 705 | /* Enable Prefetch Buffer */ 706 | FLASH->ACR |= FLASH_ACR_PRFTBE; 707 | 708 | /* Flash 1 wait state */ 709 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 710 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1; 711 | 712 | /* HCLK = SYSCLK */ 713 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 714 | 715 | /* PCLK2 = HCLK */ 716 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 717 | 718 | /* PCLK1 = HCLK */ 719 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 720 | 721 | /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */ 722 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 723 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6); 724 | 725 | /* Enable PLL */ 726 | RCC->CR |= RCC_CR_PLLON; 727 | 728 | /* Wait till PLL is ready */ 729 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 730 | { 731 | } 732 | 733 | /* Select PLL as system clock source */ 734 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 735 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 736 | 737 | /* Wait till PLL is used as system clock source */ 738 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 739 | { 740 | } 741 | } 742 | else 743 | { /* If HSE fails to start-up, the application will have wrong clock 744 | configuration. User can add here some code to deal with this error */ 745 | } 746 | } 747 | 748 | #elif defined SYSCLK_FREQ_56MHz 749 | /** 750 | * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 751 | * and PCLK1 prescalers. 752 | * @note This function should be used only after reset. 753 | * @param None 754 | * @retval None 755 | */ 756 | static void SetSysClockTo56(void) 757 | { 758 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 759 | 760 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 761 | /* Enable HSE */ 762 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 763 | 764 | /* Wait till HSE is ready and if Time out is reached exit */ 765 | do 766 | { 767 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 768 | StartUpCounter++; 769 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 770 | 771 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 772 | { 773 | HSEStatus = (uint32_t)0x01; 774 | } 775 | else 776 | { 777 | HSEStatus = (uint32_t)0x00; 778 | } 779 | 780 | if (HSEStatus == (uint32_t)0x01) 781 | { 782 | /* Enable Prefetch Buffer */ 783 | FLASH->ACR |= FLASH_ACR_PRFTBE; 784 | 785 | /* Flash 2 wait state */ 786 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 787 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 788 | 789 | /* HCLK = SYSCLK */ 790 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 791 | 792 | /* PCLK2 = HCLK */ 793 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 794 | 795 | /* PCLK1 = HCLK */ 796 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 797 | 798 | 799 | /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */ 800 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); 801 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL7); 802 | 803 | /* Enable PLL */ 804 | RCC->CR |= RCC_CR_PLLON; 805 | 806 | /* Wait till PLL is ready */ 807 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 808 | { 809 | } 810 | 811 | /* Select PLL as system clock source */ 812 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 813 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 814 | 815 | /* Wait till PLL is used as system clock source */ 816 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 817 | { 818 | } 819 | } 820 | else 821 | { /* If HSE fails to start-up, the application will have wrong clock 822 | configuration. User can add here some code to deal with this error */ 823 | } 824 | } 825 | 826 | #elif defined SYSCLK_FREQ_72MHz 827 | /** 828 | * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 829 | * and PCLK1 prescalers. 830 | * @note This function should be used only after reset. 831 | * @param None 832 | * @retval None 833 | */ 834 | static void SetSysClockTo72(void) 835 | { 836 | __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 837 | 838 | /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ 839 | /* Enable HSE */ 840 | RCC->CR |= ((uint32_t)RCC_CR_HSEON); 841 | 842 | /* Wait till HSE is ready and if Time out is reached exit */ 843 | do 844 | { 845 | HSEStatus = RCC->CR & RCC_CR_HSERDY; 846 | StartUpCounter++; 847 | } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); 848 | 849 | if ((RCC->CR & RCC_CR_HSERDY) != RESET) 850 | { 851 | HSEStatus = (uint32_t)0x01; 852 | } 853 | else 854 | { 855 | HSEStatus = (uint32_t)0x00; 856 | } 857 | 858 | if (HSEStatus == (uint32_t)0x01) 859 | { 860 | /* Enable Prefetch Buffer */ 861 | FLASH->ACR |= FLASH_ACR_PRFTBE; 862 | 863 | /* Flash 2 wait state */ 864 | FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); 865 | FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; 866 | 867 | 868 | /* HCLK = SYSCLK */ 869 | RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; 870 | 871 | /* PCLK2 = HCLK */ 872 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; 873 | 874 | /* PCLK1 = HCLK */ 875 | RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; 876 | 877 | /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ 878 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | 879 | RCC_CFGR_PLLMULL)); 880 | RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9); 881 | 882 | /* Enable PLL */ 883 | RCC->CR |= RCC_CR_PLLON; 884 | 885 | /* Wait till PLL is ready */ 886 | while((RCC->CR & RCC_CR_PLLRDY) == 0) 887 | { 888 | } 889 | 890 | /* Select PLL as system clock source */ 891 | RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 892 | RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 893 | 894 | /* Wait till PLL is used as system clock source */ 895 | while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) 896 | { 897 | } 898 | } 899 | else 900 | { /* If HSE fails to start-up, the application will have wrong clock 901 | configuration. User can add here some code to deal with this error */ 902 | } 903 | } 904 | #endif 905 | 906 | /** 907 | * @} 908 | */ 909 | 910 | /** 911 | * @} 912 | */ 913 | 914 | /** 915 | * @} 916 | */ 917 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 918 | -------------------------------------------------------------------------------- /stm32-spi-test/time.c: -------------------------------------------------------------------------------- 1 | 2 | #include "time.h" 3 | #include 4 | #include 5 | 6 | volatile uint32_t counter_ms = 0; 7 | 8 | void time_SysTick_Handler() { 9 | counter_ms++; 10 | } 11 | 12 | void time_setup() { 13 | /* 14 | * Setup SysTick Timer for 1 msec interrupts. 15 | * ------------------------------------------ 16 | * 1. The SysTick_Config() function is a CMSIS function which configure: 17 | * - The SysTick Reload register with value passed as function parameter. 18 | * - Configure the SysTick IRQ priority to the lowest value (0x0F). 19 | * - Reset the SysTick Counter register. 20 | * - Configure the SysTick Counter clock source to be Core Clock Source (HCLK). 21 | * - Enable the SysTick Interrupt. 22 | * - Start the SysTick Counter. 23 | * 24 | * 2. You can change the SysTick Clock source to be HCLK_Div8 by calling the 25 | * SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8) just after the 26 | * SysTick_Config() function call. The SysTick_CLKSourceConfig() is defined 27 | * inside the misc.c file. 28 | * 29 | * 3. You can change the SysTick IRQ priority by calling the 30 | * NVIC_SetPriority(SysTick_IRQn,...) just after the SysTick_Config() function 31 | * call. The NVIC_SetPriority() is defined inside the core_cm3.h file. 32 | * 33 | * 4. To adjust the SysTick time base, use the following formula: 34 | * 35 | * Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s) 36 | * 37 | * - Reload Value is the parameter to be passed for SysTick_Config() function 38 | * - Reload Value should not exceed 0xFFFFFF 39 | */ 40 | if (SysTick_Config(SystemCoreClock / 1000)) { 41 | /* Capture error */ 42 | while (1); 43 | } 44 | } 45 | 46 | volatile uint32_t time_ms() { 47 | return counter_ms; 48 | } 49 | -------------------------------------------------------------------------------- /stm32-spi-test/time.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_H 2 | #define TIME_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | struct tm { 11 | int tm_sec; 12 | int tm_min; 13 | int tm_hour; 14 | int tm_mday; 15 | int tm_mon; 16 | int tm_year; 17 | int tm_wday; 18 | int tm_yday; 19 | int tm_isdst; 20 | }; 21 | typedef long time_t; 22 | 23 | void time_setup(); 24 | volatile uint32_t time_ms(); 25 | void time_SysTick_Handler(); 26 | 27 | struct tm * gmtime(register const time_t *timer); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* TIME_H */ 34 | 35 | -------------------------------------------------------------------------------- /stm32-spi-test/upload.sh: -------------------------------------------------------------------------------- 1 | 2 | sudo /opt/arm-linaro-eabi-4.6/bin/openocd -f openocd.cfg 3 | 4 | --------------------------------------------------------------------------------