Files
templates/c/rs485-boot/ports/stm32f103/rs485_boot_stm32f103.c

18 lines
2.9 KiB
C

#include "rs485_boot_stm32f103.h"
#include "rs485_boot_port_config.h"
#include "stm32f10x.h"
#include <string.h>
static bool fw(void){while(FLASH->SR&FLASH_SR_BSY){}if(FLASH->SR&(FLASH_SR_PGERR|FLASH_SR_WRPRTERR)){FLASH->SR=FLASH_SR_PGERR|FLASH_SR_WRPRTERR|FLASH_SR_EOP;return false;}FLASH->SR=FLASH_SR_EOP;return true;}
static void ul(void){if(FLASH->CR&FLASH_CR_LOCK){FLASH->KEYR=0x45670123UL;FLASH->KEYR=0xCDEF89ABUL;}}
static void lk(void){FLASH->CR|=FLASH_CR_LOCK;}
void rs485_boot_hw_init(void){uint32_t c;RCC->APB2ENR|=RCC_APB2ENR_IOPAEN|RCC_APB2ENR_USART1EN;c=GPIOA->CRH;c&=~((0xFUL<<0)|(0xFUL<<4)|(0xFUL<<8));c|=(0x3UL<<0)|(0xBUL<<4)|(0x4UL<<8);GPIOA->CRH=c;GPIOA->BRR=1UL<<RS485_BOOT_DE_PIN;USART1->BRR=(SystemCoreClock+RS485_BOOT_BAUDRATE/2U)/RS485_BOOT_BAUDRATE;USART1->CR1=USART_CR1_TE|USART_CR1_RE|USART_CR1_UE;}
bool rs485_boot_hw_get_byte(uint8_t*b){uint32_t s=USART1->SR;if(s&(USART_SR_ORE|USART_SR_FE|USART_SR_NE)){(void)USART1->DR;return false;}if(!(s&USART_SR_RXNE))return false;*b=(uint8_t)USART1->DR;return true;}
static bool tx(void*u,const uint8_t*d,uint16_t n){uint16_t i;(void)u;GPIOA->BSRR=1UL<<RS485_BOOT_DE_PIN;for(i=0;i<n;i++){while(!(USART1->SR&USART_SR_TXE)){}USART1->DR=d[i];}while(!(USART1->SR&USART_SR_TC)){}GPIOA->BRR=1UL<<RS485_BOOT_DE_PIN;return true;}
static bool er(void*u,uint32_t n){uint32_t a,e;(void)u;if(!n||n>RS485_BOOT_FLASH_END-RS485_BOOT_APP_ADDRESS)return false;e=RS485_BOOT_APP_ADDRESS+((n+RS485_BOOT_FLASH_PAGE-1U)&~(RS485_BOOT_FLASH_PAGE-1U));ul();for(a=RS485_BOOT_APP_ADDRESS;a<e;a+=RS485_BOOT_FLASH_PAGE){FLASH->CR=FLASH_CR_PER;FLASH->AR=a;FLASH->CR|=FLASH_CR_STRT;if(!fw()){FLASH->CR=0;lk();return false;}}FLASH->CR=0;lk();return true;}
static bool wr(void*u,uint32_t o,const uint8_t*d,uint16_t n){uint16_t i;(void)u;if((o&1U)||o+n>RS485_BOOT_FLASH_END-RS485_BOOT_APP_ADDRESS)return false;ul();for(i=0;i<n;i+=2){uint16_t v=(uint16_t)d[i]|(uint16_t)(i+1<n?((uint16_t)d[i+1]<<8):0xFF00U);volatile uint16_t*q=(volatile uint16_t*)(RS485_BOOT_APP_ADDRESS+o+i);FLASH->CR=FLASH_CR_PG;*q=v;if(!fw()||*q!=v){FLASH->CR=0;lk();return false;}}FLASH->CR=0;lk();return true;}
static bool rd(void*u,uint32_t o,uint8_t*d,uint16_t n){(void)u;if(o+n>RS485_BOOT_FLASH_END-RS485_BOOT_APP_ADDRESS)return false;memcpy(d,(const void*)(RS485_BOOT_APP_ADDRESS+o),n);return true;}
static bool ok(void*u,uint32_t n,uint32_t c){uint32_t sp=*(const uint32_t*)RS485_BOOT_APP_ADDRESS,rv=*(const uint32_t*)(RS485_BOOT_APP_ADDRESS+4);(void)u;return sp>=0x20000000UL&&sp<=0x20005000UL&&(rv&1U)&&(rv&~1UL)>=RS485_BOOT_APP_ADDRESS&&(rv&~1UL)<RS485_BOOT_FLASH_END&&rs485_boot_crc32((const uint8_t*)RS485_BOOT_APP_ADDRESS,n)==c;}
static void reset(void*u){(void)u;NVIC_SystemReset();}
rs485_boot_config_t rs485_boot_hw_config(void){rs485_boot_config_t c={RS485_BOOT_APP_ADDRESS,RS485_BOOT_FLASH_END-RS485_BOOT_APP_ADDRESS,RS485_BOOT_MAX_BLOCK};return c;}
rs485_boot_port_t rs485_boot_hw_make_port(void){rs485_boot_port_t p={tx,er,wr,rd,ok,reset};return p;}