aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-01-02 20:53:42 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2016-01-02 20:53:42 +0100
commit9129af503c8211d713c8a160a3b6f3f86b328639 (patch)
tree3cd9ff26f4d323fc553b2a99d56be9b81a57a4c4 /apps
parentaae314fead54dab7b258f3a6c7ac1615833f9987 (diff)
downloadstm32f103-playground-9129af503c8211d713c8a160a3b6f3f86b328639.tar.gz
stm32f103-playground-9129af503c8211d713c8a160a3b6f3f86b328639.tar.bz2
stm32f103-playground-9129af503c8211d713c8a160a3b6f3f86b328639.tar.xz
stm32f103-playground-9129af503c8211d713c8a160a3b6f3f86b328639.zip
o Adding a utility to dump segment sizes from the generated ELF files.
o Adding os2 with support for critical sections. More to come. o Adding dma1 to test DMA + SPI.
Diffstat (limited to 'apps')
-rw-r--r--apps/CMakeLists.txt1
-rw-r--r--apps/dma1/CMakeLists.txt19
-rw-r--r--apps/dma1/dma1.cpp207
3 files changed, 227 insertions, 0 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
new file mode 100644
index 0000000..57fb795
--- /dev/null
+++ b/apps/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(dma1)
diff --git a/apps/dma1/CMakeLists.txt b/apps/dma1/CMakeLists.txt
new file mode 100644
index 0000000..689e437
--- /dev/null
+++ b/apps/dma1/CMakeLists.txt
@@ -0,0 +1,19 @@
+add_executable(dma1.elf dma1.cpp
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/misc.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rcc.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_spi.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_dma.c
+ $<TARGET_OBJECTS:playground>
+ )
+
+target_include_directories(dma1.elf PUBLIC
+ $<TARGET_PROPERTY:playground,INTERFACE_INCLUDE_DIRECTORIES>
+ )
+target_compile_definitions(dma1.elf PUBLIC ${STM32F10X_STDPERIPH_DEFINES})
+target_link_libraries(dma1.elf tinyprintf)
+
+set_target_properties(dma1.elf PROPERTIES LINK_FLAGS "-nostartfiles -T${CMAKE_SOURCE_DIR}/cmake/stm32.ld")
+add_extra_commands(dma1.elf)
diff --git a/apps/dma1/dma1.cpp b/apps/dma1/dma1.cpp
new file mode 100644
index 0000000..4179c65
--- /dev/null
+++ b/apps/dma1/dma1.cpp
@@ -0,0 +1,207 @@
+#include <stdint.h>
+#include <stm32f10x.h>
+#include <stm32f10x_rcc.h>
+#include <stm32f10x_gpio.h>
+#include <stm32f10x_spi.h>
+#include <stm32f10x_dma.h>
+#include <misc.h>
+
+#include "debug.h"
+#include "tinyprintf.h"
+#include "playground.h"
+
+extern "C"
+__attribute__((naked, used))
+void HardFault_Handler_C(uint32_t *hardfault_args) {
+ dbg_printf("r0 = 0x%08lx (%lu)\n", hardfault_args[0], hardfault_args[0]);
+ dbg_printf("r1 = 0x%08lx (%lu)\n", hardfault_args[1], hardfault_args[1]);
+ dbg_printf("r2 = 0x%08lx (%lu)\n", hardfault_args[2], hardfault_args[2]);
+ dbg_printf("r3 = 0x%08lx (%lu)\n", hardfault_args[3], hardfault_args[3]);
+ dbg_printf("r12 = 0x%08lx (%lu)\n", hardfault_args[4], hardfault_args[4]);
+ dbg_printf("lr = 0x%08lx (%lu)\n", hardfault_args[5], hardfault_args[5]);
+ dbg_printf("pc = 0x%08lx (%lu)\n", hardfault_args[6], hardfault_args[6]);
+ dbg_printf("psr = 0x%08lx (%lu)\n", hardfault_args[7], hardfault_args[7]);
+ dbg_printf("\n");
+
+ halt();
+}
+
+volatile bool run = true;
+
+void manual_spi_write(char &c);
+
+void dma_spi_write();
+
+volatile bool manual = false;
+volatile bool dma_busy;
+
+static uint8_t dma_buffer[256];
+
+/*
+ * When we get there the stack pointer is set
+ */
+int main() {
+ SystemInit();
+
+ init_printf(nullptr, dbg_putc);
+
+ dbg_printf("DMA with SPI sample\n");
+
+ for (uint16_t i = 0; i < SizeOfArray(dma_buffer); i++) {
+ dma_buffer[i] = uint8_t(i);
+ }
+
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
+
+ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
+ NVIC_InitTypeDef NVIC_InitStruct = {
+ NVIC_IRQChannel: DMA1_Channel3_IRQn,
+ NVIC_IRQChannelPreemptionPriority: 0,
+ NVIC_IRQChannelSubPriority: 0,
+ NVIC_IRQChannelCmd: ENABLE,
+ };
+ NVIC_Init(&NVIC_InitStruct);
+ NVIC_EnableIRQ(DMA1_Channel3_IRQn);
+
+
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO
+ | RCC_APB2Periph_SPI1
+ | RCC_APB2Periph_GPIOA
+ | RCC_APB2Periph_GPIOB
+ | RCC_APB2Periph_GPIOC,
+ ENABLE);
+
+ /* ***************************************** */
+
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
+
+ GPIO_ResetBits(GPIOB, GPIO_Pin_5);
+ GPIO_InitTypeDef gpioInit;
+ GPIO_StructInit(&gpioInit);
+ gpioInit.GPIO_Pin = GPIO_Pin_5;
+ gpioInit.GPIO_Mode = GPIO_Mode_Out_PP;
+ gpioInit.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_Init(GPIOB, &gpioInit);
+
+ // ----------------------------------------------------
+ // SPI Configuration
+ // Configure SPI MOSI to be on pin PA7, SCK on PA5 and NSS on PA15
+
+ SPI_InitTypeDef spiInit;
+ SPI_StructInit(&spiInit);
+ spiInit.SPI_Direction = SPI_Direction_1Line_Tx;
+ spiInit.SPI_Mode = SPI_Mode_Master;
+ spiInit.SPI_DataSize = SPI_DataSize_8b;
+ spiInit.SPI_CPOL = SPI_CPOL_Low;
+ spiInit.SPI_CPHA = SPI_CPHA_1Edge;
+ spiInit.SPI_NSS = SPI_NSS_Soft;
+ spiInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
+ spiInit.SPI_FirstBit = SPI_FirstBit_MSB;
+ SPI_I2S_DeInit(SPI1);
+ SPI_Init(SPI1, &spiInit);
+ SPI_Cmd(SPI1, ENABLE);
+ SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
+
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);
+ GPIO_StructInit(&gpioInit);
+ gpioInit.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_15;
+ gpioInit.GPIO_Mode = GPIO_Mode_AF_PP;
+ gpioInit.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_Init(GPIOA, &gpioInit);
+
+ if (manual) {
+ char c = 'a';
+ while (run) {
+ manual_spi_write(c);
+ }
+ } else {
+ while (run) {
+ dma_spi_write();
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Test code to ensure that the SPI part is configured correctly
+ */
+void manual_spi_write(char &c) {
+ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
+
+ GPIO_SetBits(GPIOB, GPIO_Pin_5);
+ SPI_I2S_SendData(SPI1, (uint16_t) c);
+
+ if (c == 'Z') {
+ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
+
+ GPIO_ResetBits(GPIOB, GPIO_Pin_5);
+ for (int count = 100; count > 0; count--) {
+ __NOP();
+ }
+ GPIO_SetBits(GPIOB, GPIO_Pin_5);
+
+ c = 'a';
+ } else if (c == 'z') {
+ c = '0';
+ } else if (c == '9') {
+ c = '\n';
+ } else if (c == '\n') {
+ c = 'A';
+ } else {
+ c++;
+ }
+}
+
+void dma_spi_write() {
+ dma_busy = true;
+
+ DMA_InitTypeDef dmaInit;
+ DMA_StructInit(&dmaInit);
+ dmaInit.DMA_M2M = DMA_M2M_Disable;
+ dmaInit.DMA_Mode = DMA_Mode_Normal;
+ dmaInit.DMA_Priority = DMA_Priority_Low;
+ dmaInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+ dmaInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+ dmaInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
+ dmaInit.DMA_MemoryInc = DMA_MemoryInc_Enable;
+ dmaInit.DMA_DIR = DMA_DIR_PeripheralDST;
+ dmaInit.DMA_BufferSize = SizeOfArray(dma_buffer);
+ dmaInit.DMA_PeripheralBaseAddr = reinterpret_cast<uint32_t>(&SPI1->DR);
+ dmaInit.DMA_MemoryBaseAddr = reinterpret_cast<uint32_t>(dma_buffer);
+ DMA_DeInit(DMA1_Channel3);
+ DMA_Init(DMA1_Channel3, &dmaInit);
+ DMA_ITConfig(DMA1_Channel3, DMA_IT_TC | DMA_IT_TE, ENABLE);
+
+
+ GPIO_SetBits(GPIOB, GPIO_Pin_5);
+ DMA_Cmd(DMA1_Channel3, ENABLE);
+
+// dbg_printf("HT=%d, TE=%d, TC=%d\n", DMA_GetFlagStatus(DMA1_IT_HT3), DMA_GetFlagStatus(DMA1_IT_TE3),
+// DMA_GetFlagStatus(DMA1_IT_TC3));
+
+// dbg_printf("HT=%d, TE=%d, TC=%d\n", DMA_GetFlagStatus(DMA1_IT_HT3), DMA_GetFlagStatus(DMA1_IT_TE3),
+// DMA_GetFlagStatus(DMA1_IT_TC3));
+
+ while (dma_busy) {
+ __NOP();
+
+// dbg_printf("HT=%d, TE=%d, TC=%d\n", DMA_GetFlagStatus(DMA1_IT_HT3), DMA_GetFlagStatus(DMA1_IT_TE3),
+// DMA_GetFlagStatus(DMA1_IT_TC3));
+ }
+ GPIO_ResetBits(GPIOB, GPIO_Pin_5);
+}
+
+extern "C"
+void DMA1_Channel3_IRQHandler() {
+ ITStatus tc = DMA_GetITStatus(DMA1_IT_TC3);
+ ITStatus te = DMA_GetITStatus(DMA1_IT_TE3);
+ ITStatus ht = DMA_GetITStatus(DMA1_IT_HT3);
+
+ if (tc || te || ht) {
+ DMA_ClearITPendingBit(DMA1_IT_GL3);
+ dma_busy = false;
+ }
+}