#include #include "systems.h" #include #ifdef STM32F30X #include #include #include #elif defined( STM32F40_41xxx ) #include #include #include #endif #include #include extern RCC_ClocksTypeDef RCC_Clocks; //For precise timing. volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register volatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register volatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register void send_openocd_command(int command, void *message) { #ifdef DEBUG asm("mov r0, %[cmd];" "mov r1, %[msg];" "bkpt #0xAB" : : [cmd] "r" (command), [msg] "r" (message) : "r0", "r1", "memory"); #endif } void send_text( const char * text ) { uint32_t m[] = { 2, (uint32_t)text, strlen(text) }; send_openocd_command(0x05, m); } int __attribute__((used)) _write (int fd, const void *buf, size_t count) { //uint32_t m[] = { 2, (uint32_t)buf, count }; //send_openocd_command(0x05, m); int i; for (i=count; i > 0; --i) { while (!(USART1->SR & USART_SR_TXE)); USART1->DR = (uint16_t)(*((char*) buf) & 0x01FF); buf++; } return count; } int __attribute__((used)) _read(int fd, void *buf, size_t count) { int i; for (i=0; i < count; ++i) { while (!(USART1->SR & USART_SR_RXNE)); *((char*) buf) = USART1->DR; _write(0, buf, 1); if (*((char*) buf) == '\r') break; buf++; } i++; return i; } void __attribute__((used)) * _sbrk(int incr) { extern char _ebss; // Defined by the linker static char *heap_end; char *prev_heap_end; if (heap_end == 0) { heap_end = &_ebss; } prev_heap_end = heap_end; char * stack = (char*) __get_MSP(); if (heap_end + incr > stack) { return (void*)(-1); } heap_end += incr; return (void*) prev_heap_end; } void _delay_us(uint32_t us) { if( us ) us--; //Approximate extra overhead time. us *= RCC_Clocks.HCLK_Frequency/1000000; *SCB_DEMCR = *SCB_DEMCR | 0x01000000; *DWT_CYCCNT = 0; // reset the counter *DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter while( *DWT_CYCCNT < us ); } void ConfigureUART() { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; // Enable clock for GPIOB RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); /** * Enable clock for USART1 peripheral */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /** * Set Baudrate to value you pass to function * Disable Hardware Flow control * Set Mode To TX and RX, so USART will work in full-duplex mode * Disable parity bit * Set 1 stop bit * Set Data bits to 8 * * Initialize USART1 * Activate USART1 */ USART_InitStruct.USART_BaudRate = 115200; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART1, &USART_InitStruct); USART_Cmd(USART1, ENABLE); /** * Enable RX interrupt */ //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /** * Set Channel to USART1 * Set Channel Cmd to enable. That will enable USART1 channel in NVIC * Set Both priorities to 0. This means high priority * * Initialize NVIC */ /*NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStruct);*/ } void ConfigureDMX() { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // Set up UART GPIOs GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); // Set up control GPIOs GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); // Set up UART RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); USART_InitStruct.USART_BaudRate = 250000; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_StopBits = USART_StopBits_2; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART2, &USART_InitStruct); USART_Cmd(USART2, ENABLE); } void ConfigureLED() { ConfigureGPIO(LED_RED, INOUT_OUT); ConfigureGPIO(LED_GREEN, INOUT_OUT); ConfigureGPIO(LED_BLUE, INOUT_OUT); } uint8_t GetGPIOFromString( const char * str ) { int mode = 0; int port = -1; int pin = -1; const char * st = str; for( ; *st; st++ ) { char c = *st; if( mode == 0 ) { if( c >= 'A' && c <= 'F' ) { port = c - 'A'; mode = 2; } else if( c >= 'a' && c <= 'f' ) { port = c - 'a'; mode = 2; } } else if( mode == 2 ) { if( c >= '0' && c <= '9' ) { pin = 0; mode = 3; } } if( mode == 3 ) { if( c >= '0' && c <= '9' ) { pin = pin * 10; pin+= c - '0'; } else { break; } } } if( port > 0 && pin > 0 && port <= 6 && pin <= 15) { return (port<<4)|pin; } else { return 0xff; } } void ConfigureGPIO( uint8_t gpio, int parameters ) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable the GPIO_LED Clock */ #ifdef STM32F30X RCC_AHBPeriphClockCmd( 1<<(17+(gpio>>4)), ENABLE); #elif defined( STM32F40_41xxx ) RCC_AHB1PeriphClockCmd( 1<<((gpio>>4)), ENABLE); #endif if( parameters & DEFAULT_VALUE_FLAG ) { GPIOOn( gpio ); } else { GPIOOff( gpio ); } /* Configure the GPIO_LED pin */ GPIO_InitStructure.GPIO_Pin = 1<<(gpio&0xf); GPIO_InitStructure.GPIO_Mode = (parameters&INOUT_FLAG)?GPIO_Mode_OUT:GPIO_Mode_IN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = (parameters&PUPD_FLAG)?( (parameters&PUPD_UP)?GPIO_PuPd_UP:GPIO_PuPd_DOWN ):GPIO_PuPd_NOPULL; #ifdef STM32F30X GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; #elif defined( STM32F40_41xxx ) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; #endif GPIO_Init(GPIOOf(gpio), &GPIO_InitStructure); } void JumpToBootloader(void) { // Many thanks to https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/ void (*SysMemBootJump)(void); volatile uint32_t addr = 0x1FFF0000; RCC_DeInit(); // Disable and reset systick SysTick->CTRL = 0; SysTick->LOAD = 0; SysTick->VAL = 0; __disable_irq(); // Remap system memory SYSCFG->MEMRMP = 0x01; SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4))); // Set main stack pointer __set_MSP(*(uint32_t *)addr); // Jump SysMemBootJump(); }