From acf22f18828595a0731d3558b7e2d2ba321c926d Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 20 Dec 2015 22:25:48 +0100 Subject: o Interrupt-driven serial port writing. --- CMakeLists.txt | 14 ++-- gdb-start | 16 ++++- init_low.s | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- serial2.cpp | 98 +++++++++++++++---------- 4 files changed, 289 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c894168..99b97dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,17 +6,17 @@ project(stm32f103-playground C CXX ASM) function(add_extra_commands target_name) add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND arm-none-eabi-objdump -D ${target_name} > ${target_name}.asm) + COMMAND mkdir -p ${target_name}-info && arm-none-eabi-objdump -D ${target_name} > ${target_name}-info/${target_name}.asm) add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND arm-none-eabi-nm ${target_name} > ${target_name}.nm) + COMMAND mkdir -p ${target_name}-info && arm-none-eabi-nm ${target_name} > ${target_name}-info/${target_name}.nm) add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND arm-none-eabi-size ${target_name} > ${target_name}.size) + COMMAND mkdir -p ${target_name}-info && arm-none-eabi-size ${target_name} > ${target_name}-info/${target_name}.size) add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND arm-none-eabi-readelf -a ${target_name} > ${target_name}.readelf) + COMMAND mkdir -p ${target_name}-info && arm-none-eabi-readelf -a ${target_name} > ${target_name}-info/${target_name}.readelf) add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND arm-none-eabi-objcopy -O ihex ${target_name} ${target_name}.hex) + COMMAND mkdir -p ${target_name}-info && arm-none-eabi-objcopy -O ihex ${target_name} ${target_name}-info/${target_name}.hex) add_custom_command(TARGET ${target_name} POST_BUILD - COMMAND arm-none-eabi-objcopy -O binary ${target_name} ${target_name}.bin) + COMMAND mkdir -p ${target_name}-info && arm-none-eabi-objcopy -O binary ${target_name} ${target_name}-info/${target_name}.bin) endfunction() # https://github.com/cjlano/tinyprintf @@ -78,7 +78,9 @@ add_executable(serial2.elf serial2.cpp init_low.s init_high.cpp include/stm32f10 debug.cpp debug.h tmp/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c tmp/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c + tmp/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/misc.c tmp/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rcc.c + tmp/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_usart.c tmp/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c ) target_link_libraries(serial2.elf tinyprintf) diff --git a/gdb-start b/gdb-start index 07bb364..ead4d9b 100644 --- a/gdb-start +++ b/gdb-start @@ -27,7 +27,21 @@ define flash_serial1 set confirm on monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480 - delete breakpoint 1 + hbreak halt +end + +define flash_serial2 + shell cd build && make serial2.elf + + monitor arm semihosting enable + monitor reset halt + + set confirm off + file build/serial2.elf + load build/serial2.elf + set confirm on + + monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480 hbreak halt end diff --git a/init_low.s b/init_low.s index bd7f329..1c3d10e 100644 --- a/init_low.s +++ b/init_low.s @@ -9,24 +9,68 @@ http://stackoverflow.com/questions/9565921/cortex-m3-initialisation .section .isr_vectors +/* TODO: Move this to C code */ .global vectors vectors: -stacktop: .word 0x20001000 -.word _Reset_Handler -.word NMI_Handler -.word HardFault_Handler -.word MemManage_Handler -.word BusFault_Handler -.word UsageFault_Handler -.word halt -.word halt -.word halt -.word halt -.word halt -.word halt -.word halt -.word halt -.word halt + .word 0x20001000 /* TODO: this should come from the linker */ + .word _Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 /* Not used */ + .word 0 /* Not used */ + .word 0 /* Not used */ + .word 0 /* Not used */ + .word SVC_Handler + .word DebugMon_Handler + .word 0 /* Not used */ + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_IRQHandler + .word TAMPER_IRQHandler + .word RTC_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word USB_HP_CAN1_TX_IRQHandler + .word USB_LP_CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_IRQHandler + .word TIM1_UP_IRQHandler + .word TIM1_TRG_COM_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTCAlarm_IRQHandler + .word USBWakeUp_IRQHandler /* VERY significant */ .section .text @@ -66,4 +110,150 @@ BusFault_Handler: UsageFault_Handler: b halt +/* +TODO: replace with functions like this: +void TIM2_IRQHandler() __attribute__ ((weak, alias ("Default_Handler"))); +*/ + +.weak SVC_Handler +.thumb_set SVC_Handler, halt + +.weak DebugMon_Handler +.thumb_set DebugMon_Handler, halt + +.weak PendSV_Handler +.thumb_set PendSV_Handler, halt + +.weak SysTick_Handler +.thumb_set SysTick_Handler, halt + +.weak WWDG_IRQHandler +.thumb_set WWDG_IRQHandler, halt + +.weak PVD_IRQHandler +.thumb_set PVD_IRQHandler, halt + +.weak TAMPER_IRQHandler +.thumb_set TAMPER_IRQHandler, halt + +.weak RTC_IRQHandler +.thumb_set RTC_IRQHandler, halt + +.weak FLASH_IRQHandler +.thumb_set FLASH_IRQHandler, halt + +.weak RCC_IRQHandler +.thumb_set RCC_IRQHandler, halt + +.weak EXTI0_IRQHandler +.thumb_set EXTI0_IRQHandler, halt + +.weak EXTI1_IRQHandler +.thumb_set EXTI1_IRQHandler, halt + +.weak EXTI2_IRQHandler +.thumb_set EXTI2_IRQHandler, halt + +.weak EXTI3_IRQHandler +.thumb_set EXTI3_IRQHandler, halt + +.weak EXTI4_IRQHandler +.thumb_set EXTI4_IRQHandler, halt + +.weak DMA1_Channel1_IRQHandler +.thumb_set DMA1_Channel1_IRQHandler, halt + +.weak DMA1_Channel2_IRQHandler +.thumb_set DMA1_Channel2_IRQHandler, halt + +.weak DMA1_Channel3_IRQHandler +.thumb_set DMA1_Channel3_IRQHandler, halt + +.weak DMA1_Channel4_IRQHandler +.thumb_set DMA1_Channel4_IRQHandler, halt + +.weak DMA1_Channel5_IRQHandler +.thumb_set DMA1_Channel5_IRQHandler, halt + +.weak DMA1_Channel6_IRQHandler +.thumb_set DMA1_Channel6_IRQHandler, halt + +.weak DMA1_Channel7_IRQHandler +.thumb_set DMA1_Channel7_IRQHandler, halt + +.weak ADC1_2_IRQHandler +.thumb_set ADC1_2_IRQHandler, halt + +.weak USB_HP_CAN1_TX_IRQHandler +.thumb_set USB_HP_CAN1_TX_IRQHandler, halt + +.weak USB_LP_CAN1_RX0_IRQHandler +.thumb_set USB_LP_CAN1_RX0_IRQHandler, halt + +.weak CAN1_RX1_IRQHandler +.thumb_set CAN1_RX1_IRQHandler, halt + +.weak CAN1_SCE_IRQHandler +.thumb_set CAN1_SCE_IRQHandler, halt + +.weak EXTI9_5_IRQHandler +.thumb_set EXTI9_5_IRQHandler, halt + +.weak TIM1_BRK_IRQHandler +.thumb_set TIM1_BRK_IRQHandler, halt + +.weak TIM1_UP_IRQHandler +.thumb_set TIM1_UP_IRQHandler, halt + +.weak TIM1_TRG_COM_IRQHandler +.thumb_set TIM1_TRG_COM_IRQHandler, halt + +.weak TIM1_CC_IRQHandler +.thumb_set TIM1_CC_IRQHandler, halt + +.weak TIM2_IRQHandler +.thumb_set TIM2_IRQHandler, halt + +.weak TIM3_IRQHandler +.thumb_set TIM3_IRQHandler, halt + +.weak TIM4_IRQHandler +.thumb_set TIM4_IRQHandler, halt + +.weak I2C1_EV_IRQHandler +.thumb_set I2C1_EV_IRQHandler, halt + +.weak I2C1_ER_IRQHandler +.thumb_set I2C1_ER_IRQHandler, halt + +.weak I2C2_EV_IRQHandler +.thumb_set I2C2_EV_IRQHandler, halt + +.weak I2C2_ER_IRQHandler +.thumb_set I2C2_ER_IRQHandler, halt + +.weak SPI1_IRQHandler +.thumb_set SPI1_IRQHandler, halt + +.weak SPI2_IRQHandler +.thumb_set SPI2_IRQHandler, halt + +.weak USART1_IRQHandler +.thumb_set USART1_IRQHandler, halt + +.weak USART2_IRQHandler +.thumb_set USART2_IRQHandler, halt + +.weak USART3_IRQHandler +.thumb_set USART3_IRQHandler, halt + +.weak EXTI15_10_IRQHandler +.thumb_set EXTI15_10_IRQHandler, halt + +.weak RTCAlarm_IRQHandler +.thumb_set RTCAlarm_IRQHandler, halt + +.weak USBWakeUp_IRQHandler +.thumb_set USBWakeUp_IRQHandler, halt + .end diff --git a/serial2.cpp b/serial2.cpp index 58ea536..c01aa13 100644 --- a/serial2.cpp +++ b/serial2.cpp @@ -1,22 +1,30 @@ -#include "tinyprintf.h" #include #include #include #include -#include -#include -#include "tinyprintf.h" +#include +#include + #include "debug.h" +#include "tinyprintf.h" int init_high(); extern "C" void halt(); -#include "stm32f10x_conf.h" - extern "C" __attribute__((naked)) void HardFault_Handler_C(uint32_t *hardfault_args) { + dbg_printf("r0 = 0x%08x (%d)\n", hardfault_args[0], hardfault_args[0]); + dbg_printf("r1 = 0x%08x (%d)\n", hardfault_args[1], hardfault_args[1]); + dbg_printf("r2 = 0x%08x (%d)\n", hardfault_args[2], hardfault_args[2]); + dbg_printf("r3 = 0x%08x (%d)\n", hardfault_args[3], hardfault_args[3]); + dbg_printf("r12 = 0x%08x (%d)\n", hardfault_args[4], hardfault_args[4]); + dbg_printf("lr = 0x%08x (%d)\n", hardfault_args[5], hardfault_args[5]); + dbg_printf("pc = 0x%08x (%d)\n", hardfault_args[6], hardfault_args[6]); + dbg_printf("psr = 0x%08x (%d)\n", hardfault_args[7], hardfault_args[7]); + dbg_printf("\n"); + halt(); } @@ -30,6 +38,8 @@ int run = 1; volatile USART_TypeDef *usart1 = (volatile USART_TypeDef *) USART1_BASE; +volatile uint8_t tx_ready = 0; + /* * When we get there the stack pointer is set */ @@ -79,53 +89,65 @@ int main() { init.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &init); + NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); + NVIC_InitTypeDef NVIC_InitStruct = { + /*.NVIC_IRQChannel =*/ USART1_IRQn, + /*.NVIC_IRQChannelPreemptionPriority =*/ 0, + /*.NVIC_IRQChannel =*/ 0, + /*.NVIC_IRQChannelCmd =*/ ENABLE, + }; + NVIC_Init(&NVIC_InitStruct); + NVIC_EnableIRQ(USART1_IRQn); + // 8 bit mode USART1->CR1 &= ~USART_CR1_M; USART1->CR2 &= ~USART_CR2_STOP_1; - USART1->CR1 |= USART_CR1_UE /* Set UART Enable */ - | USART_CR1_TE; /* Set Transmission Enable */ - // Set baud rate int mantissa = 39; int fraction = static_cast(16 * 0.0625); // == 1 // 72M / (16*39.0625) = 115200 USART1->BRR = static_cast(mantissa << 4 | fraction); + USART1->CR1 |= USART_CR1_UE /* Set UART Enable */ + | USART_CR1_TE /* Set Transmission Enable */ + | USART_CR1_TXEIE; /* Set TX buffer Empty Interrupt Enable */ + char c = 'A'; + tx_ready = 1; while (run) { - int txe = USART1->SR & USART_SR_TXE; - -// dbg_printf("1:%d?\n", x); - -// char mm[100]; -// tfp_sprintf(mm, "2:%d?\n", x); -// send_command(SYS_WRITE0, mm); - -// printf(" %u?\n", usart1->SR); -// printf(" %u?\n", 1); - - if (txe) { - GPIO_SetBits(GPIOB, GPIO_Pin_All); - GPIO_ResetBits(GPIOB, GPIO_Pin_All); - - USART1->DR = (uint16_t) c; -// USART1->DR = 0x55; - - if (c == 'Z') { - c = 'a'; - } else if (c == 'z') { - c = '0'; - } else if (c == '9') { - c = '\n'; - } else if (c == '\n') { - c = 'A'; - } else { - c++; - } + // wait for TX to be ready + while (!tx_ready); + tx_ready = 0; + + GPIO_SetBits(GPIOB, GPIO_Pin_All); + GPIO_ResetBits(GPIOB, GPIO_Pin_All); + + USART1->DR = (uint16_t) c; + USART_ITConfig(USART1, USART_IT_TXE, ENABLE); + + if (c == 'Z') { + c = 'a'; + } else if (c == 'z') { + c = '0'; + } else if (c == '9') { + c = '\n'; + } else if (c == '\n') { + c = 'A'; + } else { + c++; } } return 0; } +extern "C" +void USART1_IRQHandler() { + tx_ready = 1; + + if (USART_GetITStatus(USART1, USART_IT_TXE) == SET) { + // Disable the interrupt + USART_ITConfig(USART1, USART_IT_TXE, DISABLE); + } +} -- cgit v1.2.3