From 8ea835d80f798ff3c0469bff26825f45fb364e88 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 7 Mar 2024 19:40:21 +0300 Subject: [PATCH] add spi, not tested yet --- F3:F303/CANbus4BTA/BTA_CAN.bin | Bin 21176 -> 22900 bytes F3:F303/CANbus4BTA/canbus4bta.creator.user | 2 +- F3:F303/CANbus4BTA/canbus4bta.files | 4 + F3:F303/CANbus4BTA/commonfunctions.c | 77 ++++++-- F3:F303/CANbus4BTA/encoder.c | 36 ++++ F3:F303/CANbus4BTA/encoder.h | 24 +++ F3:F303/CANbus4BTA/flash.c | 27 ++- F3:F303/CANbus4BTA/flash.h | 19 +- F3:F303/CANbus4BTA/hardware.c | 18 +- F3:F303/CANbus4BTA/hardware.h | 3 + F3:F303/CANbus4BTA/main.c | 2 + F3:F303/CANbus4BTA/proto.h | 5 + F3:F303/CANbus4BTA/spi.c | 198 +++++++++++++++++++++ F3:F303/CANbus4BTA/spi.h | 37 ++++ F3:F303/CANbus4BTA/textfunctions.c | 16 ++ F3:F303/CANbus4BTA/usart.c | 10 +- F3:F303/CANbus4BTA/version.inc | 4 +- 17 files changed, 433 insertions(+), 49 deletions(-) create mode 100644 F3:F303/CANbus4BTA/encoder.c create mode 100644 F3:F303/CANbus4BTA/encoder.h create mode 100644 F3:F303/CANbus4BTA/spi.c create mode 100644 F3:F303/CANbus4BTA/spi.h diff --git a/F3:F303/CANbus4BTA/BTA_CAN.bin b/F3:F303/CANbus4BTA/BTA_CAN.bin index 539773609b5eb3258b7132697d3a1ee5e1cf200a..53faf23deb61405ebddaa3e8981fdbe64260c88c 100755 GIT binary patch delta 6530 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 diff --git a/F3:F303/CANbus4BTA/canbus4bta.creator.user b/F3:F303/CANbus4BTA/canbus4bta.creator.user index b114d45..d8ad98b 100644 --- a/F3:F303/CANbus4BTA/canbus4bta.creator.user +++ b/F3:F303/CANbus4BTA/canbus4bta.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F3:F303/CANbus4BTA/canbus4bta.files b/F3:F303/CANbus4BTA/canbus4bta.files index 4478816..73679a0 100644 --- a/F3:F303/CANbus4BTA/canbus4bta.files +++ b/F3:F303/CANbus4BTA/canbus4bta.files @@ -4,6 +4,8 @@ can.c can.h commonfunctions.c commonfunctions.h +encoder.c +encoder.h flash.c flash.h gpio.c @@ -14,6 +16,8 @@ main.c proto.h ringbuffer.c ringbuffer.h +spi.c +spi.h strfunc.c strfunc.h textfunctions.c diff --git a/F3:F303/CANbus4BTA/commonfunctions.c b/F3:F303/CANbus4BTA/commonfunctions.c index f4a828c..ca19889 100644 --- a/F3:F303/CANbus4BTA/commonfunctions.c +++ b/F3:F303/CANbus4BTA/commonfunctions.c @@ -19,9 +19,11 @@ #include "adc.h" #include "can.h" #include "commonfunctions.h" +#include "encoder.h" #include "flash.h" #include "gpio.h" #include "proto.h" +#include "spi.h" #include "usb.h" #define FIXDL(m) do{m->length = 8;}while(0) @@ -64,16 +66,6 @@ static errcodes adcv(CAN_message *msg){ *(uint32_t*)&msg->data[4] = (uint32_t) v; // or float?? return ERR_OK; } -// get/set CAN speed -static errcodes canspeed(CAN_message *msg){ - if(ISSETTER(msg->data)){ - uint32_t spd = *(uint32_t*)&msg->data[4]; - CAN_reinit(spd); - the_conf.CANspeed = CAN_speed(); - }else FIXDL(msg); - *(uint32_t*)&msg->data[4] = CAN_speed(); - return ERR_OK; -} // get/set CAN ID static errcodes canid(CAN_message *msg){ if(ISSETTER(msg->data)){ @@ -128,12 +120,56 @@ static errcodes esw(CAN_message *msg){ *(uint32_t*)&msg->data[4] = getESW(no); return ERR_OK; } -// bounce constant, ms -static errcodes bounce(CAN_message *msg){ +// init SPI2 +static errcodes initspi2(CAN_message _U_ *msg){ + spi_setup(2); + return ERR_OK; +} +// send/read 1..4 bytes +static errcodes sendspi2(CAN_message *msg){ + int n = msg->length - 4; + if(n < 1) return ERR_BADVAL; + if(spi_writeread(2, msg->data + 4, n)) return ERR_OK; + return ERR_CANTRUN; +} +// read encoder value and send over CAN +static errcodes encget(CAN_message *msg){ + FIXDL(msg); + if(read_encoder(msg->data + 4)) return ERR_OK; + return ERR_CANTRUN; +} + +// common uint32_t setter/getter +static errcodes u32setget(CAN_message *msg){ + uint16_t idx = *(uint16_t*)msg->data; + uint32_t *ptr = NULL; + switch(idx){ + case CMD_CANSPEED: ptr = &the_conf.CANspeed; break; + case CMD_BOUNCE: ptr = &the_conf.bounce_ms; break; + case CMD_USARTSPEED: ptr = &the_conf.usartspeed; break; + default: break; + } + if(!ptr) return ERR_CANTRUN; // unknown error if(ISSETTER(msg->data)){ - the_conf.bounce_ms = *(uint32_t*)&msg->data[4]; + *ptr = *(uint32_t*)&msg->data[4]; }else FIXDL(msg); - *(uint32_t*)&msg->data[4] = the_conf.bounce_ms; + *(uint32_t*)&msg->data[4] = *ptr; + return ERR_OK; +} +// common bitflag setter/getter +static errcodes flagsetget(CAN_message *msg){ + uint16_t idx = *(uint16_t*)msg->data; + uint8_t bit = 32; + switch(idx){ + case CMD_ENCISSSI: bit = FLAGBIT(ENC_IS_SSI); break; + default: break; + } + if(bit > 31) return ERR_CANTRUN; // unknown error + if(ISSETTER(msg->data)){ + if(msg->data[4]) the_conf.flags |= 1<data[4] = (the_conf.flags & (1<= CMD_AMOUNT || funclist[idx].fn == NULL){ // bad command index FORMERR(msg, ERR_BADCMD); return; } - // check minimal length (2 or 3) + // check minimal length if(funclist[idx].datalen > datalen){ FORMERR(msg, ERR_WRONGLEN); return; } diff --git a/F3:F303/CANbus4BTA/encoder.c b/F3:F303/CANbus4BTA/encoder.c new file mode 100644 index 0000000..3969cc7 --- /dev/null +++ b/F3:F303/CANbus4BTA/encoder.c @@ -0,0 +1,36 @@ +/* + * This file is part of the canbus4bta project. + * Copyright 2024 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 "encoder.h" +#include "flash.h" +#include "spi.h" +#include "usart.h" + + +void encoder_setup(){ + if(FLAG(ENC_IS_SSI)) spi_setup(ENCODER_SPI); + else usart_setup(); +} + +// read encoder value into buffer `outbuf` +// return TRUE if all OK +int read_encoder(uint8_t outbuf[4]){ + if(!FLAG(ENC_IS_SSI)) return FALSE; + *((uint32_t*)outbuf) = 0; + return spi_writeread(ENCODER_SPI, outbuf, 4); +} diff --git a/F3:F303/CANbus4BTA/encoder.h b/F3:F303/CANbus4BTA/encoder.h new file mode 100644 index 0000000..e935349 --- /dev/null +++ b/F3:F303/CANbus4BTA/encoder.h @@ -0,0 +1,24 @@ +/* + * This file is part of the canbus4bta project. + * Copyright 2024 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 + +#include + +void encoder_setup(); +int read_encoder(uint8_t outbuf[4]); diff --git a/F3:F303/CANbus4BTA/flash.c b/F3:F303/CANbus4BTA/flash.c index aa869be..0fbe9ed 100644 --- a/F3:F303/CANbus4BTA/flash.c +++ b/F3:F303/CANbus4BTA/flash.c @@ -31,23 +31,23 @@ const uint32_t FLASH_blocksize = (uint32_t)&_BLOCKSIZE; static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here -#define USERCONF_INITIALIZER { \ - .userconf_sz = sizeof(user_conf) \ - ,.CANspeed = 100000 \ - ,.CANID = 0xaa \ - ,.bounce_ms = 50 \ - ,.adcmul[0] = 10.930f \ - ,.adcmul[1] = 2.028f \ - ,.adcmul[2] = 1.f \ - ,.adcmul[3] = 1.f \ - } - static int write2flash(const void*, const void*, uint32_t); // don't write `static` here, or get error: // 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t' const user_conf *Flash_Data = (const user_conf *)(&__varsstart); -user_conf the_conf = USERCONF_INITIALIZER; +user_conf the_conf = { + .userconf_sz = sizeof(user_conf), + .CANspeed = 100000, + .CANID = 0xaa, + .bounce_ms = 50, + .adcmul[0] = 10.930f, + .adcmul[1] = 2.028f, + .adcmul[2] = 1.f, + .adcmul[3] = 1.f, + .usartspeed = 115200, + .flags = FLAGP(ENC_IS_SSI), +}; int currentconfidx = -1; // index of current configuration @@ -179,9 +179,6 @@ int erase_storage(int npage){ FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2; } - /*USB_sendstr("size/block size/nblocks/FLASH_SIZE: "); printu(flsz); - USB_putbyte('/'); printu(FLASH_blocksize); USB_putbyte('/'); - printu(nblocks); USB_putbyte('/'); printu(FLASH_SIZE); newline(); USB_sendall();*/ while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; FLASH->CR |= FLASH_CR_PER; diff --git a/F3:F303/CANbus4BTA/flash.h b/F3:F303/CANbus4BTA/flash.h index 4f5730f..fe0e8a4 100644 --- a/F3:F303/CANbus4BTA/flash.h +++ b/F3:F303/CANbus4BTA/flash.h @@ -28,6 +28,21 @@ #define FLASH_SIZE *((uint16_t*)FLASH_SIZE_BASE) +// bit flags positions +// encoder have SSI (1) or RS-422 (0) +#define ENC_IS_SSI_BIT 0 + +// bit number +#define FLAGBIT(f) (f ## _BIT) +// flag position +#define FLAGP(f) (1 << FLAGBIT(f)) +// flag value +#define FLAG(f) ((the_conf.flags & FLAGP(f)) ? 1 : 0) +// set flag +#define FLAGS(f) do{the_conf.flags |= FLAGP(f);}while(0) +// reset flag +#define FLAGR(f) do{the_conf.flags &= ~FLAGP(f);}while(0) + /* * struct to save user configurations */ @@ -35,8 +50,10 @@ typedef struct __attribute__((packed, aligned(4))){ uint16_t userconf_sz; // "magick number" uint16_t CANID; // identifier uint32_t CANspeed; // default CAN speed - uint32_t bounce_ms; // a + uint32_t bounce_ms; // debounce wait float adcmul[ADC_TSENS]; // ADC voltage multipliers + uint32_t usartspeed; // USART1 speed (baud/s) + uint32_t flags; // bit flags } user_conf; extern user_conf the_conf; // global user config (read from FLASH to RAM) diff --git a/F3:F303/CANbus4BTA/hardware.c b/F3:F303/CANbus4BTA/hardware.c index 2836d52..5989c59 100644 --- a/F3:F303/CANbus4BTA/hardware.c +++ b/F3:F303/CANbus4BTA/hardware.c @@ -49,25 +49,24 @@ TRUE_INLINE void iwdg_setup(){ static 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; USART1 = AF7 @PA9/10; SWD - AF0 @PA13/14 + // PWM - AF1 @PA7; USB - alternate function 14 @ pins PA11/PA12; SWD - AF0 @PA13/14 GPIOA->AFR[0] = AFRf(1, 7); - GPIOA->AFR[1] = AFRf(7, 9) | AFRf(7, 10) | AFRf(14, 11) | AFRf(14, 12); - // PA4 - din (PU in), USART1: PA10(Rx, pullup), PA9(Tx); USB - PA11, PA12; SWDIO - PA13, PA14; PA8 & PA15 - PU in + GPIOA->AFR[1] = AFRf(14, 11) | AFRf(14, 12); + // PA4 - din (PU in); USB - PA11, PA12; SWDIO - PA13, PA14; PA8 & PA15 - PU in GPIOA->PUPDR = (GPIOA->PUPDR & PUPD_CLR(4) & PUPD_CLR(8) & PUPD_CLR(10) & PUPD_CLR(15)) | PUPD_PU(4) | PUPD_PU(8) | PUPD_PU(10) | PUPD_PU(15); GPIOA->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_I(4) | MODER_O(5) | - MODER_O(6) | MODER_AF(7) | MODER_I(8) | MODER_AF(9) | MODER_AF(10) | MODER_AF(11) | + MODER_O(6) | MODER_AF(7) | MODER_I(8) | MODER_AF(11) | MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_I(15); GPIOA->OSPEEDR = OSPEED_HI(4) | OSPEED_MED(7) | OSPEED_MED(9) | OSPEED_MED(10) | OSPEED_HI(11) | OSPEED_HI(12) | OSPEED_HI(13) | OSPEED_HI(14); - // SPI for SSI: AF5 @PB3, PB4; I2C1: AF4 @PB6, PB7; CAN: AF9 @PB8, PB9; SPI2: AF5 @PB12..PB15 + // I2C1: AF4 @PB6, PB7; CAN: AF9 @PB8, PB9; SPI2: AF5 @PB12..PB15 GPIOB->AFR[0] = AFRf(5, 3) | AFRf(5, 4) | AFRf(4, 6) | AFRf(4, 7); - GPIOB->AFR[1] = AFRf(9, 8) | AFRf(9, 9) | AFRf(5, 12) | AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15); + GPIOB->AFR[1] = AFRf(9, 8) | AFRf(9, 9); // PB10,11 - PU in GPIOB->PUPDR = PUPD_PU(10) | PUPD_PU(11); - GPIOB->MODER = MODER_O(0) | MODER_O(1) | MODER_O(2) | MODER_AF(3) | MODER_AF(4) | MODER_AF(6) | MODER_AF(7) | - MODER_AF(8) | MODER_AF(9) | MODER_I(10) | MODER_I(11) | MODER_AF(12) | MODER_AF(13) | - MODER_AF(14) | MODER_AF(15); + GPIOB->MODER = MODER_O(0) | MODER_O(1) | MODER_O(2) | MODER_AF(6) | MODER_AF(7) | + MODER_AF(8) | MODER_AF(9) | MODER_I(10) | MODER_I(11); GPIOB->OSPEEDR = OSPEED_HI(3) | OSPEED_HI(4) | OSPEED_HI(6) | OSPEED_HI(7) | OSPEED_HI(8) | OSPEED_HI(9) | OSPEED_HI(12) | OSPEED_HI(13) | OSPEED_HI(14) | OSPEED_HI(15); GPIOC->MODER = MODER_O(13) | MODER_O(14) | MODER_O(15); @@ -76,7 +75,6 @@ static inline void gpio_setup(){ void hw_setup(){ gpio_setup(); adc_setup(); - //usart_setup(); - power it on only for encoders on RS-422 USB_setup(); #ifndef EBUG iwdg_setup(); diff --git a/F3:F303/CANbus4BTA/hardware.h b/F3:F303/CANbus4BTA/hardware.h index c1138cf..9da78f9 100644 --- a/F3:F303/CANbus4BTA/hardware.h +++ b/F3:F303/CANbus4BTA/hardware.h @@ -41,4 +41,7 @@ extern volatile uint32_t Tms; +// SPI1 is encoder, SPI2 is ext +#define ENCODER_SPI (1) + void hw_setup(); diff --git a/F3:F303/CANbus4BTA/main.c b/F3:F303/CANbus4BTA/main.c index 91aaeb8..56dd9bf 100644 --- a/F3:F303/CANbus4BTA/main.c +++ b/F3:F303/CANbus4BTA/main.c @@ -17,6 +17,7 @@ */ #include "can.h" +#include "encoder.h" #include "flash.h" #include "gpio.h" #include "hardware.h" @@ -60,6 +61,7 @@ int main(void){ hw_setup(); // getSwitches() and set module role & CAN ID CAN_setup(the_conf.CANspeed); + encoder_setup(); USBPU_ON(); while(1){ IWDG->KR = IWDG_REFRESH; diff --git a/F3:F303/CANbus4BTA/proto.h b/F3:F303/CANbus4BTA/proto.h index 677c4f9..186e3f7 100644 --- a/F3:F303/CANbus4BTA/proto.h +++ b/F3:F303/CANbus4BTA/proto.h @@ -64,6 +64,11 @@ typedef enum{ CMD_GETESW_BLK, // 11 - blocking read of ESW CMD_GETESW, // 12 - current ESW state, bounce-free CMD_BOUNCE, // 13 - get/set bounce constant (ms) + CMD_USARTSPEED, // 14 - get/set USART1 speed (if encoder on RS-422) + CMD_ENCISSSI, // 15 - encoder is SSI (1) or RS-422 (0) + CMD_SPIINIT, // 16 - init SPI2 + CMD_SPISEND, // 17 - send 1..4 bytes over SPI + CMD_ENCGET, // 18 - get encoder value CMD_AMOUNT // amount of CAN commands } can_cmd; diff --git a/F3:F303/CANbus4BTA/spi.c b/F3:F303/CANbus4BTA/spi.c new file mode 100644 index 0000000..2026617 --- /dev/null +++ b/F3:F303/CANbus4BTA/spi.c @@ -0,0 +1,198 @@ +/* + * This file is part of the canbus4bta project. + * Copyright 2024 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 "spi.h" + +#include "usb.h" +#ifdef EBUG +#include "strfunc.h" +#endif + +//#define SPIDR *((volatile uint8_t*)&SPI2->DR) + +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) + +// SPI DMA Rx buffer (set by spi_write_dma call) for SPI2 +//static uint8_t *rxbufptr = NULL; +//static uint32_t rxbuflen = 0; + +// init SPI to work with (only SPI2) and without DMA (both) +// Channel 4 - SPI2 Rx +// Channel 5 - SPI2 Tx +void spi_setup(uint8_t idx){ + if(idx > AMOUNT_OF_SPI) return; + volatile SPI_TypeDef *SPI = SPIs[idx]; + SPI->CR1 = 0; // clear EN + SPI->CR2 = 0; + if(idx == 1){ // PB3/PB4, without MOSI; SPI for SSI: AF5 @PB3, PB4 + GPIOB->AFR[0] = (GPIOB->AFR[0] & ~(GPIO_AFRL_AFRL3 | GPIO_AFRL_AFRL4)) | + AFRf(5, 3) | AFRf(5, 4); + GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER3 | GPIO_MODER_MODER4)) | + MODER_AF(3) | MODER_AF(4); + RCC->APB1RSTR = RCC_APB2RSTR_SPI1RST; + RCC->APB1RSTR = 0; // clear reset + RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; + SPI->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_RXONLY; // software slave management (without hardware NSS pin); RX only + }else if(idx == 2){ // PB12..PB15 + GPIOB->AFR[1] = (GPIOB->AFR[1] & ~(GPIO_AFRH_AFRH4 | GPIO_AFRH_AFRH5 | GPIO_AFRH_AFRH6 | GPIO_AFRH_AFRH7)) | + AFRf(5, 12) | AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15); + GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER12 | GPIO_MODER_MODER13 | GPIO_MODER_MODER14 | GPIO_MODER_MODER15)) | + MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_AF(15); + 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 + //SPI->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN; + // Tx + /*DMA1_Channel5->CPAR = (uint32_t)&(SPI2->DR); // hardware + DMA1_Channel5->CCR = DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TEIE; // memory increment, mem->hw, error interrupt + // Rx + DMA1_Channel4->CPAR = (uint32_t)&(SPI2->DR); + DMA1_Channel4->CCR = DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE; // mem inc, hw->mem, Rx complete and error interrupt + NVIC_EnableIRQ(DMA1_Channel4_IRQn); // enable Rx interrupt + NVIC_EnableIRQ(DMA1_Channel5_IRQn); // enable Tx interrupt + */ + }else return; // err + // Baudrate = 0b110 - fpclk/128 + SPI->CR1 |= SPI_CR1_MSTR | SPI_CR1_BR_2 | SPI_CR1_BR_1; + // DS=8bit; RXNE generates after 8bit of data in FIFO; + SPI->CR2 |= SPI_CR2_FRXTH | SPI_CR2_DS_2|SPI_CR2_DS_1|SPI_CR2_DS_0; + spi_status[idx] = SPI_READY; + SPI->CR1 |= SPI_CR1_SPE; + DBG("SPI works"); +} + +int spi_waitbsy(uint8_t idx){ + if(idx > AMOUNT_OF_SPI) return 0; + WAITX(SPIs[idx]->SR & SPI_SR_BSY); + return 1; +} + +/** + * @brief spi_writeread - send data over SPI (change data array with received bytes) + * @param data - data to write/read + * @param n - length of data + * @return 0 if failed + */ +int spi_writeread(uint8_t idx, uint8_t *data, uint32_t n){ + if(idx > AMOUNT_OF_SPI) return 0; + if(spi_status[idx] != SPI_READY || !data || !n){ + DBG("not ready"); + return 0; + } + for(uint32_t x = 0; x < n; ++x){ + WAITX(!(SPIs[idx]->SR & SPI_SR_TXE)); + *((volatile uint8_t*)&SPIs[idx]->DR) = data[x]; + WAITX(!(SPIs[idx]->SR & SPI_SR_RXNE)); + data[x] = *((volatile uint8_t*)&SPIs[idx]->DR); + } + return 1; +} + +/** + * @brief spi_send_dma - send data over SPI2 through DMA (used both for writing and reading) + * @param data - data to read + * @param rxbuf - pointer to receiving buffer (at least n bytes), can be also `data` (if `data` isn't const) + * @param n - length of data + * @return 0 if failed + * !!! `data` buffer can be changed only after SPI_READY flag! + */ +/*int spi_write_dma(const uint8_t *data, uint8_t *rxbuf, uint32_t n){ + if(spi_status[2] != SPI_READY) return 0; + if(!spi_waitbsy(2)) return 0; + rxbufptr = rxbuf; + rxbuflen = n; + // spi_setup(); - only so we can clear Rx FIFO! + DMA1_Channel5->CMAR = (uint32_t) data; + DMA1_Channel5->CNDTR = n; + // check if user want to receive data + if(rxbuf){ + DMA1_Channel4->CCR |= DMA_CCR_TCIE; + DMA1_Channel5->CCR &= ~DMA_CCR_TCIE; // turn off Tx ready interrupt + DMA1_Channel4->CMAR = (uint32_t) rxbuf; + DMA1_Channel4->CNDTR = n; + DMA1_Channel4->CCR |= DMA_CCR_EN; // turn on reception + }else DMA1_Channel5->CCR |= DMA_CCR_TCIE; // interrupt by Tx ready - user don't want reception + spi_status[2] = SPI_BUSY; + DMA1_Channel5->CCR |= DMA_CCR_EN; // turn on transmission + return 1; +}*/ + +/** + * @brief spi_read - read SPI2 data + * @param data - data to read + * @param n - length of data + * @return n + */ +/* +int spi_read(uint8_t idx, uint8_t *data, uint32_t n){ + if(idx > AMOUNT_OF_SPI) return 0; + if(spi_status[idx] != SPI_READY){ + DBG("not ready"); + return 0; + } + if(!spi_waitbsy(idx)) return 0; + // clear SPI Rx FIFO + for(int i = 0; i < 4; ++i) (void) SPIs[idx]->DR; + for(uint32_t x = 0; x < n; ++x){ + WAITX(!(SPIs[idx]->SR & SPI_SR_TXE)); + *((volatile uint8_t*)&SPIs[idx]->DR) = 0; + WAITX(!(SPIs[idx]->SR & SPI_SR_RXNE)); + data[x] = *((volatile uint8_t*)&SPIs[idx]->DR); + //USB_sendstr("rd got "); USB_sendstr(uhex2str(data[x])); + newline(); + } + return 1; +}*/ + +/** + * @brief spi_read_dma - got buffer read by DMA + * @param n (o) - length of rxbuffer + * @return amount of bytes read + */ +/*uint8_t *spi_read_dma(uint32_t *n){ + if(spi_status[2] != SPI_READY || rxbuflen == 0) return NULL; + if(n) *n = rxbuflen - DMA1_Channel4->CNDTR; // in case of error buffer would be underfull + rxbuflen = 0; // prevent consequent readings + return rxbufptr; +}*/ + +/* +// Rx ready interrupt +void dma1_channel4_isr(){ + spi_status[2] = SPI_READY; // ready independent on errors or Rx ready + DMA1->IFCR = DMA_IFCR_CTCIF4 | DMA_IFCR_CTEIF4; + // turn off DMA + DMA1_Channel4->CCR &= ~DMA_CCR_EN; + DMA1_Channel5->CCR &= ~DMA_CCR_EN; +} + +// Tx ready interrupt +void dma1_channel5_isr(){ + spi_status[2] = SPI_READY; // ready independent on errors or Tx ready + DMA1->IFCR = DMA_IFCR_CTCIF5 | DMA_IFCR_CTEIF5; + // turn off DMA + DMA1_Channel4->CCR &= ~DMA_CCR_EN; + DMA1_Channel5->CCR &= ~DMA_CCR_EN; +} +*/ diff --git a/F3:F303/CANbus4BTA/spi.h b/F3:F303/CANbus4BTA/spi.h new file mode 100644 index 0000000..e617fa6 --- /dev/null +++ b/F3:F303/CANbus4BTA/spi.h @@ -0,0 +1,37 @@ +/* + * This file is part of the canbus4bta project. + * Copyright 2024 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 +#include + +#define AMOUNT_OF_SPI (2) + +typedef enum{ + SPI_NOTREADY, + SPI_READY, + SPI_BUSY +} spiStatus; + +extern spiStatus spi_status[AMOUNT_OF_SPI+1]; + +void spi_setup(uint8_t idx); +int spi_waitbsy(uint8_t idx); +int spi_writeread(uint8_t idx, uint8_t *data, uint32_t n); +//int spi_write_dma(const uint8_t *data, uint8_t *rxbuf, uint32_t n); +//int spi_read(uint8_t idx, uint8_t *data, uint32_t n); +//uint8_t *spi_read_dma(uint32_t *n); diff --git a/F3:F303/CANbus4BTA/textfunctions.c b/F3:F303/CANbus4BTA/textfunctions.c index d1615e4..bf6638c 100644 --- a/F3:F303/CANbus4BTA/textfunctions.c +++ b/F3:F303/CANbus4BTA/textfunctions.c @@ -66,6 +66,7 @@ static const funcdescr funclist[] = { {"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)"}, {"wdtest", -TCMD_WDTEST, "test watchdog"}, {NULL, 0, NULL} // last record @@ -79,6 +80,12 @@ static errcodes wdtest(const char _U_ *str){ return ERR_OK; } +// names of bit flags (ordered from LSE of[0]) +static const char * const bitfields[] = { + "encisSSI", + NULL +}; + static errcodes dumpconf(const char _U_ *str){ #ifdef EBUG uint32_t sz = FLASH_SIZE*1024; @@ -95,6 +102,15 @@ static errcodes dumpconf(const char _U_ *str){ USB_sendstr("\nadcmul"); USB_putbyte('0'+i); USB_putbyte('='); USB_sendstr(float2str(the_conf.adcmul[i], 3)); } + USB_sendstr("\nusartspeed="); printu(the_conf.usartspeed); + const char * const *p = bitfields; + int bit = 0; + while(p){ + newline(); + USB_sendstr(*p); USB_putbyte('='); USB_putbyte((the_conf.flags & (1< 31) break; + ++p; + } //#define PROPNAME(nm) do{newline(); USB_sendstr(nm); USB_putbyte(cur); USB_putbyte('=');}while(0) //#undef PROPNAME newline(); diff --git a/F3:F303/CANbus4BTA/usart.c b/F3:F303/CANbus4BTA/usart.c index e0c14b8..40b84d0 100644 --- a/F3:F303/CANbus4BTA/usart.c +++ b/F3:F303/CANbus4BTA/usart.c @@ -16,8 +16,9 @@ * along with this program. If not, see . */ -#include "stm32f3.h" +#include #include "hardware.h" +#include "flash.h" #include "usart.h" #include @@ -64,11 +65,16 @@ void usart_send(const char *str){ usart_sendn(str, L); } +// 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)) | + AFRf(7, 9) | AFRf(7, 10); RCC->APB2ENR |= RCC_APB2ENR_USART1EN; USART1->ICR = 0xffffffff; // clear all flags - USART1->BRR = SysFreq / 115200; + USART1->BRR = SysFreq / the_conf.usartspeed; USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE | USART_CR1_RXNEIE; // 1start,8data,nstop; enable Rx,Tx,USART uint32_t tmout = 16000000; while(!(USART1->ISR & USART_ISR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission diff --git a/F3:F303/CANbus4BTA/version.inc b/F3:F303/CANbus4BTA/version.inc index 7893c4b..cb5140d 100644 --- a/F3:F303/CANbus4BTA/version.inc +++ b/F3:F303/CANbus4BTA/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "68" -#define BUILD_DATE "2024-01-08" +#define BUILD_NUMBER "80" +#define BUILD_DATE "2024-03-07"