From ab5f7bc87b10ac14db9120a655757b6ce6da888e Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 21 Feb 2023 11:55:42 +0300 Subject: [PATCH] add some features to 3steppersLB --- F0:F030,F042,F072/3steppersLB/commonproto.c | 8 +- F0:F030,F042,F072/3steppersLB/flash.c | 56 +++--- F0:F030,F042,F072/3steppersLB/hardware.c | 4 +- F0:F030,F042,F072/3steppersLB/hardware.h | 8 + F0:F030,F042,F072/3steppersLB/main.c | 1 - F0:F030,F042,F072/3steppersLB/steppers.bin | Bin 23476 -> 23288 bytes F0:F030,F042,F072/3steppersLB/steppers.c | 15 +- F0:F030,F042,F072/3steppersLB/steppers.cflags | 1 + F0:F030,F042,F072/3steppersLB/steppers.config | 5 + .../3steppersLB/steppers.creator | 1 + .../3steppersLB/steppers.creator.user | 160 ++++++++++++++++++ .../3steppersLB/steppers.cxxflags | 1 + F0:F030,F042,F072/3steppersLB/steppers.files | 24 +++ F0:F030,F042,F072/3steppersLB/steppers.h | 9 + .../3steppersLB/steppers.includes | 6 + F0:F030,F042,F072/3steppersLB/usb.c | 3 +- F0:F030,F042,F072/3steppersLB/usb_lib.c | 4 +- F0:F030,F042,F072/3steppersLB/usb_lib.h | 2 +- F0:F030,F042,F072/3steppersLB/version.inc | 4 +- 19 files changed, 261 insertions(+), 51 deletions(-) create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.cflags create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.config create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.creator create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.creator.user create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.cxxflags create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.files create mode 100644 F0:F030,F042,F072/3steppersLB/steppers.includes diff --git a/F0:F030,F042,F072/3steppersLB/commonproto.c b/F0:F030,F042,F072/3steppersLB/commonproto.c index 76cbb05..b40d885 100644 --- a/F0:F030,F042,F072/3steppersLB/commonproto.c +++ b/F0:F030,F042,F072/3steppersLB/commonproto.c @@ -188,6 +188,7 @@ static errcodes ustepsparser(uint8_t par, int32_t *val){ if(m != 1< PCLK/(MOTORTIM_PSC+1)/(MOTORTIM_ARRMIN+1)) return ERR_BADVAL; the_conf.microsteps[n] = m; + update_stepper(n); } *val = the_conf.microsteps[n]; return ERR_OK; @@ -218,6 +219,7 @@ static errcodes accparser(uint8_t par, int32_t *val){ if(ISSETTER(par)){ if(*val/the_conf.microsteps[n] > ACCELMAXSTEPS || *val < 1) return ERR_BADVAL; the_conf.accel[n] = *val; + update_stepper(n); } *val = the_conf.accel[n]; return ERR_OK; @@ -238,6 +240,7 @@ static errcodes maxspdparser(uint8_t par, int32_t *val){ if(ISSETTER(par)){ if(*val <= the_conf.minspd[n]) return ERR_BADVAL; the_conf.maxspd[n] = getSPD(n, *val); + update_stepper(n); } *val = the_conf.maxspd[n]; return ERR_OK; @@ -248,6 +251,7 @@ static errcodes minspdparser(uint8_t par, int32_t *val){ if(ISSETTER(par)){ if(*val >= the_conf.maxspd[n]) return ERR_BADVAL; the_conf.minspd[n] = getSPD(n, *val); + update_stepper(n); } *val = the_conf.minspd[n]; return ERR_OK; @@ -274,7 +278,7 @@ static errcodes encrevparser(uint8_t par, int32_t *val){ if(ISSETTER(par)){ if(*val < 1 || *val > MAXENCREV) return ERR_BADVAL; the_conf.encrev[n] = *val; - enctimers[n]->ARR = *val; + update_stepper(n); } *val = the_conf.encrev[n]; return ERR_OK; @@ -284,6 +288,7 @@ static errcodes motflagsparser(uint8_t par, int32_t *val){ uint8_t n; CHECKN(n, par); if(ISSETTER(par)){ the_conf.motflags[n] = *((motflags_t*)val); + update_stepper(n); } *(motflags_t*)val = the_conf.motflags[n]; return ERR_OK; @@ -295,6 +300,7 @@ static errcodes eswreactparser(uint8_t par, int32_t *val){ if(ISSETTER(par)){ if(*val < 0 || *val > ESW_AMOUNT-1) return ERR_BADVAL; the_conf.ESW_reaction[n] = *val; + update_stepper(n); } // *val = the_conf.ESW_reaction[n]; *val = geteswreact(n); diff --git a/F0:F030,F042,F072/3steppersLB/flash.c b/F0:F030,F042,F072/3steppersLB/flash.c index 9f958cf..43a1d20 100644 --- a/F0:F030,F042,F072/3steppersLB/flash.c +++ b/F0:F030,F042,F072/3steppersLB/flash.c @@ -123,10 +123,7 @@ static int write2flash(const void *start, const void *wrdata, uint32_t stor_size FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2; } - while (FLASH->SR & FLASH_SR_BSY); - if(FLASH->SR & FLASH_SR_WRPRTERR){ - return 1; // write protection - } + while (FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags FLASH->CR |= FLASH_CR_PG; const uint16_t *data = (const uint16_t*) wrdata; @@ -135,14 +132,14 @@ static int write2flash(const void *start, const void *wrdata, uint32_t stor_size for (i = 0; i < count; ++i){ IWDG->KR = IWDG_REFRESH; *(volatile uint16_t*)(address + i) = data[i]; - while (FLASH->SR & FLASH_SR_BSY); - if(FLASH->SR & FLASH_SR_PGERR){ + while (FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + if(FLASH->SR & FLASH_SR_PGERR){ + SEND("Prog err\n"); ret = 1; // program error - meet not 0xffff break; - }else while (!(FLASH->SR & FLASH_SR_EOP)); + } FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; } - FLASH->CR |= FLASH_CR_LOCK; // lock it back FLASH->CR &= ~(FLASH_CR_PG); return ret; } @@ -166,39 +163,26 @@ static int erase_flash(const void *start, const void *end){ } nblocks = flsz / blocksize; if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1; + if((FLASH->CR & FLASH_CR_LOCK) != 0){ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } + while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; + FLASH->CR |= FLASH_CR_PER; for(uint32_t i = 0; i < nblocks; ++i){ - IWDG->KR = IWDG_REFRESH; - /* (1) Wait till no operation is on going */ - /* (2) Clear error & EOP bits */ - /* (3) Check that the Flash is unlocked */ - /* (4) Perform unlock sequence */ - while ((FLASH->SR & FLASH_SR_BSY) != 0){} /* (1) */ - FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; /* (2) */ - /* if (FLASH->SR & FLASH_SR_EOP){ - FLASH->SR |= FLASH_SR_EOP; - }*/ - if ((FLASH->CR & FLASH_CR_LOCK) != 0){ /* (3) */ - FLASH->KEYR = FLASH_KEY1; /* (4) */ - FLASH->KEYR = FLASH_KEY2; - } - /* (1) Set the PER bit in the FLASH_CR register to enable page erasing */ - /* (2) Program the FLASH_AR register to select a page to erase */ - /* (3) Set the STRT bit in the FLASH_CR register to start the erasing */ - /* (4) Wait until the EOP flag in the FLASH_SR register set */ - /* (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*blocksize; /* (2) */ - FLASH->CR |= FLASH_CR_STRT; /* (3) */ - while(!(FLASH->SR & FLASH_SR_EOP)); - FLASH->SR |= FLASH_SR_EOP; /* (5)*/ - if(FLASH->SR & FLASH_SR_WRPRTERR){ /* Check Write protection error */ + SEND("Erase block #"); printu(i); newline(); + FLASH->AR = (uint32_t)Flash_Data + i * blocksize; + FLASH->CR |= FLASH_CR_STRT; + while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + FLASH->SR |= FLASH_SR_EOP; + if(FLASH->SR & FLASH_SR_WRPRTERR){ ret = 1; - FLASH->SR |= FLASH_SR_WRPRTERR; /* Clear the flag by software by writing it at 1*/ + FLASH->SR |= FLASH_SR_WRPRTERR; break; } - FLASH->CR &= ~FLASH_CR_PER; /* (6) */ } + FLASH->CR &= ~FLASH_CR_PER; return ret; } diff --git a/F0:F030,F042,F072/3steppersLB/hardware.c b/F0:F030,F042,F072/3steppersLB/hardware.c index 486ac86..dd38f81 100644 --- a/F0:F030,F042,F072/3steppersLB/hardware.c +++ b/F0:F030,F042,F072/3steppersLB/hardware.c @@ -24,7 +24,7 @@ // Buttons: PA10, PA13, PA14, PA15, pullup (0 active) volatile GPIO_TypeDef *BTNports[BTNSNO] = {GPIOA, GPIOA, GPIOA, GPIOA}; const uint32_t BTNpins[BTNSNO] = {1<<10, 1<<13, 1<<14, 1<<15}; -// Limit switches: PC13, PC14, PC15, pulldown (0 active) +// Limit switches: PC13, PC14, PC15, pullup (0 active) volatile GPIO_TypeDef *ESWports[ESWNO] = {GPIOC, GPIOC, GPIOC}; const uint32_t ESWpins[ESWNO] = {1<<13, 1<<14, 1<<15}; // external GPIO @@ -55,7 +55,7 @@ void gpio_setup(void){ GPIO_MODER_MODER10_O | GPIO_MODER_MODER11_O | GPIO_MODER_MODER12_O | GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O | GPIO_MODER_MODER15_O ; GPIOB->AFR[0] = (1 << (4*4)) | (1 << (5*4)) | (1 << (6*4)) | (1 << (7*4)); - GPIOC->PUPDR = GPIO_PUPDR13_PD | GPIO_PUPDR14_PD | GPIO_PUPDR15_PD; + GPIOC->PUPDR = GPIO_PUPDR13_PU | GPIO_PUPDR14_PU | GPIO_PUPDR15_PU; GPIOF->MODER = GPIO_MODER_MODER0_O; } diff --git a/F0:F030,F042,F072/3steppersLB/hardware.h b/F0:F030,F042,F072/3steppersLB/hardware.h index 267a895..56dbd8b 100644 --- a/F0:F030,F042,F072/3steppersLB/hardware.h +++ b/F0:F030,F042,F072/3steppersLB/hardware.h @@ -22,6 +22,14 @@ #include +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + // PCLK frequency #ifndef PCLK #define PCLK (48000000) diff --git a/F0:F030,F042,F072/3steppersLB/main.c b/F0:F030,F042,F072/3steppersLB/main.c index 5212cc0..36f9286 100644 --- a/F0:F030,F042,F072/3steppersLB/main.c +++ b/F0:F030,F042,F072/3steppersLB/main.c @@ -25,7 +25,6 @@ #include "steppers.h" #include "strfunct.h" #include "usb.h" -#include "usb_lib.h" volatile uint32_t Tms = 0; diff --git a/F0:F030,F042,F072/3steppersLB/steppers.bin b/F0:F030,F042,F072/3steppersLB/steppers.bin index 97db3a95e3491af1aef6da5ec59c9eb35d153b0b..320958b9793a4d33f288b9f5b107d9327473b921 100755 GIT binary patch delta 16093 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 o5IFjw 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 St5CbK{t#TNQ3uK`_xjD)i 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 G#Q!gY#~ZT% diff --git a/F0:F030,F042,F072/3steppersLB/steppers.c b/F0:F030,F042,F072/3steppersLB/steppers.c index 6c7ab24..fdc5599 100644 --- a/F0:F030,F042,F072/3steppersLB/steppers.c +++ b/F0:F030,F042,F072/3steppersLB/steppers.c @@ -92,6 +92,16 @@ TRUE_INLINE void recalcARR(int i){ curspeed[i] = (((PCLK/(MOTORTIM_PSC+1)) / (ARR+1)) >> ustepsshift[i]); // recalculate speed due to new val } +// update stepper's settings +void update_stepper(uint8_t i){ + if(i >= MOTORSNO) return; + accdecsteps[i] = (the_conf.maxspd[i] * the_conf.maxspd[i]) / the_conf.accel[i] / 2; + ustepsshift[i] = MSB(the_conf.microsteps[i]); + encperstep[i] = the_conf.encrev[i] / STEPSPERREV; + enctimers[i]->ARR = the_conf.encrev[i]; + ESW_reaction[i] = the_conf.ESW_reaction[i]; +} + // run this function after each steppers parameters changing void init_steppers(){ timers_setup(); // reinit timers & stop them @@ -101,13 +111,10 @@ void init_steppers(){ stopflag[i] = 0; motdir[i] = 0; curspeed[i] = 0; - accdecsteps[i] = (the_conf.maxspd[i] * the_conf.maxspd[i]) / the_conf.accel[i] / 2; state[i] = STP_RELAX; - ustepsshift[i] = MSB(the_conf.microsteps[i]); - encperstep[i] = the_conf.encrev[i] / STEPSPERREV; if(!the_conf.motflags[i].donthold) MOTOR_EN(i); else MOTOR_DIS(i); - ESW_reaction[i] = the_conf.ESW_reaction[i]; + update_stepper(i); } } diff --git a/F0:F030,F042,F072/3steppersLB/steppers.cflags b/F0:F030,F042,F072/3steppersLB/steppers.cflags new file mode 100644 index 0000000..68d5165 --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/F0:F030,F042,F072/3steppersLB/steppers.config b/F0:F030,F042,F072/3steppersLB/steppers.config new file mode 100644 index 0000000..ca0621c --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.config @@ -0,0 +1,5 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 +#define EBUG +#define STM32F0 +#define STM32F072xB diff --git a/F0:F030,F042,F072/3steppersLB/steppers.creator b/F0:F030,F042,F072/3steppersLB/steppers.creator new file mode 100644 index 0000000..e94cbbd --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.creator @@ -0,0 +1 @@ +[General] diff --git a/F0:F030,F042,F072/3steppersLB/steppers.creator.user b/F0:F030,F042,F072/3steppersLB/steppers.creator.user new file mode 100644 index 0000000..819893c --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.creator.user @@ -0,0 +1,160 @@ + + + + + + EnvironmentId + {cf63021e-ef53-49b0-b03b-2f2570cdf3b6} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + KOI8-R + false + 4 + false + 80 + true + true + 1 + false + false + false + 1 + true + true + 0 + 8 + true + false + 2 + true + true + true + *.md, *.MD, Makefile + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + Desktop + {91347f2c-5221-46a7-80b1-0a054ca02f79} + 0 + 0 + 0 + + /home/eddy/Docs/SAO/ELECTRONICS/STM32/F0-srcs/usbcan_ringbuffer + + + + all + + true + GenericProjectManager.GenericMakeStep + + 1 + Сборка + Сборка + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + GenericProjectManager.GenericMakeStep + + 1 + Очистка + Очистка + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + По умолчанию + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Развёртывание + Развёртывание + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + 2 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/F0:F030,F042,F072/3steppersLB/steppers.cxxflags b/F0:F030,F042,F072/3steppersLB/steppers.cxxflags new file mode 100644 index 0000000..6435dfc --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/F0:F030,F042,F072/3steppersLB/steppers.files b/F0:F030,F042,F072/3steppersLB/steppers.files new file mode 100644 index 0000000..94e04bd --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.files @@ -0,0 +1,24 @@ +adc.c +adc.h +buttons.c +buttons.h +can.c +can.h +commonproto.c +commonproto.h +custom_buttons.c +custom_buttons.h +flash.c +flash.h +hardware.c +hardware.h +main.c +steppers.c +steppers.h +strfunct.c +strfunct.h +usb.c +usb_defs.h +usb.h +usb_lib.c +usb_lib.h diff --git a/F0:F030,F042,F072/3steppersLB/steppers.h b/F0:F030,F042,F072/3steppersLB/steppers.h index 00c5e22..f5c42b0 100644 --- a/F0:F030,F042,F072/3steppersLB/steppers.h +++ b/F0:F030,F042,F072/3steppersLB/steppers.h @@ -23,6 +23,14 @@ #include #include "commonproto.h" +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + // amount of tries to detect motor stall #define NSTALLEDMAX (5) // amount of steps to detect stalled state @@ -55,6 +63,7 @@ void addmicrostep(uint8_t i); void encoders_UPD(uint8_t i); void init_steppers(); +void update_stepper(uint8_t i); int32_t encoder_position(uint8_t i); int setencpos(uint8_t i, int32_t position); errcodes setmotpos(uint8_t i, int32_t position); diff --git a/F0:F030,F042,F072/3steppersLB/steppers.includes b/F0:F030,F042,F072/3steppersLB/steppers.includes new file mode 100644 index 0000000..06d1130 --- /dev/null +++ b/F0:F030,F042,F072/3steppersLB/steppers.includes @@ -0,0 +1,6 @@ +. +../inc +../inc/Fx +../inc/cm +../inc/ld +../inc/startup diff --git a/F0:F030,F042,F072/3steppersLB/usb.c b/F0:F030,F042,F072/3steppersLB/usb.c index a7b1ee8..e592ab4 100644 --- a/F0:F030,F042,F072/3steppersLB/usb.c +++ b/F0:F030,F042,F072/3steppersLB/usb.c @@ -84,7 +84,7 @@ static int usbwr(const uint8_t *buf, uint16_t l){ } static uint8_t usbbuff[USB_TXBUFSZ-1]; // temporary buffer (63 - to prevent need of ZLP) -static uint8_t buflen = 0; // amount of symbols in usbbuff +static volatile uint8_t buflen = 0; // amount of symbols in usbbuff // send next up to 63 bytes of data in usbbuff static void send_next(){ @@ -172,4 +172,3 @@ uint8_t USB_receive(uint8_t *buf){ rxNE = 0; return sz; } - diff --git a/F0:F030,F042,F072/3steppersLB/usb_lib.c b/F0:F030,F042,F072/3steppersLB/usb_lib.c index 8d1bf6c..58a4110 100644 --- a/F0:F030,F042,F072/3steppersLB/usb_lib.c +++ b/F0:F030,F042,F072/3steppersLB/usb_lib.c @@ -22,11 +22,11 @@ ep_t endpoints[STM32ENDPOINTS]; usb_dev_t USB_Dev; -uint8_t usbON = 0; +volatile uint8_t usbON = 0; static usb_LineCoding lineCoding = {115200, 0, 0, 8}; static config_pack_t setup_packet; static uint8_t ep0databuf[EP0DATABUF_SIZE]; -static uint8_t ep0dbuflen = 0; +static volatile uint8_t ep0dbuflen = 0; usb_LineCoding getLineCoding(){return lineCoding;} diff --git a/F0:F030,F042,F072/3steppersLB/usb_lib.h b/F0:F030,F042,F072/3steppersLB/usb_lib.h index d6fc0cc..1555633 100644 --- a/F0:F030,F042,F072/3steppersLB/usb_lib.h +++ b/F0:F030,F042,F072/3steppersLB/usb_lib.h @@ -166,7 +166,7 @@ typedef struct { extern ep_t endpoints[]; extern usb_dev_t USB_Dev; -extern uint8_t usbON; +extern volatile uint8_t usbON; void USB_Init(); uint8_t USB_GetState(); diff --git a/F0:F030,F042,F072/3steppersLB/version.inc b/F0:F030,F042,F072/3steppersLB/version.inc index 338ce6f..7f30586 100644 --- a/F0:F030,F042,F072/3steppersLB/version.inc +++ b/F0:F030,F042,F072/3steppersLB/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "169" -#define BUILD_DATE "2023-01-11" +#define BUILD_NUMBER "173" +#define BUILD_DATE "2023-02-21"