max31865 pooling - not finished, some tweaks and comments for spi driver

tatry_variant
Mateusz Lubecki 2022-10-03 21:43:08 +02:00
rodzic 37c76aeb1d
commit f094422d92
6 zmienionych plików z 262 dodań i 128 usunięć

Wyświetl plik

@ -152,8 +152,6 @@ void SysTick_Handler(void) {
i2cKeepTimeout();
spi_timeout_handler();
delay_decrement_counter();
if (it_handlers_inhibit_radiomodem_dcd_led == 0) {

Wyświetl plik

@ -1430,6 +1430,8 @@ int main(int argc, char* argv[]){
wx_check_force_i2c_reset();
max31865_pool();
#ifdef INTERNAL_WATCHDOG
IWDG_ReloadCounter();
#endif

Wyświetl plik

@ -20,7 +20,7 @@ typedef enum max31865_qf_t {
}max31865_qf_t;
void max31865_init(uint8_t rdt_type);
void max31865_start_measurement(void);
void max31865_pool(void);
int32_t max31865_get_result(max31865_qf_t * quality_factor);

Wyświetl plik

@ -1,5 +1,9 @@
/*
* spi_stm32l4x.h
* spi.h
*
* This is a general interface of SPI driver. Please read notes
* in platform specific implementation. Each of them might have
* it's own limitations
*
* Created on: Sep 22, 2022
* Author: mateusz
@ -10,13 +14,19 @@
#include <stdint.h>
#define SPI_OK 0
#define SPI_BUSY_DIFF_SLAVE 10
#define SPI_BUSY 11
#define SPI_TX_DATA_TO_LONG 20
#define SPI_WRONG_SLAVE_ID 30
#define SPI_UKNOWN 255
/**
* Return codes
*/
#define SPI_OK 0 //!< Function has succeeded
#define SPI_BUSY_DIFF_SLAVE 10 //!< Communication has been requested for different slave than what transmission is ongoing for
#define SPI_BUSY 11 //!< SPI bus is currently busy and cannot be used for requested operation
#define SPI_TX_DATA_TO_LONG 20 //!< requested data is too long to fit in internal SPI tx buffer
#define SPI_WRONG_SLAVE_ID 30 //!< unknown SPI slave (missing chip select mapping)
#define SPI_UKNOWN 255 //!< undesignated SPI error
/**
* SPI transfer mode using for initialization
*/
typedef enum spi_transfer_mode_t {
SPI_MASTER_MOTOROLA,
SPI_MASTER_TI,
@ -24,26 +34,39 @@ typedef enum spi_transfer_mode_t {
SPI_SLAVE_TI
}spi_transfer_mode_t;
/**
* SPI clock mode using for initialization, look at CPOL and CPHA values for each enum values.
*/
typedef enum spi_clock_polarity_strobe_t {
CLOCK_NORMAL_FALLING, // CPOL 0, CPHA 1
CLOCK_NORMAL_RISING, // CPOL 0, CPHA 0
CLOCK_REVERSED_FALLING, // CPOL 1, CPHA 0
CLOCK_REVERSED_RISING // CPOL 1, CPHA 1
CLOCK_NORMAL_FALLING, //!< CPOL 0, CPHA 1
CLOCK_NORMAL_RISING, //!< CPOL 0, CPHA 0
CLOCK_REVERSED_FALLING, //!< CPOL 1, CPHA 0
CLOCK_REVERSED_RISING //!< CPOL 1, CPHA 1
}spi_clock_polarity_strobe_t;
#define SPI_ENDIAN_LSB 0
#define SPI_ENDIAN_MSB 1
#define SPI_TX_FROM_INTERNAL 1
#define SPI_TX_FROM_EXTERNAL 2
#define SPI_USE_INTERNAL_RX_BUF 0
/**
* Current SPI reception state
*/
typedef enum spi_rx_state_t {
SPI_RX_IDLE, // SPI is configured and ready for operation
SPI_RX_RXING, // SPI is currently receiving
SPI_RX_DONE, // Reception is done
SPI_RX_WAITING_FOR_RX, // SPI is currently transmitting and reception is queued
SPI_RX_ERROR_OVERRUN, // Overrun had been detected and reception was terminated
SPI_RX_IDLE, //!< SPI is configured and ready for operation
SPI_RX_RXING, //!< SPI is currently receiving
SPI_RX_DONE, //!< Reception is done
SPI_RX_WAITING_FOR_RX, //!< SPI is currently transmitting and reception is queued
SPI_RX_ERROR_OVERRUN, //!< Overrun had been detected and reception was terminated
SPI_RX_ERROR_MODF,
SPI_RX_ERROR_TIMEOUT // Timeout has been detected
}spi_rx_state_t;
/**
* Current SPI transmission state
*/
typedef enum spi_tx_state_t {
SPI_TX_IDLE,
SPI_TX_TXING,
@ -51,21 +74,30 @@ typedef enum spi_tx_state_t {
SPI_TX_ERROR_MODF
}spi_tx_state_t;
#define SPI_TIMEOUT_MSEC 100
//! This function initializes SPI bus to work as full duplex two-wire connection, w/o DMA data flow
uint8_t spi_init_full_duplex_pio(spi_transfer_mode_t mode, spi_clock_polarity_strobe_t strobe, int speed, int endianess);
uint8_t spi_rx_data(uint32_t slave_id, uint8_t * rx_buffer, uint16_t ln_to_rx);
uint8_t spi_tx_data(uint32_t slave_id, uint8_t * tx_buffer, uint16_t ln_to_tx);
uint8_t spi_rx_tx_data(uint32_t slave_id, uint8_t * rx_buffer, uint8_t * tx_buffer, uint16_t ln_to_rx, uint16_t ln_to_tx);
//! Sends data asynchronously to selected SPI slave, discards anything what will come in over MISO line
uint8_t spi_tx_data(uint32_t slave_id, uint8_t tx_from_internal, uint8_t * tx_buffer, uint16_t ln_to_tx);
//! Sends data synchronously to selected slave and after that receives data from it. Everything received before TX is finish is discarded.
uint8_t spi_rx_tx_data(uint32_t slave_id, uint8_t tx_from_internal, uint8_t * rx_buffer, uint8_t * tx_buffer, uint16_t ln_to_rx, uint16_t ln_to_tx);
//! Returns pointer to receive buffer and if reception is done resets RX state back to idle.
uint8_t * spi_get_rx_data(void);
//! Blocking wait until both RX and TX is done
uint8_t spi_wait_for_comms_done(void);
//! Resets all errors and reverts state back to IDLE
void spi_reset_errors(void);
void spi_irq_handler(void);
void spi_timeout_handler(void);
spi_rx_state_t spi_get_rx_state(void);
spi_tx_state_t spi_get_tx_state(void);
void spi_enable(uint8_t cs_assert);
void spi_disable(uint8_t immediately);
//! Returns an ID of current SPI slave or zero if SPI is idle
uint32_t spi_get_current_slave(void);
void spi_irq_handler(void);
#endif /* INCLUDE_DRIVERS_SPI_H_ */

Wyświetl plik

@ -1,6 +1,9 @@
/*
* spi_stm32l4xx.c
*
* This module consist an implementation of SPI driver for STM32L4xx micro, but with some
* limitations over what this micro actually supports.
*
* Created on: Sep 22, 2022
* Author: mateusz
*/
@ -81,11 +84,6 @@ uint8_t * spi_tx_buffer_ptr;
*/
uint8_t spi_garbage;
/**
* Timestamp when receiving has been initiated
*/
uint32_t spi_timestamp_rx_start;
/**
* How many bytes has been discarded into garbage storage
*/
@ -93,6 +91,65 @@ uint8_t spi_garbage_counter = 0;
EVAL_SLAVE_ARR
static void spi_enable(uint8_t cs_assert) {
// delay between asserting chip select and starting SPI
volatile int delay = 0;
SPI2->CR2 |= SPI_CR2_ERRIE;
SPI2->CR2 |= SPI_CR2_RXNEIE;
SPI2->CR2 |= SPI_CR2_TXEIE;
if (cs_assert != 0) {
LL_GPIO_ResetOutputPin((GPIO_TypeDef *)spi_slaves_cfg[spi_current_slave - 1][1], spi_slaves_cfg[spi_current_slave - 1][2]);
// delay required by CS to SCLK Setup (MAX31865)
for (delay = 0; delay < SPI_CS_TO_SCLK_SETUP_DELAY; delay++);
}
LL_SPI_Enable(SPI2);
}
/**
* This function will disable SPI and close bus communication, optionally
* it can wait until the peripheral will be released
*/
static void spi_disable(uint8_t immediately) {
if (immediately == 0) {
while ((SPI2->SR & SPI_SR_BSY) != 0);
LL_GPIO_SetOutputPin((GPIO_TypeDef *)spi_slaves_cfg[spi_current_slave - 1][1], spi_slaves_cfg[spi_current_slave - 1][2]);
LL_SPI_Disable(SPI2);
// disable all interrupts
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_ERRIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_RXNEIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_TXEIE);
if ((SPI2->SR & SPI_SR_RXNE) != 0) {
// clear RX fifo queue
do {
spi_garbage_counter++;
spi_garbage = SPI2->DR & 0xFF;
} while ((SPI2->SR & SPI_SR_RXNE) != 0);
}
}
else {
LL_GPIO_SetOutputPin((GPIO_TypeDef *)spi_slaves_cfg[spi_current_slave - 1][1], spi_slaves_cfg[spi_current_slave - 1][2]);
// disable all interrupts
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_ERRIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_RXNEIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_TXEIE);
LL_SPI_Disable(SPI2);
}
}
uint8_t spi_init_full_duplex_pio(spi_transfer_mode_t mode, spi_clock_polarity_strobe_t strobe, int speed, int endianess) {
LL_GPIO_InitTypeDef GPIO_InitTypeDef;
@ -290,7 +347,7 @@ uint8_t spi_rx_data(uint32_t slave_id, uint8_t * rx_buffer, uint16_t ln_to_rx) {
/**
* Initiate tx only transaction. Data will be sent to chosen slave, any receive data will be discarded
*/
uint8_t spi_tx_data(uint32_t slave_id, uint8_t * tx_buffer, uint16_t ln_to_tx) {
uint8_t spi_tx_data(uint32_t slave_id, uint8_t tx_from_internal, uint8_t * tx_buffer, uint16_t ln_to_tx) {
uint8_t out = SPI_UKNOWN;
@ -318,7 +375,7 @@ uint8_t spi_tx_data(uint32_t slave_id, uint8_t * tx_buffer, uint16_t ln_to_tx) {
spi_current_tx_cntr = 0;
// check if external or internal buffer shall be used
if (tx_buffer == 0) {
if (tx_from_internal == SPI_TX_FROM_INTERNAL) {
spi_tx_buffer_ptr = spi_tx_buffer;
// check if internal buffer has enought room for data
@ -358,10 +415,11 @@ uint8_t spi_tx_data(uint32_t slave_id, uint8_t * tx_buffer, uint16_t ln_to_tx) {
/**
* Initiate full duplex communication with the slave. After this call the SPI bus
* will be enabled and all data from tx_buffer will be send. SPI bus will be disabled
* after requested amount of data will be received or timeout occured.
* will be enabled and all data from tx_buffer will be send. After transmitting all bytes
* the master will transmit 0xFF on MOSI in the loop, until requested number of bytes
* will be received. Then SPI is disabled
*/
uint8_t spi_rx_tx_data(uint32_t slave_id, uint8_t * rx_buffer, uint8_t * tx_buffer, uint16_t ln_to_rx, uint16_t ln_to_tx) {
uint8_t spi_rx_tx_data(uint32_t slave_id, uint8_t tx_from_internal, uint8_t * rx_buffer, uint8_t * tx_buffer, uint16_t ln_to_rx, uint16_t ln_to_tx) {
uint8_t out = SPI_UKNOWN;
@ -404,7 +462,7 @@ uint8_t spi_rx_tx_data(uint32_t slave_id, uint8_t * rx_buffer, uint8_t * tx_buff
}
// check if external TX buffer shall be user or not
if (tx_buffer == 0) {
if (tx_from_internal == SPI_TX_FROM_INTERNAL) {
spi_tx_buffer_ptr = spi_tx_buffer;
// check if internal buffer has enought room for data
@ -432,9 +490,6 @@ uint8_t spi_rx_tx_data(uint32_t slave_id, uint8_t * rx_buffer, uint8_t * tx_buff
spi_tx_bytes_rq = ln_to_tx;
}
// latch a timestamp when reception has been triggered
spi_timestamp_rx_start = master_time;
// // set first byte for transmission
// SPI2->DR = spi_tx_buffer_ptr[0];
@ -485,11 +540,28 @@ uint8_t spi_wait_for_comms_done(void) {
}
void spi_reset_errors(void) {
if (spi_rx_state == SPI_RX_ERROR_MODF || spi_rx_state == SPI_RX_ERROR_OVERRUN || spi_rx_state == SPI_RX_ERROR_TIMEOUT) {
if (spi_rx_state == SPI_RX_ERROR_MODF || spi_rx_state == SPI_RX_ERROR_OVERRUN) {
spi_rx_state = SPI_RX_IDLE;
}
}
spi_rx_state_t spi_get_rx_state(void) {
return spi_rx_state;
}
spi_tx_state_t spi_get_tx_state(void) {
return spi_tx_state;
}
uint32_t spi_get_current_slave(void) {
if (spi_rx_state != SPI_RX_RXING && spi_tx_state != SPI_TX_TXING) {
return 0;
}
else {
return spi_current_slave;
}
}
void spi_irq_handler(void) {
// The RXNE flag is set depending on the FRXTH bit value in the SPIx_CR2 register:
@ -636,77 +708,3 @@ void spi_irq_handler(void) {
spi_disable(1);
}
}
/**
* This function should be caller from SysTick Interrupt
*/
void spi_timeout_handler(void) {
if (spi_rx_state == SPI_RX_RXING) {
if (master_time - spi_timestamp_rx_start > SPI_RX_ERROR_TIMEOUT) {
spi_rx_state = SPI_RX_ERROR_TIMEOUT;
spi_tx_state = SPI_TX_IDLE;
spi_disable(1);
}
}
}
void spi_enable(uint8_t cs_assert) {
// delay between asserting chip select and starting SPI
volatile int delay = 0;
SPI2->CR2 |= SPI_CR2_ERRIE;
SPI2->CR2 |= SPI_CR2_RXNEIE;
SPI2->CR2 |= SPI_CR2_TXEIE;
if (cs_assert != 0) {
LL_GPIO_ResetOutputPin((GPIO_TypeDef *)spi_slaves_cfg[spi_current_slave - 1][1], spi_slaves_cfg[spi_current_slave - 1][2]);
// delay required by CS to SCLK Setup (MAX31865)
for (delay = 0; delay < SPI_CS_TO_SCLK_SETUP_DELAY; delay++);
}
LL_SPI_Enable(SPI2);
}
/**
* This function will disable SPI and close bus communication, optionally
* it can wait until the peripheral will be released
*/
void spi_disable(uint8_t immediately) {
if (immediately == 0) {
while ((SPI2->SR & SPI_SR_BSY) != 0);
LL_GPIO_SetOutputPin((GPIO_TypeDef *)spi_slaves_cfg[spi_current_slave - 1][1], spi_slaves_cfg[spi_current_slave - 1][2]);
LL_SPI_Disable(SPI2);
// disable all interrupts
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_ERRIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_RXNEIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_TXEIE);
if ((SPI2->SR & SPI_SR_RXNE) != 0) {
// clear RX fifo queue
do {
spi_garbage_counter++;
spi_garbage = SPI2->DR & 0xFF;
} while ((SPI2->SR & SPI_SR_RXNE) != 0);
}
}
else {
LL_GPIO_SetOutputPin((GPIO_TypeDef *)spi_slaves_cfg[spi_current_slave - 1][1], spi_slaves_cfg[spi_current_slave - 1][2]);
// disable all interrupts
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_ERRIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_RXNEIE);
SPI2->CR2 &= (0xFFFFFFFF ^ SPI_CR2_TXEIE);
LL_SPI_Disable(SPI2);
}
}

Wyświetl plik

@ -7,6 +7,26 @@
#include "drivers/max31865.h"
typedef enum max31865_pool_state_t {
MAX_IDLE,
MAX_INITIALIZED,
MAX_ERROR,
MAX_MEASUREMENT_STARTED,
MAX_REGISTER_REQUESTED,
MAX_SHUTDOWN,
MAX_POWER_OFF
}max31865_pool_state_t;
max31865_pool_state_t max31865_current_state = MAX_IDLE;
/**
* This variable is incremented from 0 up to 9 to pause measurement
* state machine into MAX_SHUTDOWN state. When it reach 9 measurement
* is triggered
*/
uint8_t max31865_shutdown_ticks = 0;
/**
* 1 - bias on
* 0 - bias on
@ -48,6 +68,9 @@ uint8_t max31865_filter_select = 0;
uint8_t max31865_buffer[3] = {0u};
/**
* Set to one if MAX has been initialized correctly
*/
uint8_t max31865_ok = 0;
/**
@ -68,8 +91,44 @@ static uint8_t max31865_get_config_register(void) {
return out;
}
static void max31865_request_registers(void) {
uint8_t result = 0;
// check if SPI is busy now
if (spi_get_current_slave() == 0) {
// read adres of configuation register
max31865_buffer[0] = 0x00;
max31865_buffer[1] = 0x00;
// read data for verifiaction
result = spi_rx_tx_data(1, SPI_TX_FROM_EXTERNAL, SPI_USE_INTERNAL_RX_BUF, max31865_buffer, 10, 1);
}
else {
max31865_current_state = MAX_ERROR;
}
}
static void max31865_send_config_measurement(void) {
uint8_t result = 0;
// check if SPI is busy now
if (spi_get_current_slave() == 0) {
// read adres of configuation register
max31865_buffer[0] = 0x80;
max31865_buffer[1] = max31865_get_config_register();
spi_tx_data(1, SPI_TX_FROM_EXTERNAL, max31865_buffer, 2);
}
else {
max31865_current_state = MAX_ERROR;
}
}
void max31865_init(uint8_t rdt_type) {
uint8_t * rx_data;
if (rdt_type == MAX_3WIRE) {
max31865_rdt_sensor_type = 1;
}
@ -84,30 +143,75 @@ void max31865_init(uint8_t rdt_type) {
max31865_conversion_mode = 1;
max31865_buffer[0] = 0x80;
max31865_buffer[1] = max31865_get_config_register();
// max31865_buffer[0] = 0x80;
// max31865_buffer[1] = max31865_get_config_register();
//
// spi_tx_data(1, SPI_TX_FROM_EXTERNAL, max31865_buffer, 2);
spi_tx_data(1, max31865_buffer, 2);
max31865_send_config_measurement();
spi_wait_for_comms_done();
// read adres of configuation register
max31865_buffer[0] = 0x00;
max31865_buffer[1] = 0x00;
// // read adres of configuation register
// max31865_buffer[0] = 0x00;
// max31865_buffer[1] = 0x00;
//
// // read data for verifiaction
// spi_rx_tx_data(1, SPI_TX_FROM_EXTERNAL, SPI_USE_INTERNAL_RX_BUF, max31865_buffer, 30, 1);
// read data for verifiaction
spi_rx_tx_data(1, 0, max31865_buffer, 30, 1);
max31865_request_registers();
spi_wait_for_comms_done();
if (max31865_buffer[0] == max31865_get_config_register()) {
rx_data = spi_get_rx_data();
if (rx_data[0] == max31865_get_config_register()) {
max31865_ok = 1;
}
else {
max31865_ok = 0;
}
}
void max31865_start_measurement(void) {
/**
* This pooler shall be called in two seconds interval
*/
void max31865_pool(void) {
switch (max31865_current_state) {
case MAX_IDLE:
// MAX31865 is powered up but not initialized
if (max31865_rdt_sensor_type == 1) {
max31865_init(MAX_3WIRE);
}
else {
max31865_init(MAX_4WIRE);
}
max31865_current_state = MAX_INITIALIZED;
break;
case MAX_INITIALIZED:
// initialized and ready to start measurement
max31865_start_singleshot = 1;
break;
case MAX_ERROR:
break;
case MAX_MEASUREMENT_STARTED:
break;
case MAX_REGISTER_REQUESTED:
break;
case MAX_SHUTDOWN:
// MAX31965 is powered up and initialized but PT bias is disabled
// and no measurement is ongoing
break;
case MAX_POWER_OFF:
// supply voltage for MAX31865 is powered off and no communication
// is currently possible
break;
}
}
int32_t max31865_get_result(max31865_qf_t * quality_factor) {