2021-02-23 19:05:43 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
#include "systems.h"
|
|
|
|
#include <string.h>
|
|
|
|
#ifdef STM32F30X
|
|
|
|
#include <stm32f30x.h>
|
|
|
|
#include <stm32f30x_rcc.h>
|
|
|
|
#include <stm32f30x_gpio.h>
|
|
|
|
#elif defined( STM32F40_41xxx )
|
|
|
|
#include <stm32f4xx.h>
|
|
|
|
#include <stm32f4xx_rcc.h>
|
|
|
|
#include <stm32f4xx_gpio.h>
|
|
|
|
#endif
|
|
|
|
#include <core_cm4.h>
|
|
|
|
#include <core_cmFunc.h>
|
|
|
|
|
|
|
|
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 ConfigureLED()
|
|
|
|
{
|
|
|
|
ConfigureGPIO( LEDPIN, 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);
|
|
|
|
}
|
|
|
|
|
2021-03-02 19:27:50 +01:00
|
|
|
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();
|
|
|
|
}
|