PEP emulation (didn't test yet)

This commit is contained in:
Edward Emelianov 2024-03-08 13:23:23 +03:00
parent 8ea835d80f
commit bc82142e87
17 changed files with 183 additions and 26 deletions

Binary file not shown.

View File

@ -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,

View File

@ -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},
};

View File

@ -16,15 +16,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "can.h"
#include "encoder.h"
#include "flash.h"
#include "gpio.h"
#include "spi.h"
#include "usart.h"
#include <string.h>
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);
}

View File

@ -22,3 +22,5 @@
void encoder_setup();
int read_encoder(uint8_t outbuf[4]);
void CANsendEnc();
void CANsendLim();

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -20,6 +20,9 @@
#include <stm32f3.h>
// PEP emulation - period of encoder/esw data send - 70ms
#define ENCODER_PERIOD (69)
// USB pullup
#define USBPU_port GPIOC
#define USBPU_pin (1<<15)

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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
};

View File

@ -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)) |

View File

@ -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);

View File

@ -1,2 +1,2 @@
#define BUILD_NUMBER "80"
#define BUILD_DATE "2024-03-07"
#define BUILD_NUMBER "84"
#define BUILD_DATE "2024-03-08"