diff --git a/F3:F303/CANbus4BTA/BTA_CAN.bin b/F3:F303/CANbus4BTA/BTA_CAN.bin index 53faf23..ca20479 100755 Binary files a/F3:F303/CANbus4BTA/BTA_CAN.bin and b/F3:F303/CANbus4BTA/BTA_CAN.bin differ diff --git a/F3:F303/CANbus4BTA/Readme.md b/F3:F303/CANbus4BTA/Readme.md index 9c3c277..a33949a 100644 --- a/F3:F303/CANbus4BTA/Readme.md +++ b/F3:F303/CANbus4BTA/Readme.md @@ -122,6 +122,59 @@ Channel1 - ADC1. ## DMA2 +# Other resources usage +## Timers + +- SysTick is 1ms system time counter (`Tms`). +- TIM2 is 32bit timer with 2mks period (system timestamp for PEP emulation). + +## CAN + +CAN bus is primary interface. + +## USB + +USB (PL2303 emulation with iINTERFACE="canbusbta") used as alternate managing interface and for debugging. + +## USART + +USART1 can be used to operate with external encoder or other device over RS-422. + +## SPI + +- SPI1 used to work with external SSI encoder. +- SPI2 used with some external things. + +## I2C + +not implemented yet + +## ADC + +ADC1 used to measure internal temperature (CH16) and external: + +- CH1 - external power supply (raw value approx Uext/10). +- CH2 - onboard 5V supply after DC-DC (raw value approx V/2). +- CH3, CH4 - external inputs through dividers on RV1/R14 and RV2/R15. + +## GPIO + +GPIOA: + +- PA4 - DIN - input of multiplexers U1 and U2. +- PA5 - DEN0 - enable multiplexer U1. +- PA6 - DEN1 - enable multiplexer U2. + +GPIOB: + +- PB0..PB2 - 3bit input address on multiplexer. + +GPIOC: + +- PC13 - buzzer (not implemented yet). +- PC14 - relay. +- PC15 - USB pullup. + # Text command protocol Text commands have format of `parameter[number][=setter]`. Where - *parameter* is any possible command, diff --git a/F3:F303/CANbus4BTA/commonfunctions.c b/F3:F303/CANbus4BTA/commonfunctions.c index ca19889..2e912f3 100644 --- a/F3:F303/CANbus4BTA/commonfunctions.c +++ b/F3:F303/CANbus4BTA/commonfunctions.c @@ -43,6 +43,14 @@ static errcodes time_getset(CAN_message *msg){ *(uint32_t*)&msg->data[4] = Tms; return ERR_OK; } +// get/set timestamp +static errcodes timestamp_getset(CAN_message *msg){ + if(ISSETTER(msg->data)){ + TIM2->CNT = *(uint32_t*)&msg->data[4]; + }else FIXDL(msg); + *(uint32_t*)&msg->data[4] = TIM2->CNT; + return ERR_OK; +} // get MCU T static errcodes mcut(CAN_message *msg){ FIXDL(msg); @@ -138,6 +146,11 @@ static errcodes encget(CAN_message *msg){ if(read_encoder(msg->data + 4)) return ERR_OK; return ERR_CANTRUN; } +// reinit encoder +static errcodes encreinit(CAN_message _U_ *msg){ + encoder_setup(); + return ERR_OK; +} // common uint32_t setter/getter static errcodes u32setget(CAN_message *msg){ @@ -204,6 +217,9 @@ static const commonfunction funclist[CMD_AMOUNT] = { [CMD_SPIINIT] = {initspi2, 0, 0, 0}, [CMD_SPISEND] = {sendspi2, 0, 0, 5}, [CMD_ENCGET] = {encget, 0, 0, 0}, + [CMD_EMULPEP] = {flagsetget, 0, 0, 0}, + [CMD_ENCREINIT] = {encreinit, 0, 0, 0}, + [CMD_TIMESTAMP] = {timestamp_getset, 0, 0xffffff, 0}, }; diff --git a/F3:F303/CANbus4BTA/encoder.c b/F3:F303/CANbus4BTA/encoder.c index 3969cc7..9e16465 100644 --- a/F3:F303/CANbus4BTA/encoder.c +++ b/F3:F303/CANbus4BTA/encoder.c @@ -16,15 +16,23 @@ * along with this program. If not, see . */ +#include "can.h" #include "encoder.h" #include "flash.h" +#include "gpio.h" #include "spi.h" #include "usart.h" +#include void encoder_setup(){ - if(FLAG(ENC_IS_SSI)) spi_setup(ENCODER_SPI); - else usart_setup(); + if(FLAG(ENC_IS_SSI)){ + usart_deinit(); + spi_setup(ENCODER_SPI); + }else{ + spi_deinit(ENCODER_SPI); + usart_setup(); + } } // read encoder value into buffer `outbuf` @@ -34,3 +42,22 @@ int read_encoder(uint8_t outbuf[4]){ *((uint32_t*)outbuf) = 0; return spi_writeread(ENCODER_SPI, outbuf, 4); } + +// send encoder data +void CANsendEnc(){ + CAN_message msg = {.data = {0}, .ID = the_conf.encoderID, .length = 8}; + if(!read_encoder(msg.data)) return; + uint32_t ctr = TIM2->CNT; + //msg.data[4] = 0; + msg.data[5] = (ctr >> 16) & 0xff; + msg.data[6] = (ctr >> 8 ) & 0xff; + msg.data[7] = (ctr >> 0 ) & 0xff; + CAN_send(&msg); +} +// send limit-switches data +void CANsendLim(){ + CAN_message msg = {.data = {0}, .ID = the_conf.limitsID, .length = 8}; + msg.data[2] = getESW(0); + msg.data[3] = getESW(1); + CAN_send(&msg); +} diff --git a/F3:F303/CANbus4BTA/encoder.h b/F3:F303/CANbus4BTA/encoder.h index e935349..41addc3 100644 --- a/F3:F303/CANbus4BTA/encoder.h +++ b/F3:F303/CANbus4BTA/encoder.h @@ -22,3 +22,5 @@ void encoder_setup(); int read_encoder(uint8_t outbuf[4]); +void CANsendEnc(); +void CANsendLim(); diff --git a/F3:F303/CANbus4BTA/flash.c b/F3:F303/CANbus4BTA/flash.c index 0fbe9ed..f4610d1 100644 --- a/F3:F303/CANbus4BTA/flash.c +++ b/F3:F303/CANbus4BTA/flash.c @@ -46,7 +46,9 @@ user_conf the_conf = { .adcmul[2] = 1.f, .adcmul[3] = 1.f, .usartspeed = 115200, - .flags = FLAGP(ENC_IS_SSI), + .encoderID = 8, + .limitsID = 0xe, + .flags = FLAGP(ENC_IS_SSI) /*| FLAGP(EMULATE_PEP)*/, }; int currentconfidx = -1; // index of current configuration diff --git a/F3:F303/CANbus4BTA/flash.h b/F3:F303/CANbus4BTA/flash.h index fe0e8a4..44a958b 100644 --- a/F3:F303/CANbus4BTA/flash.h +++ b/F3:F303/CANbus4BTA/flash.h @@ -31,6 +31,8 @@ // bit flags positions // encoder have SSI (1) or RS-422 (0) #define ENC_IS_SSI_BIT 0 +// old PEP behaviour +#define EMULATE_PEP_BIT 1 // bit number #define FLAGBIT(f) (f ## _BIT) @@ -53,6 +55,8 @@ typedef struct __attribute__((packed, aligned(4))){ uint32_t bounce_ms; // debounce wait float adcmul[ADC_TSENS]; // ADC voltage multipliers uint32_t usartspeed; // USART1 speed (baud/s) + uint16_t encoderID; // CANbus encoders' ID (PEP emulation) + uint16_t limitsID; // CANbus limits' ID (PEP emulation) uint32_t flags; // bit flags } user_conf; diff --git a/F3:F303/CANbus4BTA/hardware.c b/F3:F303/CANbus4BTA/hardware.c index 5989c59..b4cd3fe 100644 --- a/F3:F303/CANbus4BTA/hardware.c +++ b/F3:F303/CANbus4BTA/hardware.c @@ -46,7 +46,17 @@ TRUE_INLINE void iwdg_setup(){ } #endif -static inline void gpio_setup(){ +// setup TIM2 as 24-bit 2mks timestamp counter +TRUE_INLINE void tim2_setup(){ + TIM2->CR1 = 0; // turn off timer + RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // enable clocking + TIM2->PSC = 143; // 500kHz + TIM2->ARR = 0xffffff; // 24 bit counter from 0xffffff to 0 + // turn it on, downcounting + TIM2->CR1 = TIM_CR1_CEN | TIM_CR1_DIR; +} + +TRUE_INLINE void gpio_setup(){ RELAY_OFF(); MUL_OFF(0); MUL_OFF(1); RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN; // PWM - AF1 @PA7; USB - alternate function 14 @ pins PA11/PA12; SWD - AF0 @PA13/14 @@ -73,6 +83,7 @@ static inline void gpio_setup(){ } void hw_setup(){ + tim2_setup(); gpio_setup(); adc_setup(); USB_setup(); diff --git a/F3:F303/CANbus4BTA/hardware.h b/F3:F303/CANbus4BTA/hardware.h index 9da78f9..26dd084 100644 --- a/F3:F303/CANbus4BTA/hardware.h +++ b/F3:F303/CANbus4BTA/hardware.h @@ -20,6 +20,9 @@ #include +// PEP emulation - period of encoder/esw data send - 70ms +#define ENCODER_PERIOD (69) + // USB pullup #define USBPU_port GPIOC #define USBPU_pin (1<<15) diff --git a/F3:F303/CANbus4BTA/main.c b/F3:F303/CANbus4BTA/main.c index 56dd9bf..4778379 100644 --- a/F3:F303/CANbus4BTA/main.c +++ b/F3:F303/CANbus4BTA/main.c @@ -50,6 +50,7 @@ TRUE_INLINE void showCANmessages(){ int main(void){ char inbuff[MAXSTRLEN+1]; + uint32_t encT = 0; // time of ENC and LIM data sent (PEP emulation) USBPU_OFF(); if(StartHSE()){ SysTick_Config((uint32_t)72000); // 1ms @@ -75,15 +76,6 @@ int main(void){ CAN_reinit(0); } if(cansniffer) showCANmessages(); - /*if(bufovr){ - bufovr = 0; - USB_sendstr("error=uartoverflow\n"); - }*/ - char *txt = NULL; - if(usart_getline(&txt)){ - const char *ans = run_text_cmd(txt); - if(ans) usart_send(ans); - } int l = USB_receivestr(inbuff, MAXSTRLEN); if(l < 0) USB_sendstr("error=usboverflow\n"); else if(l){ @@ -92,13 +84,22 @@ int main(void){ } ESW_process(); static uint8_t oldswitches[2] = {0}; + int send = 0; for(int i = 0; i < 2; ++i){ uint8_t new = getESW(i); if(oldswitches[i] != new){ + send = 1; oldswitches[i] = new; - USB_sendstr("ESW changed @"); printu(Tms); + USB_sendstr("ESW"); USB_putbyte('0' + i); + USB_sendstr(" changed @"); printu(Tms); USB_sendstr(" to "); printuhex(new); newline(); } } + if(FLAG(EMULATE_PEP)){ + if(Tms - encT > ENCODER_PERIOD){ + encT = Tms; + CANsendEnc(); + } else if(send) CANsendLim(); + } } } diff --git a/F3:F303/CANbus4BTA/proto.h b/F3:F303/CANbus4BTA/proto.h index 186e3f7..9f48e09 100644 --- a/F3:F303/CANbus4BTA/proto.h +++ b/F3:F303/CANbus4BTA/proto.h @@ -69,6 +69,9 @@ typedef enum{ CMD_SPIINIT, // 16 - init SPI2 CMD_SPISEND, // 17 - send 1..4 bytes over SPI CMD_ENCGET, // 18 - get encoder value + CMD_EMULPEP, // 19 - emulate (1) / not (0) PEP + CMD_ENCREINIT, // 20 - reinit encoder + CMD_TIMESTAMP, // 21 - 2mks 24-bit timestamp CMD_AMOUNT // amount of CAN commands } can_cmd; diff --git a/F3:F303/CANbus4BTA/spi.c b/F3:F303/CANbus4BTA/spi.c index 2026617..7867e5c 100644 --- a/F3:F303/CANbus4BTA/spi.c +++ b/F3:F303/CANbus4BTA/spi.c @@ -26,6 +26,9 @@ //#define SPIDR *((volatile uint8_t*)&SPI2->DR) +#define CHKIDX(idx) do{if(idx == 0 || idx > AMOUNT_OF_SPI) return;}while(0) +#define CHKIDXR(idx) do{if(idx == 0 || idx > AMOUNT_OF_SPI) return 0;}while(0) + spiStatus spi_status[AMOUNT_OF_SPI+1] = {0, SPI_NOTREADY, SPI_NOTREADY}; static volatile SPI_TypeDef* const SPIs[AMOUNT_OF_SPI+1] = {NULL, SPI1, SPI2}; #define WAITX(x) do{volatile uint32_t wctr = 0; while((x) && (++wctr < 360000)) IWDG->KR = IWDG_REFRESH; if(wctr==360000){ DBG("timeout"); return 0;}}while(0) @@ -38,7 +41,7 @@ static volatile SPI_TypeDef* const SPIs[AMOUNT_OF_SPI+1] = {NULL, SPI1, SPI2}; // Channel 4 - SPI2 Rx // Channel 5 - SPI2 Tx void spi_setup(uint8_t idx){ - if(idx > AMOUNT_OF_SPI) return; + CHKIDX(idx); volatile SPI_TypeDef *SPI = SPIs[idx]; SPI->CR1 = 0; // clear EN SPI->CR2 = 0; @@ -59,9 +62,9 @@ void spi_setup(uint8_t idx){ RCC->APB1RSTR = RCC_APB1RSTR_SPI2RST; // reset SPI RCC->APB1RSTR = 0; // clear reset RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; - RCC->AHBENR |= RCC_AHBENR_DMA1EN; SPI->CR2 = SPI_CR2_SSOE; // hardware NSS management // setup SPI2 DMA + //RCC->AHBENR |= RCC_AHBENR_DMA1EN; //SPI->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN; // Tx /*DMA1_Channel5->CPAR = (uint32_t)&(SPI2->DR); // hardware @@ -82,8 +85,25 @@ void spi_setup(uint8_t idx){ DBG("SPI works"); } +// turn off given SPI channel and release GPIO +void spi_deinit(uint8_t idx){ + CHKIDX(idx); + volatile SPI_TypeDef *SPI = SPIs[idx]; + SPI->CR1 = 0; + SPI->CR2 = 0; + if(idx == 1){ + RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN; + GPIOB->AFR[0] = GPIOB->AFR[0] & ~(GPIO_AFRL_AFRL3 | GPIO_AFRL_AFRL4); + GPIOB->MODER = GPIOB->MODER & ~(GPIO_MODER_MODER3 | GPIO_MODER_MODER4); + }else if(idx == 2){ + RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN; + GPIOB->AFR[1] = GPIOB->AFR[1] & ~(GPIO_AFRH_AFRH4 | GPIO_AFRH_AFRH5 | GPIO_AFRH_AFRH6 | GPIO_AFRH_AFRH7); + GPIOB->MODER = GPIOB->MODER & ~(GPIO_MODER_MODER12 | GPIO_MODER_MODER13 | GPIO_MODER_MODER14 | GPIO_MODER_MODER15); + } +} + int spi_waitbsy(uint8_t idx){ - if(idx > AMOUNT_OF_SPI) return 0; + CHKIDXR(idx); WAITX(SPIs[idx]->SR & SPI_SR_BSY); return 1; } @@ -95,7 +115,7 @@ int spi_waitbsy(uint8_t idx){ * @return 0 if failed */ int spi_writeread(uint8_t idx, uint8_t *data, uint32_t n){ - if(idx > AMOUNT_OF_SPI) return 0; + CHKIDXR(idx); if(spi_status[idx] != SPI_READY || !data || !n){ DBG("not ready"); return 0; @@ -146,7 +166,7 @@ int spi_writeread(uint8_t idx, uint8_t *data, uint32_t n){ */ /* int spi_read(uint8_t idx, uint8_t *data, uint32_t n){ - if(idx > AMOUNT_OF_SPI) return 0; + CHKIDXR(idx); if(spi_status[idx] != SPI_READY){ DBG("not ready"); return 0; diff --git a/F3:F303/CANbus4BTA/spi.h b/F3:F303/CANbus4BTA/spi.h index e617fa6..9f3a870 100644 --- a/F3:F303/CANbus4BTA/spi.h +++ b/F3:F303/CANbus4BTA/spi.h @@ -29,6 +29,7 @@ typedef enum{ extern spiStatus spi_status[AMOUNT_OF_SPI+1]; +void spi_deinit(uint8_t idx); void spi_setup(uint8_t idx); int spi_waitbsy(uint8_t idx); int spi_writeread(uint8_t idx, uint8_t *data, uint32_t n); diff --git a/F3:F303/CANbus4BTA/textfunctions.c b/F3:F303/CANbus4BTA/textfunctions.c index bf6638c..fc12ca5 100644 --- a/F3:F303/CANbus4BTA/textfunctions.c +++ b/F3:F303/CANbus4BTA/textfunctions.c @@ -58,16 +58,23 @@ static const funcdescr funclist[] = { {"cansnif", -TCMD_CANSNIF, "get/change sniffer state (0 - normal, 1 - sniffer)"}, {"canspeed", CMD_CANSPEED, "get/set CAN speed (bps)"}, {"dumpconf", -TCMD_DUMPCONF, "dump current configuration"}, + {"encget", CMD_ENCGET, "read encoder data"}, + {"encreinit", CMD_ENCREINIT, "reinit encoder"}, + {"encssi", CMD_ENCISSSI, "encoder is SSI (1) or RS-422 (0)"}, {"esw", CMD_GETESW, "anti-bounce read ESW of channel 0 or 1"}, {"eswblk", CMD_GETESW_BLK, "blocking read ESW of channel 0 or 1"}, {"eraseflash", CMD_ERASESTOR, "erase all flash storage"}, {"mcutemp", CMD_MCUTEMP, "get MCU temperature (*10degrC)"}, + {"pepemul", CMD_EMULPEP, "emulate (1) / not (0) PEP"}, {"relay", CMD_RELAY, "get/set relay state (0 - off, 1 - on)"}, {"reset", CMD_RESET, "reset MCU"}, {"s", -TCMD_CANSEND, "send CAN message: ID 0..8 data bytes"}, {"saveconf", CMD_SAVECONF, "save configuration"}, {"spiinit", CMD_SPIINIT, "init SPI2"}, - {"time", CMD_TIME, "get/set time (ms)"}, + {"spisend", CMD_SPISEND, "send 4 bytes over SPI2"}, + {"time", CMD_TIME, "get/set time (1ms, 32bit)"}, + {"timestamp", CMD_TIMESTAMP, "get/set timestamp (2mks, 24bit)"}, + {"usartspeed", CMD_USARTSPEED, "get/set USART1 speed"}, {"wdtest", -TCMD_WDTEST, "test watchdog"}, {NULL, 0, NULL} // last record }; diff --git a/F3:F303/CANbus4BTA/usart.c b/F3:F303/CANbus4BTA/usart.c index 40b84d0..ab3ed58 100644 --- a/F3:F303/CANbus4BTA/usart.c +++ b/F3:F303/CANbus4BTA/usart.c @@ -24,7 +24,7 @@ static volatile int idatalen = 0; // received data line length (including '\n') -volatile int linerdy = 0, // received data ready +static volatile int linerdy = 0, // received data ready dlen = 0, // length of data (including '\n') in current buffer bufovr = 0; // input buffer overfull @@ -65,9 +65,17 @@ void usart_send(const char *str){ usart_sendn(str, L); } +// turn off USART1 and deinit GPIO +void usart_deinit(){ + USART1->ICR = 0xffffffff; + USART1->CR1 = 0; + RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN; + GPIOA->AFR[1] = GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2); + GPIOA->MODER = GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10); +} + // USART1: PA10(Rx, pullup), PA9(Tx); USART1 = AF7 @PA9/10; void usart_setup(){ - // clock GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10)) | MODER_AF(9) | MODER_AF(10); GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) | diff --git a/F3:F303/CANbus4BTA/usart.h b/F3:F303/CANbus4BTA/usart.h index a0198e0..e75f1ce 100644 --- a/F3:F303/CANbus4BTA/usart.h +++ b/F3:F303/CANbus4BTA/usart.h @@ -23,9 +23,8 @@ // input buffers size #define UARTBUFSZ (80) -extern volatile int linerdy, bufovr; - void usart_setup(); +void usart_deinit(); int usart_getline(char **line); void usart_send(const char *str); void usart_sendn(const char *str, int L); diff --git a/F3:F303/CANbus4BTA/version.inc b/F3:F303/CANbus4BTA/version.inc index cb5140d..afd5a14 100644 --- a/F3:F303/CANbus4BTA/version.inc +++ b/F3:F303/CANbus4BTA/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "80" -#define BUILD_DATE "2024-03-07" +#define BUILD_NUMBER "84" +#define BUILD_DATE "2024-03-08"