Fix EEPROM in flash emulation; can't fix error in ADC16/ADC17 (temperature and Vdd calculation)

This commit is contained in:
eddyem 2017-12-06 21:46:16 +03:00
parent 22d195d38b
commit 1210df589e
7 changed files with 87 additions and 47 deletions

View File

@ -23,6 +23,7 @@
#include "stm32f0.h" #include "stm32f0.h"
#include "flash.h" #include "flash.h"
#include "adc.h" #include "adc.h"
#include "usart.h"
/* /*
* 0 - Steppers current * 0 - Steppers current
@ -39,9 +40,11 @@ uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS];
void adc_setup(){ void adc_setup(){
// AIN: PA0..3, PA13, PA14. ADC_IN16 - inner temperature. ADC_IN17 - VREFINT // AIN: PA0..3, PA13, PA14. ADC_IN16 - inner temperature. ADC_IN17 - VREFINT
/* (1) Enable the peripheral clock of the ADC */ /* (1) Enable the peripheral clock of the ADC */
/* (2) Set peripheral prescaler to /2 so PCLK = HCLK/2 = 24MHz */ /* (2) Start HSI14 RC oscillator */
/* (3) Wait HSI14 is ready */
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* (1) */ RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* (1) */
RCC->CFGR |= RCC_CFGR_PPRE_2; /* (2) */ RCC->CR2 |= RCC_CR2_HSI14ON; /* (2) */
while ((RCC->CR2 & RCC_CR2_HSI14RDY) == 0) /* (3) */
/* (1) Ensure that ADEN = 0 */ /* (1) Ensure that ADEN = 0 */
/* (2) Clear ADEN */ /* (2) Clear ADEN */
/* (3) Launch the calibration by setting ADCAL */ /* (3) Launch the calibration by setting ADCAL */
@ -56,12 +59,12 @@ void adc_setup(){
do{ do{
ADC1->CR |= ADC_CR_ADEN; /* (1) */ ADC1->CR |= ADC_CR_ADEN; /* (1) */
}while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (2) */; }while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* (2) */;
/* (1) Select PCLK/2 by writing 01 in CKMODE */ /* (1) Select HSI14 by writing 00 in CKMODE (reset value) */
/* (2) Select the continuous mode */ /* (2) Select the continuous mode */
/* (3) Select CHSEL0..3, 13,14, 16,17 */ /* (3) Select CHSEL0..3, 13,14, 16,17 */
/* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */ /* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */
/* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */ /* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */
ADC1->CFGR2 |= ADC_CFGR2_CKMODE_0; /* (1) */ // ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */
ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/ ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/
ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL2 | ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL2 |
ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL13 | ADC_CHSELR_CHSEL14 | ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL13 | ADC_CHSELR_CHSEL14 |
@ -87,25 +90,47 @@ void adc_setup(){
} }
// return MCU temperature (degrees of celsius) // return MCU temperature (degrees of celsius)
uint32_t getTemp(){ int32_t getTemp(){
uint32_t temperature = ADC_array[6]; int32_t temperature = (int32_t)ADC_array[6];
temperature = ((temperature * VDD_APPLI / VDD_CALIB) - (uint32_t) *TEMP30_CAL_ADDR ) ; write2trbuf("getTemp()\ncal30=");
temperature *= (uint32_t)(110 - 30); put_uint(*TEMP30_CAL_ADDR);
temperature /= (uint32_t)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR); write2trbuf(", cal110=");
temperature += 30; put_uint(*TEMP110_CAL_ADDR);
write2trbuf(", t=");
put_int(temperature);
SENDBUF();
temperature = ((int32_t) *TEMP30_CAL_ADDR - temperature);
put_int(temperature);
SENDBUF();
temperature *= (int32_t)(1100 - 300);
put_int(temperature);
SENDBUF();
temperature = temperature / (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR);
put_int(temperature);
SENDBUF();
temperature += 300;
return(temperature); return(temperature);
} }
//static uint32_t calval = 0; //static uint32_t calval = 0;
// return Vdd * 10 (V) // return Vdd * 10 (V)
uint32_t getVdd(){ uint32_t getVdd(){
write2trbuf("getVdd(), val=");
put_uint(ADC_array[7]);
write2trbuf(", cal=");
put_uint(*VREFINT_CAL_ADDR);
SENDBUF();
/* if(!calval){ /* if(!calval){
calval = ((uint32_t) *VREFINT_CAL_ADDR) * VDD_CALIB; calval = ((uint32_t) *VREFINT_CAL_ADDR) * VDD_CALIB;
calval /= VDD_APPLI; calval /= VDD_APPLI;
} */ } */
uint32_t vdd = ADC_array[7] * (uint32_t)33 * the_conf.v33numerator; // 3.3V uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)33 * the_conf.v33numerator; // 3.3V
put_uint(vdd);
SENDBUF();
//vdd /= calval * the_conf.v33denominator; //vdd /= calval * the_conf.v33denominator;
vdd /= ((uint32_t) *VREFINT_CAL_ADDR) * the_conf.v33denominator; vdd /= ADC_array[7] * the_conf.v33denominator;
put_uint(vdd);
SENDBUF();
return vdd; return vdd;
} }

View File

@ -38,7 +38,7 @@ typedef enum{
ESW_ERROR ESW_ERROR
} ESW_status; } ESW_status;
uint32_t getTemp(); int32_t getTemp();
uint32_t getVdd(); uint32_t getVdd();
uint32_t getVmot(); uint32_t getVmot();
uint32_t getImot(); uint32_t getImot();

View File

@ -28,9 +28,10 @@
// start of configuration data in flash (from 15kB, one kB size) // start of configuration data in flash (from 15kB, one kB size)
#define FLASH_CONF_START_ADDR ((uint32_t)0x08003C00) #define FLASH_CONF_START_ADDR ((uint32_t)0x08003C00)
static const int maxnum = 1024 / sizeof(user_conf);
user_conf the_conf = { user_conf the_conf = {
.good_data_pos = 0xffffffff .userconf_sz = sizeof(user_conf)
,.devID = 0 ,.devID = 0
,.v12numerator = 1 ,.v12numerator = 1
,.v12denominator = 1 ,.v12denominator = 1
@ -41,66 +42,81 @@ user_conf the_conf = {
,.ESW_thres = 150 ,.ESW_thres = 150
}; };
static int maxnum = 0x800 / sizeof(user_conf);
static int erase_flash(); static int erase_flash();
static int get_gooddata(){ static int get_gooddata(){
user_conf *c = (user_conf*) FLASH_CONF_START_ADDR; user_conf *c = (user_conf*) FLASH_CONF_START_ADDR;
uint32_t datapos = c->good_data_pos;
if(datapos == 0xffffffff){ // virginity clear
return maxnum;
}
// have data - move it to `the_conf` // have data - move it to `the_conf`
if(maxnum > 32) maxnum = 32;
int idx; int idx;
for(idx = 1; idx < maxnum; ++idx){ // find current settings index - first non-zero bit //write2trbuf("get_gooddata()\n");
if(datapos & 1<<idx){ for(idx = 0; idx < maxnum; ++idx){ // find current settings index - first good
break; uint16_t sz = c[idx].userconf_sz;
/*write2trbuf("idx=");
put_int((int32_t) idx);
write2trbuf(", sz=");
put_uint((uint32_t) sz);
write2trbuf(", devID=");
put_uint((uint32_t) c[idx].devID);
write2trbuf(", ESW_thres=");
put_uint((uint32_t) c[idx].ESW_thres);
SENDBUF();*/
if(sz != sizeof(user_conf)){
if(sz == 0xffff) break; // first clear
else{
return -2; // flash corrupt, need to erase
}
} }
} }
return idx-1; return idx-1; // -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
} }
void get_userconf(){ void get_userconf(){
user_conf *c = (user_conf*) FLASH_CONF_START_ADDR; user_conf *c = (user_conf*) FLASH_CONF_START_ADDR;
int idx = get_gooddata(); int idx = get_gooddata();
if(idx == maxnum) return; if(idx < 0) return; // no data stored
memcpy(&the_conf, &c[idx], sizeof(user_conf)); memcpy(&the_conf, &c[idx], sizeof(user_conf));
} }
// store new configuration // store new configuration
// @return 0 if all OK // @return 0 if all OK
int store_userconf(){ int store_userconf(){
char buf[2] = {0,0};
int ret = 0; int ret = 0;
user_conf *c = (user_conf*) FLASH_CONF_START_ADDR; user_conf *c = (user_conf*) FLASH_CONF_START_ADDR;
int idx = get_gooddata(); int idx = get_gooddata();
if(idx == maxnum || idx == maxnum - 1){ // first run or there's no more place if(idx == -2 || idx == maxnum - 1){ // data corruption or there's no more place
idx = 0; idx = 0;
if(erase_flash()) return 1; if(erase_flash()) return 1;
}else ++idx; // take next data position }else ++idx; // take next data position
if (FLASH->CR & FLASH_CR_LOCK){ /*write2trbuf("store_userconf()\nidx=");
put_int((int32_t) idx);
SENDBUF();*/
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
FLASH->KEYR = FLASH_FKEY1; FLASH->KEYR = FLASH_FKEY1;
FLASH->KEYR = FLASH_FKEY2; FLASH->KEYR = FLASH_FKEY2;
} }
the_conf.good_data_pos = 0xffffffff ^ (1<<idx); // write zero to corresponding position
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY);
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; if(FLASH->SR & FLASH_SR_WRPERR) return 1; // write protection
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; // clear all flags
FLASH->CR |= FLASH_CR_PG; FLASH->CR |= FLASH_CR_PG;
uint16_t *data = (uint16_t*) &the_conf; uint16_t *data = (uint16_t*) &the_conf;
uint16_t *address = (uint16_t*) &c[idx]; uint16_t *address = (uint16_t*) &c[idx];
uint32_t i, count = sizeof(user_conf) / 2; uint32_t i, count = sizeof(user_conf) / 2;
for (i = 0; i < count; ++i){ for (i = 0; i < count; ++i){
//*(volatile uint16_t*)(address + i) = (((uint8_t)data[i + 1]) << 8) | data[i];
*(volatile uint16_t*)(address + i) = data[i]; *(volatile uint16_t*)(address + i) = data[i];
//while (!(FLASH->SR & FLASH_SR_EOP)); while (FLASH->SR & FLASH_SR_BSY);
while((FLASH->SR & FLASH_SR_BSY)); if(FLASH->SR & FLASH_SR_PGERR) ret = 1; // program error - meet not 0xffff
buf[0] = '0' + i; else while (!(FLASH->SR & FLASH_SR_EOP));
usart1_send_blocking(buf); /*write2trbuf("write byte ");
if(FLASH->SR & FLASH_SR_PGERR) ret = 1; put_int((int32_t) i);
buf[0] = ret + '0'; write2trbuf(", write value=");
usart1_send_blocking(buf); put_uint(data[i]);
write2trbuf(", read value=");
put_uint(address[i]);
SENDBUF();
if(ret){
write2trbuf("PGERR");
SENDBUF();
}*/
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR;
} }
FLASH->CR &= ~(FLASH_CR_PG); FLASH->CR &= ~(FLASH_CR_PG);
@ -110,6 +126,8 @@ usart1_send_blocking(buf);
static int erase_flash(){ static int erase_flash(){
int ret = 0; int ret = 0;
/*write2trbuf("erase_flash()");
SENDBUF();*/
/* (1) Wait till no operation is on going */ /* (1) Wait till no operation is on going */
/* (2) Clear error & EOP bits */ /* (2) Clear error & EOP bits */
/* (3) Check that the Flash is unlocked */ /* (3) Check that the Flash is unlocked */

View File

@ -26,7 +26,7 @@
#define __FLASH_H__ #define __FLASH_H__
typedef struct{ typedef struct{
uint32_t good_data_pos; // position of data (index of mostly left zero) uint16_t userconf_sz; // size of data
uint16_t devID; // device address (id) uint16_t devID; // device address (id)
uint16_t ESW_thres; // ADC threshold for end-switches/Hall sensors uint16_t ESW_thres; // ADC threshold for end-switches/Hall sensors
// calibration values for current/voltage sensors // calibration values for current/voltage sensors

View File

@ -27,8 +27,6 @@
#include "string.h" #include "string.h"
#include "usart.h" #include "usart.h"
#define SENDBUF() do{usart1_send_blocking(gettrbuf()); cleartrbuf();}while(0)
static const char *eodata = "DATAEND"; static const char *eodata = "DATAEND";
static const char *badcmd = "BADCMD"; static const char *badcmd = "BADCMD";
static const char *allok = "ALL OK"; static const char *allok = "ALL OK";
@ -158,6 +156,7 @@ typedef struct{
} user_conf_descr; } user_conf_descr;
static const user_conf_descr descrarr[] = { static const user_conf_descr descrarr[] = {
{"CONFSZ", &the_conf.userconf_sz},
{"DEVID", &the_conf.devID}, {"DEVID", &the_conf.devID},
{"V12NUM", &the_conf.v12numerator}, {"V12NUM", &the_conf.v12numerator},
{"V12DEN", &the_conf.v12denominator}, {"V12DEN", &the_conf.v12denominator},
@ -171,9 +170,6 @@ static const user_conf_descr descrarr[] = {
static char *get_conf(){ static char *get_conf(){
const user_conf_descr *curdesc = descrarr; const user_conf_descr *curdesc = descrarr;
write2trbuf("DATAPOS=");
put_uint(the_conf.good_data_pos);
SENDBUF();
do{ do{
write2trbuf(curdesc->fieldname); write2trbuf(curdesc->fieldname);
put2trbuf('='); put2trbuf('=');
@ -274,9 +270,9 @@ static char *setESWthres(char *str){
} }
static char *get_temper(){ static char *get_temper(){
uint32_t t = getTemp(); int32_t t = getTemp();
write2trbuf("TEMP="); write2trbuf("TEMP=");
put_uint(t); put_int(t);
SENDBUF(); SENDBUF();
return NULL; return NULL;
} }

BIN
STM32/steppers/steppers.bin Executable file

Binary file not shown.

View File

@ -47,6 +47,7 @@ void USART1_config();
int usart1_getline(char **line); int usart1_getline(char **line);
TXstatus usart1_send(char *str); TXstatus usart1_send(char *str);
#define usart1_send_blocking(str) do{}while(LINE_BUSY == usart1_send(str)) #define usart1_send_blocking(str) do{}while(LINE_BUSY == usart1_send(str))
#define SENDBUF() do{usart1_send_blocking(gettrbuf()); cleartrbuf();}while(0)
#define cleartrbuf() do{trbufidx = 0;}while(0) #define cleartrbuf() do{trbufidx = 0;}while(0)
#define trbufisfull() (trbufidx) #define trbufisfull() (trbufidx)