From 9b4bb6c02fcee89144fd8e3df2872cf5665879fa Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Sun, 24 Oct 2021 22:29:43 +0300 Subject: [PATCH] 3steppers next stage --- F0-nolib/3steppersLB/can.c | 10 +-- F0-nolib/3steppersLB/commonproto.c | 117 +++++++++++++++++++------ F0-nolib/3steppersLB/commonproto.h | 8 +- F0-nolib/3steppersLB/flash.c | 63 ++++++++----- F0-nolib/3steppersLB/flash.h | 34 ++++--- F0-nolib/3steppersLB/hardware.c | 75 +++++++++++++--- F0-nolib/3steppersLB/steppers.bin | Bin 15552 -> 17380 bytes F0-nolib/3steppersLB/steppers.c | 23 +++++ F0-nolib/3steppersLB/steppers.h | 27 ++++++ F0-nolib/3steppersLB/strfunct.c | 37 +++++--- F0-nolib/Snippets/Flash_EEPROM/flash.c | 19 ++-- F0-nolib/Snippets/Flash_EEPROM/flash.h | 14 +-- F0-nolib/Snippets/printuhex.c | 23 +++++ F0-nolib/inc/Fx/flash_size_reg.h | 10 +++ F0-nolib/inc/Fx/stm32f0.h | 7 +- F0-nolib/inc/Fx/stm32f1.h | 3 + F0-nolib/inc/ld/stm32f01234.ld | 2 +- F0-nolib/inc/ld/stm32f030f.ld | 2 + F0-nolib/inc/ld/stm32f042k.ld | 2 + F0-nolib/inc/ld/stm32f042x6.ld | 14 +++ F0-nolib/inc/ld/stm32f051x8.ld | 2 + F0-nolib/inc/ld/stm32f0728.ld | 2 + F0-nolib/inc/ld/stm32f072B.ld | 2 + F0-nolib/inc/ld/stm32f103x4.ld | 2 + F0-nolib/inc/ld/stm32f103x6.ld | 2 + F0-nolib/inc/ld/stm32f103x8.ld | 2 + F0-nolib/inc/ld/stm32f103xB.ld | 2 + F0-nolib/inc/ld/stm32f103xC.ld | 2 + F0-nolib/inc/ld/stm32f103xD.ld | 2 + F0-nolib/inc/ld/stm32f103xE.ld | 2 + F0-nolib/inc/ld/stm32f103xF.ld | 2 + F0-nolib/inc/ld/stm32f103xG.ld | 2 + F1-nolib/inc/ld/stm32f01234.ld | 5 +- F1-nolib/inc/ld/stm32f030f.ld | 2 + F1-nolib/inc/ld/stm32f042k.ld | 2 + F1-nolib/inc/ld/stm32f042x6.ld | 14 +++ F1-nolib/inc/ld/stm32f051x8.ld | 2 + F1-nolib/inc/ld/stm32f0728.ld | 2 + F1-nolib/inc/ld/stm32f072B.ld | 14 +++ F1-nolib/inc/ld/stm32f103x4.ld | 2 + F1-nolib/inc/ld/stm32f103x6.ld | 2 + F1-nolib/inc/ld/stm32f103x8.ld | 2 + F1-nolib/inc/ld/stm32f103xB.ld | 2 + F1-nolib/inc/ld/stm32f103xC.ld | 2 + F1-nolib/inc/ld/stm32f103xD.ld | 2 + F1-nolib/inc/ld/stm32f103xE.ld | 2 + F1-nolib/inc/ld/stm32f103xF.ld | 2 + F1-nolib/inc/ld/stm32f103xG.ld | 2 + stm32reg.png | Bin 0 -> 73901 bytes 49 files changed, 466 insertions(+), 107 deletions(-) create mode 100644 F0-nolib/3steppersLB/steppers.c create mode 100644 F0-nolib/3steppersLB/steppers.h create mode 100644 F0-nolib/inc/Fx/flash_size_reg.h create mode 100644 F0-nolib/inc/ld/stm32f042x6.ld create mode 100644 F1-nolib/inc/ld/stm32f042x6.ld create mode 100644 F1-nolib/inc/ld/stm32f072B.ld create mode 100644 stm32reg.png diff --git a/F0-nolib/3steppersLB/can.c b/F0-nolib/3steppersLB/can.c index a292bda..965fd7c 100644 --- a/F0-nolib/3steppersLB/can.c +++ b/F0-nolib/3steppersLB/can.c @@ -308,7 +308,7 @@ static void formerr(CAN_message *msg, errcodes err){ * @brief parseCANcommand - parser * @param msg - incoming message @ my CANID * FORMAT: - * 0 1 2 3 4 5 6 7 + * 0 1 2 3 4 5 6 7 * [CMD][PAR][errcode][VALUE] * CMD - uint16_t, PAR - uint8_t, errcode - one of CAN_errcodes, VALUE - int32_t * `errcode` of incoming message doesn't matter @@ -330,14 +330,14 @@ TRUE_INLINE void parseCANcommand(CAN_message *msg){ goto sendmessage; } msg->data[3] = ERR_OK; - uint8_t *par = (uint8_t *)(&msg->data[2]); - if(*par & 0x80){ + uint8_t par = msg->data[2]; + if(par & 0x80){ formerr(msg, ERR_BADPAR); goto sendmessage; } int32_t *val = (int32_t *)(&msg->data[4]); - if(msg->length == 8) *par |= 0x80; - else if(msg->length == 2) *par = CANMESG_NOPAR; // no parameter + if(msg->length == 8) par |= 0x80; + else if(msg->length == 2) par = CANMESG_NOPAR; // no parameter else if(msg->length != 3){ // wrong length formerr(msg, ERR_WRONGLEN); goto sendmessage; diff --git a/F0-nolib/3steppersLB/commonproto.c b/F0-nolib/3steppersLB/commonproto.c index ed6f56d..88ada4f 100644 --- a/F0-nolib/3steppersLB/commonproto.c +++ b/F0-nolib/3steppersLB/commonproto.c @@ -20,16 +20,20 @@ #include "buttons.h" #include "can.h" #include "commonproto.h" +#include "flash.h" #include "hardware.h" +#ifdef EBUG +#include "strfunct.h" +#endif /******* All functions from cmdlist[i].function *******/ -static errcodes pingparser(uint8_t _U_ *par, int32_t _U_ *val){ +static errcodes pingparser(uint8_t _U_ par, int32_t _U_ *val){ return ERR_OK; // just echo all input data over CAN (or return OK to USB) } -static errcodes relayparser(uint8_t _U_ *par, int32_t _U_ *val){ - if(ISSETTER(*par)){ +static errcodes relayparser(uint8_t par, int32_t *val){ + if(ISSETTER(par)){ if(*val) ON(RELAY); else OFF(RELAY); } @@ -37,8 +41,8 @@ static errcodes relayparser(uint8_t _U_ *par, int32_t _U_ *val){ return ERR_OK; } -static errcodes buzzerparser(uint8_t _U_ *par, int32_t _U_ *val){ - if(ISSETTER(*par)){ +static errcodes buzzerparser(uint8_t par, int32_t *val){ + if(ISSETTER(par)){ if(*val) ON(BUZZER); else OFF(BUZZER); } @@ -46,8 +50,8 @@ static errcodes buzzerparser(uint8_t _U_ *par, int32_t _U_ *val){ return ERR_OK; } -static errcodes adcparser(uint8_t _U_ *par, int32_t _U_ *val){ - uint8_t n = PARBASE(*par); +static errcodes adcparser(uint8_t par, int32_t *val){ + uint8_t n = PARBASE(par); if(n > NUMBER_OF_ADC_CHANNELS) return ERR_BADPAR; *val = (int32_t) getADCval(n); return ERR_OK; @@ -55,51 +59,57 @@ static errcodes adcparser(uint8_t _U_ *par, int32_t _U_ *val){ // NON-STANDARD COMMAND!!!!!!! // errcode == keystate, value = last time!!!! -static errcodes buttonsparser(uint8_t _U_ *par, int32_t _U_ *val){ -#if BTNSNO > 4 -#error "change the code!!!" -#endif - uint8_t n = PARBASE(*par); - if(n >= BTNSNO){ - *par = CANMESG_NOPAR; // the only chance to understand error +static errcodes buttonsparser(uint8_t par, int32_t *val){ + uint8_t n = PARBASE(par); + if(n > BTNSNO-1){ + par = CANMESG_NOPAR; // the only chance to understand error return ERR_BADPAR; } return (uint8_t) keystate(n, (uint32_t*)val); } -static errcodes eswparser(uint8_t _U_ *par, int32_t _U_ *val){ - uint8_t n = PARBASE(*par); - if(n > ESWNO-1) return ERR_BADPAR; +// if N > amount of esw, return all (by bytes) +static errcodes eswparser(uint8_t par, int32_t *val){ +#if ESWNO > 4 +#error "change the code!!!" +#endif + uint8_t n = PARBASE(par); + if(n > ESWNO-1){ // all + uint8_t *arr = (uint8_t*)val; + for(int i = 0; i < ESWNO; ++i) + *arr++ = ESW_state(i); + return ERR_OK; + } *val = (int32_t)ESW_state(n); return ERR_OK; } -static errcodes mcutparser(uint8_t _U_ *par, int32_t _U_ *val){ +static errcodes mcutparser(uint8_t _U_ par, int32_t *val){ *val = getMCUtemp(); return ERR_OK; } -static errcodes mcuvddparser(uint8_t _U_ *par, int32_t _U_ *val){ +static errcodes mcuvddparser(uint8_t _U_ par, int32_t *val){ *val = getVdd(); return ERR_OK; } -static errcodes resetparser(uint8_t _U_ *par, int32_t _U_ *val){ +static errcodes resetparser(uint8_t _U_ par, int32_t _U_ *val){ NVIC_SystemReset(); return ERR_OK; } -static errcodes timeparser(uint8_t _U_ *par, int32_t _U_ *val){ +static errcodes timeparser(uint8_t _U_ par, int32_t *val){ *val = Tms; return ERR_OK; } -static errcodes pwmparser(uint8_t _U_ *par, int32_t _U_ *val){ - if(PARBASE(*par) > PWMCHMAX && *par != CANMESG_NOPAR) return ERR_BADPAR; +static errcodes pwmparser(uint8_t par, int32_t *val){ + if(PARBASE(par) > PWMCHMAX && par != CANMESG_NOPAR) return ERR_BADPAR; #if PWMCHMAX != 0 #error "change the code!!!" #endif - if(ISSETTER(*par)){ + if(ISSETTER(par)){ if(*val < 0 || *val > PWMMAX) return ERR_BADVAL; PWMset((uint32_t)*val); } @@ -107,12 +117,65 @@ static errcodes pwmparser(uint8_t _U_ *par, int32_t _U_ *val){ return ERR_OK; } -static errcodes extparser(uint8_t _U_ *par, int32_t _U_ *val){ + +TRUE_INLINE void setextpar(uint8_t val, uint8_t i){ + switch(val){ + case 0: + EXT_CLEAR(i); + break; + case 1: + EXT_SET(i); + break; + default: + EXT_TOGGLE(i); + } +} +// if `par` is absent, set/get all values in subsequent bytes +// 1 - external signal high, 0 - low +// commands: 0 - reset, 1 - set, !!!!other - toggle!!!! +static errcodes extparser(uint8_t par, int32_t *val){ +#if EXTNO > 4 +#error "change the code!!!" +#endif + uint8_t n = PARBASE(par); + SEND("par="); printu(par); + SEND(", n="); bufputchar('0'+n); newline(); + if(n > EXTNO-1){ // all + SEND("ALL\n"); + uint8_t *arr = (uint8_t*)val; + if(ISSETTER(par)){ + for(int i = 0; i < EXTNO; ++i) + setextpar(arr[i], i); + } + for(int i = 0; i < EXTNO; ++i){ + arr[i] = EXT_CHK(i); + } + return ERR_OK; + } + if(ISSETTER(par)) + setextpar((uint8_t)*val, n); + *val = (int32_t) EXT_CHK(n); return ERR_OK; } +static errcodes saveconfparser(uint8_t _U_ par, int32_t _U_ *val){ + if(store_userconf()) return ERR_CANTRUN; + return ERR_OK; +} + +#if 0 +typedef struct __attribute__((packed, aligned(4))){ + uint16_t microsteps; // microsteps amount per step + uint16_t accdecsteps; // amount of steps need for full acceleration/deceleration cycle + uint16_t motspd; // max motor speed (steps per second) + uint32_t maxsteps; // maximal amount of steps from ESW0 to EWS3 + defflags_t defflags; // default flags +} user_conf; +#endif + + /* -static CAN_errcodes parser(const uint8_t _U_ *par, const int32_t _U_ *val){ +static CAN_errcodes parser(const uint8_t _U_ par, const int32_t _U_ *val){ return CANERR_OK; }*/ @@ -130,4 +193,6 @@ const commands cmdlist[CMD_AMOUNT] = { [CMD_TIMEFROMSTART] = {"time", timeparser, "get time from start"}, [CMD_PWM] = {"pwm", pwmparser, "pwm value"}, [CMD_EXT] = {"ext", extparser, "external outputs"}, + [CMD_SAVECONF] = {"saveconf", saveconfparser, "save current configuration"}, }; + diff --git a/F0-nolib/3steppersLB/commonproto.h b/F0-nolib/3steppersLB/commonproto.h index eec86b7..385ae5b 100644 --- a/F0-nolib/3steppersLB/commonproto.h +++ b/F0-nolib/3steppersLB/commonproto.h @@ -24,7 +24,9 @@ #include "can.h" +#ifndef _U_ #define _U_ __attribute__((unused)) +#endif // message have no parameter #define CANMESG_NOPAR (127) @@ -47,7 +49,7 @@ typedef enum{ // if(par &0x80) it is setter, if not - getter // if par == 0x127 it means absense of parameter!!! // @return CANERR_OK (0) if OK or error code -typedef errcodes (*fpointer)(uint8_t *par, int32_t *val); +typedef errcodes (*fpointer)(uint8_t par, int32_t *val); typedef struct{ const char *command; // text command (up to 65536 commands) @@ -68,7 +70,9 @@ enum{ ,CMD_TIMEFROMSTART // get time from start ,CMD_PWM // PWM value ,CMD_EXT // value on EXTx outputs - ,CMD_AMOUNT // amount of CANBUS commands, pure USB commands coming after it + ,CMD_SAVECONF // save configuration + // should be the last: + ,CMD_AMOUNT // amount of common commands }; extern const commands cmdlist[CMD_AMOUNT]; diff --git a/F0-nolib/3steppersLB/flash.c b/F0-nolib/3steppersLB/flash.c index dd7c3d7..b7a091c 100644 --- a/F0-nolib/3steppersLB/flash.c +++ b/F0-nolib/3steppersLB/flash.c @@ -26,20 +26,23 @@ #include "flash.h" #include "strfunct.h" +extern const uint32_t __varsstart, _BLOCKSIZE; + +static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE; // max amount of Config records stored (will be recalculate in flashstorage_init() -static uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf); +static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here #define USERCONF_INITIALIZER { \ .userconf_sz = sizeof(user_conf) \ - ,.defflags.reverse = 0 \ ,.CANspeed = 100 \ - ,.microsteps = 16 \ - ,.accdecsteps = 25 \ - ,.motspd = 1000 \ - ,.maxsteps = 50000 \ + ,.CANID = 0xaa \ + ,.microsteps = {32, 32, 32} \ + ,.accdecsteps = {25, 25, 25} \ + ,.maxspd = {1000, 1000, 1000} \ + ,.maxsteps = {50000, 50000, 50000} \ + ,.motflags = {{0},{0},{0}} \ } - static int erase_flash(const void*, const void*); static int write2flash(const void*, const void*, uint32_t); // don't write `static` here, or get error: @@ -83,7 +86,7 @@ static int binarySearch(int r, const uint8_t *start, int stor_size){ */ void flashstorage_init(){ if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ - uint32_t flsz = FLASH_SIZE * 1024; // size in bytes + uint32_t flsz = FLASH_SIZE * blocksize; // size in bytes flsz -= (uint32_t)(&__varsstart) - FLASH_BASE; maxCnum = flsz / sizeof(user_conf); } @@ -147,13 +150,13 @@ static int erase_flash(const void *start, const void *end){ uint32_t nblocks = 1, flsz = 0; if(!end){ // erase all remaining if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ - flsz = FLASH_SIZE * 1024; // size in bytes + flsz = FLASH_SIZE * blocksize; // size in bytes flsz -= (uint32_t)start - FLASH_BASE; } }else{ // erase a part flsz = (uint32_t)end - (uint32_t)start; } - nblocks = flsz / FLASH_BLOCK_SIZE; + nblocks = flsz / blocksize; if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1; for(uint32_t i = 0; i < nblocks; ++i){ IWDG->KR = IWDG_REFRESH; @@ -177,7 +180,7 @@ static int erase_flash(const void *start, const void *end){ /* (5) Clear EOP flag by software by writing EOP at 1 */ /* (6) Reset the PER Bit to disable the page erase */ FLASH->CR |= FLASH_CR_PER; /* (1) */ - FLASH->AR = (uint32_t)Flash_Data + i*FLASH_BLOCK_SIZE; /* (2) */ + FLASH->AR = (uint32_t)Flash_Data + i*blocksize; /* (2) */ FLASH->CR |= FLASH_CR_STRT; /* (3) */ while(!(FLASH->SR & FLASH_SR_EOP)); FLASH->SR |= FLASH_SR_EOP; /* (5)*/ @@ -191,16 +194,32 @@ static int erase_flash(const void *start, const void *end){ return ret; } -void dump_userconf(){ - SEND("userconf_addr="); printuhex((uint32_t)Flash_Data); - SEND("\nuserconf_sz="); printu(the_conf.userconf_sz); - SEND("\nCANspeed="); printu(the_conf.CANspeed); - SEND("\nmicrosteps="); printu(the_conf.microsteps); - SEND("\naccdecsteps="); printu(the_conf.accdecsteps); - SEND("\nmotspd="); printu(the_conf.motspd); - SEND("\nmaxsteps="); printu(the_conf.maxsteps); - //flags - SEND("\nreverse="); bufputchar('0' + the_conf.defflags.reverse); +void dump_userconf(_U_ char *txt){ +#ifdef EBUG + SEND("flashsize="); printu(FLASH_SIZE); bufputchar('*'); + printu(blocksize); bufputchar('='); printu(FLASH_SIZE*blocksize); newline(); - sendbuf(); +#endif + SEND("userconf_addr="); printuhex((uint32_t)Flash_Data); + SEND("\nuserconf_idx="); printi(currentconfidx); + SEND("\nuserconf_sz="); printu(the_conf.userconf_sz); + SEND("\ncanspeed="); printu(the_conf.CANspeed); + SEND("\ncanid="); printu(the_conf.CANID); + // motors' data + for(int i = 0; i < MOTORSNO; ++i){ + char cur = '0' + i; +#define PROPNAME(nm) do{newline(); SEND(nm); bufputchar(cur); bufputchar('=');}while(0) + PROPNAME("reverse"); + bufputchar('0' + the_conf.motflags[i].reverse); + PROPNAME("microsteps"); + printu(the_conf.microsteps[i]); + PROPNAME("accdecsteps"); + printu(the_conf.accdecsteps[i]); + PROPNAME("maxspeed"); + printu(the_conf.maxspd[i]); + PROPNAME("maxsteps"); + printu(the_conf.maxsteps[i]); +#undef PROPNAME + } + NL(); } diff --git a/F0-nolib/3steppersLB/flash.h b/F0-nolib/3steppersLB/flash.h index 9643e2d..bdc613d 100644 --- a/F0-nolib/3steppersLB/flash.h +++ b/F0-nolib/3steppersLB/flash.h @@ -26,34 +26,42 @@ #include "hardware.h" -#define FLASH_BLOCK_SIZE (1024) -#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC) +#ifndef _U_ +#define _U_ __attribute__((unused)) +#endif + + +// register with flash size (in blocks) +#ifndef FLASH_SIZE_REG +blocksizeASH_SIZE_REG ((uint32_t)0x1FFFF7CC) +#endif + #define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG) +// motor flags typedef struct{ uint8_t reverse : 1; -} defflags_t; +} motflags_t; /* * struct to save user configurations */ typedef struct __attribute__((packed, aligned(4))){ - uint16_t userconf_sz; // "magick number" - uint32_t maxsteps; // maximal amount of steps from ESW0 to EWS3 - uint16_t CANspeed; // default CAN speed - uint16_t CANID; // identifier - uint16_t microsteps; // microsteps amount per step - uint16_t accdecsteps; // amount of steps need for full acceleration/deceleration cycle - uint16_t motspd; // max motor speed (steps per second) - defflags_t defflags; // default flags + uint16_t userconf_sz; // "magick number" + uint16_t CANspeed; // default CAN speed + uint16_t CANID; // identifier + uint16_t microsteps[MOTORSNO]; // microsteps amount per step + uint16_t accdecsteps[MOTORSNO]; // amount of steps need for full acceleration/deceleration cycle + uint16_t maxspd[MOTORSNO]; // max motor speed (steps per second) + uint32_t maxsteps[MOTORSNO]; // maximal amount of steps from ESW0 to EWS3 + motflags_t motflags[MOTORSNO]; // motor's flags } user_conf; extern user_conf the_conf; // global user config (read from FLASH to RAM) // data from ld-file: start address of storage -extern const uint32_t __varsstart; void flashstorage_init(); int store_userconf(); -void dump_userconf(); +void dump_userconf(_U_ char *txt); #endif // __FLASH_H__ diff --git a/F0-nolib/3steppersLB/hardware.c b/F0-nolib/3steppersLB/hardware.c index bc59582..031e51e 100644 --- a/F0-nolib/3steppersLB/hardware.c +++ b/F0-nolib/3steppersLB/hardware.c @@ -18,6 +18,7 @@ #include "hardware.h" #include "can.h" +#include "steppers.h" // Buttons: PA10, PA13, PA14, PA15, pullup (0 active) volatile GPIO_TypeDef *BTNports[BTNSNO] = {GPIOA, GPIOA, GPIOA, GPIOA}; @@ -75,21 +76,50 @@ void iwdg_setup(){ IWDG->KR = IWDG_REFRESH; /* (6) */ } -void timers_setup(){ -#if 0 - // TIM1 channels 1..3 - PWM output - RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable clocking - TIM1->PSC = 9; // F=48/10 = 4.8MHz - TIM1->ARR = 255; // PWM frequency = 4800/256 = 18.75kHz +// motor's PWM +static void setup_mpwm(TIM_TypeDef *TIM){ + TIM->PSC = 999; // 48kHz + TIM->ARR = 1000; // starting ARR value // PWM mode 1 (OCxM = 110), preload enable - TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | + TIM->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive + TIM->CCER = TIM_CCER_CC1E; // turn it on, active high + TIM->CCR1 = 1; // 20.8us for pulse duration, according to datasheet 1.9us is enough + TIM->BDTR |= TIM_BDTR_MOE; // enable main output + TIM->CR1 |= TIM_CR1_CEN; // enable timer + TIM->EGR |= TIM_EGR_UG; // force update generation + TIM->DIER = TIM_DIER_CC1IE; // allow CC interrupt (we should count steps) +} +/* +static void setup_enc(TIM_TypeDef *TIM, uint16_t arrval){ + TIM->PSC = 9; // F=48/10 = 4.8MHz + TIM->ARR = arrval; // PWM frequency = 4800/256 = 18.75kHz + // PWM mode 1 (OCxM = 110), preload enable + TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE; - TIM1->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE; - TIM1->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E; // active high (CC1P=0), enable outputs - TIM1->BDTR |= TIM_BDTR_MOE; // enable main output - TIM1->CR1 |= TIM_CR1_CEN; // enable timer - TIM1->EGR |= TIM_EGR_UG; // force update generation -#endif + TIM->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE; + TIM->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E; // active high (CC1P=0), enable outputs + TIM->BDTR |= TIM_BDTR_MOE; // enable main output + TIM->CR1 |= TIM_CR1_CEN; // enable timer + TIM->EGR |= TIM_EGR_UG; // force update generation +}*/ + +// timers 14,15,16,17 - PWM@ch1, 1,2,3 - encoders @ ch1/2 +void timers_setup(){ + RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM15EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_TIM17EN; // enable clocking + setup_mpwm(TIM14); + setup_mpwm(TIM15); + setup_mpwm(TIM16); + // setup PWM @ TIM17 + TIM17->PSC = 5; // 8MHz for 31kHz PWM + TIM17->ARR = 254; // ARR for 8-bit PWM + TIM17->BDTR |= TIM_BDTR_MOE; // enable main output + TIM17->CCER = TIM_CCER_CC1E; // enable PWM output + TIM17->CR1 |= TIM_CR1_CEN; // enable timer + ; + NVIC_EnableIRQ(TIM14_IRQn); + NVIC_EnableIRQ(TIM15_IRQn); + NVIC_EnableIRQ(TIM16_IRQn); } // pause in milliseconds for some purposes @@ -98,6 +128,10 @@ void pause_ms(uint32_t pause){ while(Tms < Tnxt) nop(); } +#ifndef STM32F072xB +#warning "Only F072 can jump to bootloader" +#endif + void Jump2Boot(){ // for STM32F072 void (*SysMemBootJump)(void); volatile uint32_t addr = 0x1FFFC800; @@ -125,3 +159,18 @@ void Jump2Boot(){ // for STM32F072 SysMemBootJump(); } + +// count steps @tim 14/15/16 +static void stp_isr(TIM_TypeDef *TIM, int i){ + ++steps[i]; // count steps + TIM->SR = 0; +} +void tim14_isr(){ + stp_isr(TIM14, 0); +} +void tim15_isr(){ + stp_isr(TIM15, 1); +} +void tim16_isr(){ + stp_isr(TIM16, 2); +} diff --git a/F0-nolib/3steppersLB/steppers.bin b/F0-nolib/3steppersLB/steppers.bin index a456f65c31ff3b1b94cf02969dbc054284c5d42e..79b45e5c8dbed7cd628ca2c18a86a26786a1c4a9 100755 GIT binary patch delta 6915 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 Z*@s1h6U*;n9L!!g34TC_UlVMp;a~JlJ~aRU delta 5005 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 M7eD!kLQ<1|0W$`$2><{9 diff --git a/F0-nolib/3steppersLB/steppers.c b/F0-nolib/3steppersLB/steppers.c new file mode 100644 index 0000000..21fcab2 --- /dev/null +++ b/F0-nolib/3steppersLB/steppers.c @@ -0,0 +1,23 @@ +/* + * This file is part of the 3steppers project. + * Copyright 2021 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "hardware.h" +#include "steppers.h" + +int32_t steps[MOTORSNO] = {0,0,0}; + diff --git a/F0-nolib/3steppersLB/steppers.h b/F0-nolib/3steppersLB/steppers.h new file mode 100644 index 0000000..895e84a --- /dev/null +++ b/F0-nolib/3steppersLB/steppers.h @@ -0,0 +1,27 @@ +/* + * This file is part of the 3steppers project. + * Copyright 2021 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#ifndef STEPPERS_H__ +#define STEPPERS_H__ + +#include + +extern int32_t steps[]; + +#endif // STEPPERS_H__ diff --git a/F0-nolib/3steppersLB/strfunct.c b/F0-nolib/3steppersLB/strfunct.c index 350314f..ab5ced3 100644 --- a/F0-nolib/3steppersLB/strfunct.c +++ b/F0-nolib/3steppersLB/strfunct.c @@ -145,11 +145,9 @@ static void sendCANcommand(char *txt){ static void CANini(char *txt){ txt = omit_spaces(txt); int32_t N; + if(!txt) goto eofunc; char *n = getnum(txt, &N); - if(txt == n){ - SEND("No speed given"); - return; - } + if(txt == n) goto eofunc; if(N < 50){ SEND("Lowest speed is 50kbps"); return; @@ -157,9 +155,10 @@ static void CANini(char *txt){ SEND("Highest speed is 3000kbps"); return; } + the_conf.CANspeed = (uint16_t)N; CAN_reinit((uint16_t)N); - SEND("Reinit CAN bus with speed "); - printu(N); SEND("kbps"); +eofunc: + SEND("canspeed="); printu(the_conf.CANspeed); NL(); } static void addIGN(char *txt){ @@ -348,7 +347,22 @@ static void add_filter(char *str){ printu(nfilt); SEND(" parameters"); } -void getcanid(_U_ char *txt){ +void canid(char *txt){ + if(txt && *txt){ + int good = FALSE; + char *eq = getchr(txt, '='); + if(eq){ + eq = omit_spaces(eq+1); + if(eq){ + int32_t N; + if(eq != getnum(eq, &N) && N > -1 && N < 0xfff){ + the_conf.CANID = (uint16_t)N; + good = TRUE; + } + } + } + if(!good) SEND("CANID setter format: `canid=ID`, ID is 11bit\n"); + } SEND("canid="); printuhex(the_conf.CANID); } @@ -384,12 +398,13 @@ const speccommands scmdlist[] = { {"dfu", bootldr, "activate DFU mode"}, {"filter", add_filter, "add/modify filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]"}, {"canspeed", CANini, "CAN bus speed"}, - {"canid", getcanid, "read CAN ID"}, + {"canid", canid, "get/set CAN ID"}, {"listfilters", list_filters, "list all active filters"}, {"ignbuf", print_ign_buf, "print ignore buffer"}, {"pause", inpause, "pause IN packets displaying"}, {"resume", inresume, "resume IN packets displaying"}, {"send", sendCANcommand, "send data over CAN: send ID byte0 .. byteN"}, + {"dumpconf", dump_userconf, "dump current configuration"}, {NULL, NULL, NULL} }; @@ -470,10 +485,12 @@ void cmd_parser(char *txt){ } } // here we got command & ppar/pval -> call CMD - errcodes retcode = cmdlist[idx].function(&par, &val); + errcodes retcode = cmdlist[idx].function(par, &val); SEND(cmd); - if(par != CANMESG_NOPAR) printu(par & 0x7f); + par &= 0x7f; + if(par != CANMESG_NOPAR) printu(par); bufputchar('='); printi(val); + SEND(" ("); printuhex((uint32_t)val); bufputchar(')'); if(ERR_OK != retcode){ SEND("\nERRCODE="); printu(retcode); diff --git a/F0-nolib/Snippets/Flash_EEPROM/flash.c b/F0-nolib/Snippets/Flash_EEPROM/flash.c index 5e6525c..eea44e7 100644 --- a/F0-nolib/Snippets/Flash_EEPROM/flash.c +++ b/F0-nolib/Snippets/Flash_EEPROM/flash.c @@ -40,8 +40,12 @@ #include "proto.h" // printout #include // memcpy +extern const uint32_t __varsstart, _BLOCKSIZE; +// ld-script shoul include _BLOCKSIZE = 1024; (or 2048) +static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE; + // max amount of Config records stored (will be recalculate in flashstorage_init() -static uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf); +static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here #define USERCONF_INITIALIZER { \ .userconf_sz = sizeof(user_conf) \ @@ -92,7 +96,7 @@ static int binarySearch(int r, const uint8_t *start, int stor_size){ */ void flashstorage_init(){ if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ - uint32_t flsz = FLASH_SIZE * 1024; // size in bytes + uint32_t flsz = FLASH_SIZE * blocksize; // size in bytes flsz -= (uint32_t)(&__varsstart) - FLASH_BASE; maxCnum = flsz / sizeof(user_conf); //SEND("flsz="); printu(flsz); @@ -161,13 +165,13 @@ static int erase_flash(const void *start, const void *end){ uint32_t nblocks = 1, flsz = 0; if(!end){ // erase all remaining if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ - flsz = FLASH_SIZE * 1024; // size in bytes + flsz = FLASH_SIZE * blocksize; // size in bytes flsz -= (uint32_t)start - FLASH_BASE; } }else{ // erase a part flsz = (uint32_t)end - (uint32_t)start; } - nblocks = flsz / FLASH_BLOCK_SIZE; + nblocks = flsz / blocksize; if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1; for(uint32_t i = 0; i < nblocks; ++i){ #ifdef EBUG @@ -194,7 +198,7 @@ static int erase_flash(const void *start, const void *end){ /* (5) Clear EOP flag by software by writing EOP at 1 */ /* (6) Reset the PER Bit to disable the page erase */ FLASH->CR |= FLASH_CR_PER; /* (1) */ - FLASH->AR = (uint32_t)Flash_Data + i*FLASH_BLOCK_SIZE; /* (2) */ + FLASH->AR = (uint32_t)Flash_Data + i*blocksize; /* (2) */ FLASH->CR |= FLASH_CR_STRT; /* (3) */ while(!(FLASH->SR & FLASH_SR_EOP)); FLASH->SR |= FLASH_SR_EOP; /* (5)*/ @@ -210,6 +214,11 @@ static int erase_flash(const void *start, const void *end){ } void dump_userconf(){ +#ifdef EBUG + SEND("flashsize="); printu(FLASH_SIZE); bufputchar('*'); + printu(blocksize); bufputchar('='); printu(FLASH_SIZE*blocksize); + newline(); +#endif SEND("userconf_addr="); printuhex((uint32_t)Flash_Data); SEND("\nuserconf_sz="); printu(the_conf.userconf_sz); SEND("\nflags="); printuhex(the_conf.defflags); diff --git a/F0-nolib/Snippets/Flash_EEPROM/flash.h b/F0-nolib/Snippets/Flash_EEPROM/flash.h index dcccaac..9fdc3da 100644 --- a/F0-nolib/Snippets/Flash_EEPROM/flash.h +++ b/F0-nolib/Snippets/Flash_EEPROM/flash.h @@ -26,22 +26,26 @@ #include "hardware.h" -#define FLASH_BLOCK_SIZE (1024) -#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC) +#ifndef FLASH_SIZE_REG +blocksizeASH_SIZE_REG ((uint32_t)0x1FFFF7CC) +#endif #define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG) +typedef struct{ + uint8_t flag1 : 1; + uint8_t flag2 : 1; //... +} defflags_t; + /* * struct to save user configurations */ typedef struct __attribute__((packed, aligned(4))){ uint16_t userconf_sz; // "magick number" - uint8_t defflags; // default flags uint16_t CANspeed; // default CAN speed + defflags_t defflags; // default flags } user_conf; extern user_conf the_conf; // global user config (read from FLASH to RAM) -// data from ld-file: start address of storage -extern const uint32_t __varsstart; void flashstorage_init(); int store_userconf(); diff --git a/F0-nolib/Snippets/printuhex.c b/F0-nolib/Snippets/printuhex.c index c41f000..0a56cf8 100644 --- a/F0-nolib/Snippets/printuhex.c +++ b/F0-nolib/Snippets/printuhex.c @@ -11,3 +11,26 @@ void printuhex(uint32_t val){ } } } + +// print 32bit unsigned int +void printu(uint32_t val){ + char buf[11], *bufptr = &buf[10]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + register uint32_t o = val; + val /= 10; + *(--bufptr) = (o - 10*val) + '0'; + } + } + addtobuf(bufptr); +} +void printi(int32_t val){ + if(val < 0){ + val = -val; + bufputchar('-'); + } + printu((uint32_t)val); +} diff --git a/F0-nolib/inc/Fx/flash_size_reg.h b/F0-nolib/inc/Fx/flash_size_reg.h new file mode 100644 index 0000000..15bcf3b --- /dev/null +++ b/F0-nolib/inc/Fx/flash_size_reg.h @@ -0,0 +1,10 @@ +#define STM32F0_FlashAddr 0x1FFFF7CC // Базовый адрес емкости флэш-памяти STM32F0 +#define STM32F1_FlashAddr 0x1FFFF7E0 // Базовый адрес емкости флэш-памяти STM32F1 +#define STM32F2_FlashAddr 0x1FFF7A22 // Базовый адрес емкости флэш-памяти STM32F2 +#define STM32F3_FlashAddr 0x1FFFF7CC // Базовый адрес емкости флэш-памяти STM32F3 +#define STM32F4_FlashAddr 0x1FFF7A22 // Базовый адрес емкости флэш-памяти STM32F4 +#define STM32F7_FlashAddr 0x1FF0F442 // Базовый адрес флэш-памяти STM32F7 +#define STM32L0_FlashAddr 0x1FF8007C // Базовый адрес емкости флэш-памяти STM32L0 +#define STM32L1_FlashAddr 0x1FF8004C // Базовый адрес емкости флэш-памяти STM32L1 +#define STM32L4_FlashAddr 0x1FFF75E0 // Базовый адрес емкости флэш-памяти STM32L4 +#define STM32H7_FlashAddr 0x1FF0F442 // Базовый адрес флэш-памяти STM32H7 diff --git a/F0-nolib/inc/Fx/stm32f0.h b/F0-nolib/inc/Fx/stm32f0.h index 55fcffe..e838d9f 100644 --- a/F0-nolib/inc/Fx/stm32f0.h +++ b/F0-nolib/inc/Fx/stm32f0.h @@ -257,9 +257,10 @@ TRUE_INLINE void StartHSI48(){ /****************** FLASH Keys **********************************************/ -#define RDP_Key ((uint16_t)0x00A5) -#define FLASH_KEY1 ((uint32_t)0x45670123) -#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) +#define RDP_Key ((uint16_t)0x00A5) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) +#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC) /************************* ADC *************************/ /* inner termometer calibration values diff --git a/F0-nolib/inc/Fx/stm32f1.h b/F0-nolib/inc/Fx/stm32f1.h index 864ec67..6dc8fea 100644 --- a/F0-nolib/inc/Fx/stm32f1.h +++ b/F0-nolib/inc/Fx/stm32f1.h @@ -190,6 +190,9 @@ IDR - input, ODR - output (or pullups management), #define IWDG_WRITE_ACCESS (uint32_t)(0x00005555) #define IWDG_START (uint32_t)(0x0000CCCC) +// flash size +#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0) + #if 0 /************************* ADC *************************/ diff --git a/F0-nolib/inc/ld/stm32f01234.ld b/F0-nolib/inc/ld/stm32f01234.ld index aaf4995..ea7e2c2 100644 --- a/F0-nolib/inc/ld/stm32f01234.ld +++ b/F0-nolib/inc/ld/stm32f01234.ld @@ -73,7 +73,7 @@ SECTIONS { .myvars : { - . = ALIGN(1024); + . = ALIGN(_BLOCKSIZE); __varsstart = ABSOLUTE(.); KEEP(*(.myvars)); } > rom diff --git a/F0-nolib/inc/ld/stm32f030f.ld b/F0-nolib/inc/ld/stm32f030f.ld index ca27421..2337ab4 100644 --- a/F0-nolib/inc/ld/stm32f030f.ld +++ b/F0-nolib/inc/ld/stm32f030f.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f042k.ld b/F0-nolib/inc/ld/stm32f042k.ld index 2d0454f..1ff1ca1 100644 --- a/F0-nolib/inc/ld/stm32f042k.ld +++ b/F0-nolib/inc/ld/stm32f042k.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f042x6.ld b/F0-nolib/inc/ld/stm32f042x6.ld new file mode 100644 index 0000000..1ff1ca1 --- /dev/null +++ b/F0-nolib/inc/ld/stm32f042x6.ld @@ -0,0 +1,14 @@ +/* Linker script for STM32F042x6, 32K flash, 6K RAM. */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K +} + +PROVIDE(_BLOCKSIZE = 1024); + +/* Include the common ld script. */ +INCLUDE stm32f01234.ld + diff --git a/F0-nolib/inc/ld/stm32f051x8.ld b/F0-nolib/inc/ld/stm32f051x8.ld index 3dc0803..8823955 100644 --- a/F0-nolib/inc/ld/stm32f051x8.ld +++ b/F0-nolib/inc/ld/stm32f051x8.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f0728.ld b/F0-nolib/inc/ld/stm32f0728.ld index 30cbbeb..661a1ce 100644 --- a/F0-nolib/inc/ld/stm32f0728.ld +++ b/F0-nolib/inc/ld/stm32f0728.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f072B.ld b/F0-nolib/inc/ld/stm32f072B.ld index 87bef63..16fb578 100644 --- a/F0-nolib/inc/ld/stm32f072B.ld +++ b/F0-nolib/inc/ld/stm32f072B.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } +_BLOCKSIZE = 2048; + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103x4.ld b/F0-nolib/inc/ld/stm32f103x4.ld index 1170213..b871034 100644 --- a/F0-nolib/inc/ld/stm32f103x4.ld +++ b/F0-nolib/inc/ld/stm32f103x4.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103x6.ld b/F0-nolib/inc/ld/stm32f103x6.ld index 34ffd51..2ec988b 100644 --- a/F0-nolib/inc/ld/stm32f103x6.ld +++ b/F0-nolib/inc/ld/stm32f103x6.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103x8.ld b/F0-nolib/inc/ld/stm32f103x8.ld index b96fc91..73b0f1b 100644 --- a/F0-nolib/inc/ld/stm32f103x8.ld +++ b/F0-nolib/inc/ld/stm32f103x8.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103xB.ld b/F0-nolib/inc/ld/stm32f103xB.ld index 288bd2c..384d684 100644 --- a/F0-nolib/inc/ld/stm32f103xB.ld +++ b/F0-nolib/inc/ld/stm32f103xB.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103xC.ld b/F0-nolib/inc/ld/stm32f103xC.ld index 86badce..9a27c5b 100644 --- a/F0-nolib/inc/ld/stm32f103xC.ld +++ b/F0-nolib/inc/ld/stm32f103xC.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103xD.ld b/F0-nolib/inc/ld/stm32f103xD.ld index 47dc08a..923910c 100644 --- a/F0-nolib/inc/ld/stm32f103xD.ld +++ b/F0-nolib/inc/ld/stm32f103xD.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103xE.ld b/F0-nolib/inc/ld/stm32f103xE.ld index 6777cae..da143de 100644 --- a/F0-nolib/inc/ld/stm32f103xE.ld +++ b/F0-nolib/inc/ld/stm32f103xE.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103xF.ld b/F0-nolib/inc/ld/stm32f103xF.ld index fe149d7..2a52a01 100644 --- a/F0-nolib/inc/ld/stm32f103xF.ld +++ b/F0-nolib/inc/ld/stm32f103xF.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F0-nolib/inc/ld/stm32f103xG.ld b/F0-nolib/inc/ld/stm32f103xG.ld index 0b32b92..5fd0095 100644 --- a/F0-nolib/inc/ld/stm32f103xG.ld +++ b/F0-nolib/inc/ld/stm32f103xG.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f01234.ld b/F1-nolib/inc/ld/stm32f01234.ld index 930bf36..ea7e2c2 100644 --- a/F1-nolib/inc/ld/stm32f01234.ld +++ b/F1-nolib/inc/ld/stm32f01234.ld @@ -73,8 +73,9 @@ SECTIONS { .myvars : { - . = ALIGN(1024); - KEEP(*(.myvars)) + . = ALIGN(_BLOCKSIZE); + __varsstart = ABSOLUTE(.); + KEEP(*(.myvars)); } > rom _ldata = LOADADDR(.data); diff --git a/F1-nolib/inc/ld/stm32f030f.ld b/F1-nolib/inc/ld/stm32f030f.ld index ca27421..2337ab4 100644 --- a/F1-nolib/inc/ld/stm32f030f.ld +++ b/F1-nolib/inc/ld/stm32f030f.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f042k.ld b/F1-nolib/inc/ld/stm32f042k.ld index 2d0454f..1ff1ca1 100644 --- a/F1-nolib/inc/ld/stm32f042k.ld +++ b/F1-nolib/inc/ld/stm32f042k.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f042x6.ld b/F1-nolib/inc/ld/stm32f042x6.ld new file mode 100644 index 0000000..1ff1ca1 --- /dev/null +++ b/F1-nolib/inc/ld/stm32f042x6.ld @@ -0,0 +1,14 @@ +/* Linker script for STM32F042x6, 32K flash, 6K RAM. */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K +} + +PROVIDE(_BLOCKSIZE = 1024); + +/* Include the common ld script. */ +INCLUDE stm32f01234.ld + diff --git a/F1-nolib/inc/ld/stm32f051x8.ld b/F1-nolib/inc/ld/stm32f051x8.ld index 3dc0803..8823955 100644 --- a/F1-nolib/inc/ld/stm32f051x8.ld +++ b/F1-nolib/inc/ld/stm32f051x8.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 8K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f0728.ld b/F1-nolib/inc/ld/stm32f0728.ld index 30cbbeb..661a1ce 100644 --- a/F1-nolib/inc/ld/stm32f0728.ld +++ b/F1-nolib/inc/ld/stm32f0728.ld @@ -7,6 +7,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f072B.ld b/F1-nolib/inc/ld/stm32f072B.ld new file mode 100644 index 0000000..16fb578 --- /dev/null +++ b/F1-nolib/inc/ld/stm32f072B.ld @@ -0,0 +1,14 @@ +/* Linker script for STM32F072xB, 128K flash, 16K RAM. */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} + +_BLOCKSIZE = 2048; + +/* Include the common ld script. */ +INCLUDE stm32f01234.ld + diff --git a/F1-nolib/inc/ld/stm32f103x4.ld b/F1-nolib/inc/ld/stm32f103x4.ld index 1170213..b871034 100644 --- a/F1-nolib/inc/ld/stm32f103x4.ld +++ b/F1-nolib/inc/ld/stm32f103x4.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103x6.ld b/F1-nolib/inc/ld/stm32f103x6.ld index 34ffd51..2ec988b 100644 --- a/F1-nolib/inc/ld/stm32f103x6.ld +++ b/F1-nolib/inc/ld/stm32f103x6.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103x8.ld b/F1-nolib/inc/ld/stm32f103x8.ld index b96fc91..73b0f1b 100644 --- a/F1-nolib/inc/ld/stm32f103x8.ld +++ b/F1-nolib/inc/ld/stm32f103x8.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103xB.ld b/F1-nolib/inc/ld/stm32f103xB.ld index 288bd2c..384d684 100644 --- a/F1-nolib/inc/ld/stm32f103xB.ld +++ b/F1-nolib/inc/ld/stm32f103xB.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103xC.ld b/F1-nolib/inc/ld/stm32f103xC.ld index 86badce..9a27c5b 100644 --- a/F1-nolib/inc/ld/stm32f103xC.ld +++ b/F1-nolib/inc/ld/stm32f103xC.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103xD.ld b/F1-nolib/inc/ld/stm32f103xD.ld index 47dc08a..923910c 100644 --- a/F1-nolib/inc/ld/stm32f103xD.ld +++ b/F1-nolib/inc/ld/stm32f103xD.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103xE.ld b/F1-nolib/inc/ld/stm32f103xE.ld index 6777cae..da143de 100644 --- a/F1-nolib/inc/ld/stm32f103xE.ld +++ b/F1-nolib/inc/ld/stm32f103xE.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103xF.ld b/F1-nolib/inc/ld/stm32f103xF.ld index fe149d7..2a52a01 100644 --- a/F1-nolib/inc/ld/stm32f103xF.ld +++ b/F1-nolib/inc/ld/stm32f103xF.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/F1-nolib/inc/ld/stm32f103xG.ld b/F1-nolib/inc/ld/stm32f103xG.ld index 0b32b92..5fd0095 100644 --- a/F1-nolib/inc/ld/stm32f103xG.ld +++ b/F1-nolib/inc/ld/stm32f103xG.ld @@ -26,6 +26,8 @@ MEMORY ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K } +PROVIDE(_BLOCKSIZE = 1024); + /* Include the common ld script. */ INCLUDE stm32f01234.ld diff --git a/stm32reg.png b/stm32reg.png new file mode 100644 index 0000000000000000000000000000000000000000..c5ca74bee06f3895fd4c549dbe4c19ebea6a55cf GIT binary patch literal 73901 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 b8xZ(^>WW#ZSc(mV00000NkvXXu0mjf0(Ev( literal 0 HcmV?d00001