559 lines
10 KiB
Arduino
Raw Normal View History

2017-08-03 18:39:21 +03:00
#define _FLASH_PROG 1
// Temp
#define SIGNATURE_0 0x1E
#define SIGNATURE_1 0x55 //0x97
#define SIGNATURE_2 0xAA //0x02
#define SIGNATURE_3 0x97
#define SIGNATURE_4 0x02
#define STM32F10X_CL
#include "stm32f10x.h"
#include "stk500.h"
#include "stm32f10x_flash.h"
#define OPTIBOOT_MAJVER 4
#define OPTIBOOT_MINVER 5
uint32_t ResetReason ;
uint32_t LongCount ;
uint8_t Buff[512] ;
uint8_t NotSynced ;
uint8_t Port ;
static void start_timer2()
{
TIM2->CNT = 0 ;
TIM2->PSC = 71 ; // 72-1;for 72 MHZ /1.0usec/(71+1)
TIM2->ARR = 0xFFFF; //count till max
}
void RCC_DeInit(void)
{
/* Disable APB2 Peripheral Reset */
RCC->APB2RSTR = 0x00000000;
/* Disable APB1 Peripheral Reset */
RCC->APB1RSTR = 0x00000000;
/* FLITF and SRAM Clock ON */
RCC->AHBENR = 0x00000014;
/* Disable APB2 Peripheral Clock */
RCC->APB2ENR = 0x00000000;
/* Disable APB1 Peripheral Clock */
RCC->APB1ENR = 0x00000000;
/* Set HSION bit */
RCC->CR |= (u32)0x00000001;
/* Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] and MCO[2:0] bits*/
RCC->CFGR &= 0xF8FF0000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= 0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE bits */
RCC->CFGR &= 0xFF80FFFF;
/* Disable all interrupts */
RCC->CIR = 0x009F0000;
}
void disableInterrupts()
{
__disable_irq() ;
NVIC_DisableIRQ(USART1_IRQn) ;
NVIC_DisableIRQ(USART2_IRQn) ;
NVIC_DisableIRQ(USART3_IRQn) ;
NVIC_DisableIRQ(TIM1_BRK_IRQn) ;
NVIC_DisableIRQ(TIM1_UP_IRQn) ;
NVIC_DisableIRQ(TIM1_TRG_COM_IRQn) ;
NVIC_DisableIRQ(TIM1_CC_IRQn) ;
NVIC_DisableIRQ(TIM3_IRQn) ;
NVIC_DisableIRQ(TIM4_IRQn) ;
NVIC_DisableIRQ(ADC1_2_IRQn) ;
SysTick->CTRL = 0 ;
}
static void executeApp()
{
// Expected at 0x08002000
uint32_t *p ;
// Disable all peripheral clocks
// Disable used PLL
// Disable interrupts
// Clear pending interrupts
p = (uint32_t *) 0x08002000 ;
if ( *p == 0x20005000 )
{
USART1->CR1 = 0 ;
USART1->BRR = 0 ;
USART2->CR1 = 0 ;
USART2->BRR = 0 ;
USART3->CR1 = 0 ;
USART3->BRR = 0 ;
(void) USART2->SR ;
(void) USART2->DR ;
(void) USART1->SR ;
(void) USART1->DR ;
USART1->SR = 0 ;
USART2->SR = 0 ;
USART3->SR = 0 ;
RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN ; // Disable clock
RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN ; // Disable clock
TIM2->CR1 = 0 ;
disableInterrupts() ;
NVIC->ICER[0] = 0xFFFFFFFF ;
NVIC->ICER[1] = 0xFFFFFFFF ;
NVIC->ICER[2] = 0xFFFFFFFF ;
NVIC->ICPR[0] = 0xFFFFFFFF ;
NVIC->ICPR[1] = 0xFFFFFFFF ;
NVIC->ICPR[2] = 0xFFFFFFFF ;
RCC_DeInit() ;
SysTick->CTRL = 0 ;
SysTick->LOAD = 0 ;
SysTick->VAL = 0 ;
asm(" mov.w r1, #134217728"); // 0x8000000
asm(" add.w r1, #8192"); // 0x2000
asm(" movw r0, #60680"); // 0xED08
asm(" movt r0, #57344"); // 0xE000
asm(" str r1, [r0, #0]"); // Set the VTOR
asm("ldr r0, [r1, #0]"); // Stack pointer value
asm("msr msp, r0"); // Set it
asm("ldr r0, [r1, #4]"); // Reset address
asm("mov.w r1, #1");
asm("orr r0, r1"); // Set lsbit
asm("bx r0"); // Execute application
}
}
static uint16_t test0()
{
if ( USART2->SR & USART_SR_RXNE )
{
return USART2->DR ;
}
return 0xFFFF ;
}
static uint16_t test1()
{
if ( USART1->SR & USART_SR_RXNE )
{
return USART1->DR ;
}
return 0xFFFF ;
}
uint8_t getch1()
{
while ( ( USART1->SR & USART_SR_RXNE ) == 0 )
{
IWDG->KR = 0xAAAA ; // reload
if ( TIM2->SR & TIM_SR_UIF )
{
TIM2->SR &= ~TIM_SR_UIF ;
GPIOA->ODR ^= 0x0002 ;
}
// wait
}
return USART1->DR ;
}
uint8_t getch()
{
if ( Port )
{
return getch1() ;
}
while ( ( USART2->SR & USART_SR_RXNE ) == 0 )
{
IWDG->KR = 0xAAAA ; // reload
if ( TIM2->SR & TIM_SR_UIF )
{
TIM2->SR &= ~TIM_SR_UIF ;
GPIOA->ODR ^= 0x0002 ;
}
// wait
}
return USART2->DR ;
}
void putch( uint8_t byte )
{
if ( Port )
{
while ( ( USART1->SR & USART_SR_TXE ) == 0 )
{
// wait
}
USART1->DR = byte ;
}
else
{
while ( ( USART3->SR & USART_SR_TXE ) == 0 )
{
// wait
}
USART3->DR = byte ;
}
}
static void serialInit()
{
RCC->APB2ENR |= RCC_APB2ENR_USART1EN ; // Enable clock
RCC->APB1ENR |= RCC_APB1ENR_USART2EN ; // Enable clock
RCC->APB1ENR |= RCC_APB1ENR_USART3EN ; // Enable clock
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ;
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN ;
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN ;
GPIOA->CRH = GPIOA->CRH & 0xFFFFFF0F | 0x00000090 ; // PA9
// USART2 TX is PA2, only Rx used
// USART3 TX is PB10, only Tx used
GPIOB->CRH = GPIOB->CRH & 0xFFFFF0FF | 0x00000900 ; // PB10
USART1->BRR = 72000000 / 57600 ;
USART1->CR1 = 0x200C ;
USART2->BRR = 36000000 / 57600 ;
USART2->CR1 = 0x200C ;
USART2->CR2 = 0 ;
USART2->CR3 = 0 ;
USART3->BRR = 36000000 / 57600 ;
USART3->CR1 = 0x200C ;
USART3->CR2 = 0 ;
USART3->CR3 = 0 ;
}
void setup()
{
serialInit() ;
start_timer2() ;//0.5us
FLASH_Unlock() ;
GPIOA->BSRR = 0x000000F1 ;
GPIOA->CRL = GPIOA->CRL & 0x0000FF00 | 0x88880028 ; // LED and inputs
// Input with pullup, 1000B, and set the ODR bit
GPIOB->CRL = GPIOB->CRL & 0xFFFF0F0F | 0x00002020 ; // PB1 and PB3, invert controls
GPIOB->BRR = 0x00000008 ;
GPIOB->BSRR = 0x00000002 ;
}
void verifySpace()
{
if ( getch() != CRC_EOP)
{
NotSynced = 1 ;
return ;
}
putch(STK_INSYNC);
}
void bgetNch(uint8_t count)
{
do
{
getch() ;
} while (--count) ;
verifySpace() ;
}
void loader( uint32_t check )
{
uint8_t ch ;
uint8_t GPIOR0 ;
uint32_t address = 0 ;
uint8_t lastCh ;
ResetReason = RCC->CSR ;
RCC->CSR |= RCC_CSR_RMVF ;
if ( ResetReason & RCC_CSR_SFTRSTF )
{
check = 0 ; // Stay in bootloader
}
NVIC_DisableIRQ(TIM2_IRQn) ;
if ( check )
{
TIM2->CNT = 0 ;
TIM2->SR &= ~TIM_SR_UIF ;
while ( ( TIM2->SR & TIM_SR_UIF ) == 0 )
{
// wait
}
TIM2->SR &= ~TIM_SR_UIF ;
while ( ( TIM2->SR & TIM_SR_UIF ) == 0 )
{
// wait
}
TIM2->SR &= ~TIM_SR_UIF ;
ch = GPIOA->IDR & 0xF1 ;
if ( ch != 0xF0 )
{
return ;
}
}
disableInterrupts() ;
NotSynced = 1 ;
lastCh = 0 ;
for (;;)
{
while ( NotSynced )
{
uint16_t data ;
data = test0() ;
if ( data != 0xFFFF )
{
ch = data ;
if ( ( lastCh == STK_GET_SYNC ) && ( ch == CRC_EOP ) )
{
NotSynced = 0 ;
Port = 0 ;
break ;
}
lastCh = ch ;
}
data = test1() ;
if ( data != 0xFFFF )
{
ch = data ;
if ( ( lastCh == STK_GET_SYNC ) && ( ch == CRC_EOP ) )
{
NotSynced = 0 ;
Port = 1 ;
break ;
}
lastCh = ch ;
}
IWDG->KR = 0xAAAA ; // reload
if ( TIM2->SR & TIM_SR_UIF )
{
TIM2->SR &= ~TIM_SR_UIF ;
GPIOA->ODR ^= 0x0002 ;
}
}
/* get character from UART */
ch = getch() ;
if(ch == STK_GET_PARAMETER)
{
GPIOR0 = getch() ;
verifySpace() ;
if (GPIOR0 == 0x82)
{
putch(OPTIBOOT_MINVER) ;
}
else if (GPIOR0 == 0x81)
{
putch(OPTIBOOT_MAJVER) ;
}
else
{
/*
* GET PARAMETER returns a generic 0x03 reply for
* other parameters - enough to keep Avrdude happy
*/
putch(0x03) ;
}
}
else if(ch == STK_SET_DEVICE)
{
// SET DEVICE is ignored
bgetNch(20) ;
}
else if(ch == STK_SET_DEVICE_EXT)
{
// SET DEVICE EXT is ignored
bgetNch(5);
}
else if(ch == STK_LOAD_ADDRESS)
{
// LOAD ADDRESS
uint16_t newAddress ;
newAddress = getch() ;
newAddress = (newAddress & 0xff) | (getch() << 8);
address = newAddress ; // Convert from word address to byte address
address <<= 1 ;
verifySpace() ;
}
else if(ch == STK_UNIVERSAL)
{
// UNIVERSAL command is ignored
bgetNch(4) ;
putch(0x00) ;
}
else if(ch == STK_PROG_PAGE)
{
// PROGRAM PAGE - we support flash programming only, not EEPROM
uint8_t *bufPtr;
uint16_t addrPtr;
uint16_t length ;
uint16_t count ;
uint16_t data ;
uint8_t *memAddress ;
length = getch() << 8 ; /* getlen() */
length |= getch() ;
getch() ; // discard flash/eeprom byte
// While that is going on, read in page contents
count = length ;
bufPtr = Buff;
do
{
*bufPtr++ = getch() ;
}
while (--count) ;
if ( length & 1 )
{
*bufPtr = 0xFF ;
}
count = length ;
count += 1 ;
count /= 2 ;
memAddress = (uint8_t *)(address + 0x08000000) ;
if ( (uint32_t)memAddress < 0x08020000 )
{
// Read command terminator, start reply
verifySpace();
if ( (uint32_t)memAddress >= 0x08002000 )
{
if ( ((uint32_t)memAddress & 0x000003FF) == 0 )
{
// At page start so erase it
FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
FLASH_ErasePage( (uint32_t)memAddress ) ;
}
bufPtr = Buff;
while ( count )
{
data = *bufPtr++ ;
data |= *bufPtr++ << 8 ;
FLASH_ProgramHalfWord( (uint32_t)memAddress, data ) ;
memAddress += 2 ;
count -= 1 ;
}
}
}
else
{
verifySpace();
}
}
else if(ch == STK_READ_PAGE)
{
uint16_t length ;
uint8_t xlen ;
uint8_t *memAddress ;
memAddress = (uint8_t *)(address + 0x08000000) ;
// READ PAGE - we only read flash
xlen = getch() ; /* getlen() */
length = getch() | (xlen << 8 ) ;
getch() ;
verifySpace() ;
do
{
putch( *memAddress++) ;
}
while (--length) ;
}
else if(ch == STK_READ_SIGN)
{
// READ SIGN - return what Avrdude wants to hear
verifySpace() ;
putch(SIGNATURE_0) ;
if ( Port )
{
putch(SIGNATURE_3) ;
putch(SIGNATURE_4) ;
}
else
{
putch(SIGNATURE_1) ;
putch(SIGNATURE_2) ;
}
}
else if (ch == STK_LEAVE_PROGMODE)
{ /* 'Q' */
// Adaboot no-wait mod
// watchdogConfig(WATCHDOG_16MS);
verifySpace() ;
}
else
{
// This covers the response to commands like STK_ENTER_PROGMODE
verifySpace() ;
}
if ( NotSynced )
{
continue ;
}
putch(STK_OK);
}
}
void loop()
{
loader(1) ;
// Execute loaded application
executeApp() ;
loader(0) ;
// The next bit not really needed as loader(0) doesn't return
for(;;)
{
if ( TIM2->SR & TIM_SR_UIF )
{
TIM2->SR &= ~TIM_SR_UIF ;
if ( ++LongCount > 4 )
{
GPIOA->ODR ^= 0x0002 ;
LongCount = 0 ;
}
}
}
}