Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added initial support to STM32 (using CubeHAL API). #863

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions RF24.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ void RF24::csn(bool mode)
#endif // defined(RF24_RPi)

#if !defined(RF24_LINUX)
#if defined(STM32)
HAL_GPIO_WritePin(csn_port, csn_pin, mode ? GPIO_PIN_SET : GPIO_PIN_RESET);
#else
digitalWrite(csn_pin, mode);
#endif
delayMicroseconds(csDelay);
#else
static_cast<void>(mode); // ignore -Wunused-parameter
Expand All @@ -104,7 +108,11 @@ void RF24::ce(bool level)
{
//Allow for 3-pin use on ATTiny
if (ce_pin != csn_pin) {
#if defined(STM32)
HAL_GPIO_WritePin(ce_port, ce_pin, level ? GPIO_PIN_SET : GPIO_PIN_RESET);
#else
digitalWrite(ce_pin, level);
#endif
}
}

Expand Down Expand Up @@ -593,7 +601,7 @@ void RF24::_init_obj()
{
// Use a pointer on the Arduino platform

#if defined(RF24_SPI_PTR) && !defined(RF24_RP2)
#if defined(RF24_SPI_PTR) && !defined(RF24_RP2) && !defined(STM32)
_spi = &SPI;
#endif // defined (RF24_SPI_PTR)

Expand Down Expand Up @@ -945,7 +953,7 @@ void RF24::encodeRadioDetails(uint8_t* encoded_details)
#endif // !defined(MINIMAL)

/****************************************************************************/
#if defined(RF24_SPI_PTR) || defined(DOXYGEN_FORCED)
#if (defined(RF24_SPI_PTR) || defined(DOXYGEN_FORCED)) && !defined(STM32)
// does not apply to RF24_LINUX

bool RF24::begin(_SPI* spiBus)
Expand All @@ -967,6 +975,20 @@ bool RF24::begin(_SPI* spiBus, uint16_t _cepin, uint16_t _cspin)

/****************************************************************************/

#if defined(STM32)
bool RF24::begin(SPI_HandleTypeDef * spiBus, uint16_t _cepin, GPIO_TypeDef* _ceport, uint16_t _cspin, GPIO_TypeDef* _csport)
{
ce_pin = _cepin;
ce_port = _ceport;
csn_pin = _cspin;
csn_port = _csport;
_spi = new DummySpi(spiBus);
return begin();
}
#endif

/****************************************************************************/

bool RF24::begin(uint16_t _cepin, uint16_t _cspin)
{
ce_pin = _cepin;
Expand Down Expand Up @@ -1001,6 +1023,11 @@ bool RF24::begin(void)
#elif defined(RF24_RP2)
_spi->begin(PICO_DEFAULT_SPI ? spi1 : spi0);

#elif defined(STM32)
// you should configure the spi handler outside because your microcontroller may have more than one spi bus
_spi->begin();
spi_speed = _spi->get_baud();

#else // using an Arduino platform || defined (LITTLEWIRE)

#if defined(RF24_SPI_PTR)
Expand Down Expand Up @@ -1046,6 +1073,21 @@ bool RF24::_init_pins()
csn(HIGH);
delay(200);

#elif defined(STM32)
if (ce_pin != csn_pin) {
GPIO_InitTypeDef gpio;
gpio.Speed = GPIO_SPEED_FREQ_HIGH;
gpio.Mode = GPIO_MODE_OUTPUT_PP;
gpio.Pull = GPIO_NOPULL;
gpio.Pin = ce_pin;
HAL_GPIO_Init(ce_port, &gpio);
gpio.Pin = csn_pin;
HAL_GPIO_Init(csn_port, &gpio);
}

ce(LOW);
csn(HIGH);

#else // using an Arduino platform

// Initialize pins
Expand Down
35 changes: 34 additions & 1 deletion RF24.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ class RF24

uint16_t ce_pin; /* "Chip Enable" pin, activates the RX or TX role */
uint16_t csn_pin; /* SPI Chip select */

#if defined(STM32)
GPIO_TypeDef* ce_port;
GPIO_TypeDef* csn_port;
#endif

uint32_t spi_speed; /* SPI Bus Speed */
#if defined(RF24_LINUX) || defined(XMEGA_D3) || defined(RF24_RP2)
uint8_t spi_rxbuff[32 + 1]; //SPI receive buffer (payload max 32 bytes)
Expand Down Expand Up @@ -242,7 +248,7 @@ class RF24
*/
bool begin(void);

#if defined(RF24_SPI_PTR) || defined(DOXYGEN_FORCED)
#if (defined(RF24_SPI_PTR) || defined(DOXYGEN_FORCED)) && !defined(STM32)
/**
* Same as begin(), but allows specifying a non-default SPI bus to use.
*
Expand Down Expand Up @@ -284,6 +290,33 @@ class RF24
bool begin(_SPI* spiBus, uint16_t _cepin, uint16_t _cspin);
#endif // defined (RF24_SPI_PTR) || defined (DOXYGEN_FORCED)

#if defined(STM32)
/**
* Same as begin(), but allows dynamically specifying a SPI bus, CE pin,
* and CSN pin to use.
*
* @note This function assumes the `SPI::begin()` method was called before to
* calling this function.
*
* @warning This function is for the Arduino platforms only
*
* @param spiBus A pointer or reference to an instantiated SPI bus object.
* The `_SPI` datatype is a "wrapped" definition that will represent
* various SPI implementations based on the specified platform.
* @param _cepin The pin attached to Chip Enable on the RF module.
* @param _ceport The handle object associated with the pin attached to Chip Enable on the RF module.
* @param _cspin The pin attached to Chip Select (often labeled CSN) on the radio module.
* @param _csport The handle object associated with the pin attached to Chip Select (often labeled CSN) on the radio module.
* - For the Arduino Due board, the [Arduino Due extended SPI feature](https://www.arduino.cc/en/Reference/DueExtendedSPI)
* is not supported. This means that the Due's pins 4, 10, or 52 are not mandated options (can use any digital output pin) for the radio's CSN pin.
*
* @see Review the [Arduino support page](md_docs_arduino.html).
*
* @return same result as begin()
*/
bool begin(SPI_HandleTypeDef * spiBus, uint16_t _cepin, GPIO_TypeDef* _ceport, uint16_t _cspin, GPIO_TypeDef* _csport);
#endif

/**
* Same as begin(), but allows dynamically specifying a CE pin
* and CSN pin to use.
Expand Down
9 changes: 9 additions & 0 deletions RF24_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@
#include "utility/rp2/RF24_arch_config.h"
#define sprintf_P sprintf

#elif (defined(STM32))
#include "utility/stm32/RF24_arch_config.h"

#ifdef SERIAL_DEBUG
#define IF_SERIAL_DEBUG(x) ({ x; })
#else
#define IF_SERIAL_DEBUG(x)
#endif // SERIAL_DEBUG

#elif (!defined(ARDUINO)) // Any non-arduino device is handled via configure/Makefile
// The configure script detects device and copies the correct includes.h file to /utility/includes.h
// This behavior can be overridden by calling configure with respective parameters
Expand Down
99 changes: 99 additions & 0 deletions utility/STM32/RF24_arch_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#ifndef RF24_UTILITY_STM32_RF24_ARCH_CONFIG_H
#define RF24_UTILITY_STM32_RF24_ARCH_CONFIG_H


#include <cstdint>
#include <memory.h>


#if defined(STM32F0)
#include "stm32f0xx_hal.h"
#elif defined(STM32F1)
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_gpio.h"
#include "stm32f1xx_hal_spi.h"
#elif defined(STM32F4)
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_gpio.h"
#elif defined(STM32L0)
#include "stm32l0xx_hal.h"
#elif defined(STM32L1)
#include "stm32l1xx_hal.h"
#elif defined(STM32L4)
#include "stm32l4xx_hal.h"
#elif defined(STM32F3)
#include "stm32f3xx_hal.h"
#elif defined(STM32H7)
#include "stm32h7xx_hal.h"
#elif defined(STM32F7)
#include "stm32f7xx_hal.h"
#elif defined(STM32G0)
#include "stm32g0xx_hal.h"
#elif defined(STM32G4)
#include "stm32g4xx_hal.h"
#endif


#if !defined(PROGMEM)
#define PROGMEM
#endif

#if !defined(HIGH)
#define HIGH true
#endif

#if !defined(LOW)
#define LOW false
#endif

#if !defined(millis)
#define millis HAL_GetTick
#endif

#if !defined(delayMicroseconds)
void delayMicroseconds(uint32_t usecs);
#endif

#if !defined(delay)
#define delay(msecs) delayMicroseconds(1000*msecs)
#endif

#if !defined(_BV)
#define _BV(bit) (1<<(bit))
#endif

#if !defined(PSTR)
#define PSTR(x) (x)
#endif

#if !defined(printf_P)
#define printf_P printf
#endif

#if !defined(pgm_read_word)
#define pgm_read_word(p) (*(p))
#endif

#if !defined(pgm_read_byte)
#define pgm_read_byte(p) (*(p))
#endif

#if !defined(pgm_read_ptr)
#define pgm_read_ptr(p) (*(p))
#endif

class DummySpi {
public:
DummySpi(SPI_HandleTypeDef* hspi);
void begin();
uint8_t transfer(uint8_t data_to_send);
uint32_t get_baud();
private:
SPI_HandleTypeDef* _hspi;
};

#define RF24_SPI_PTR
#define _SPI DummySpi


#endif //RF24_UTILITY_STM32_RF24_ARCH_CONFIG_H
47 changes: 47 additions & 0 deletions utility/STM32/rf24_stm32.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "RF24_arch_config.h"


static uint32_t rf24_get_time_us()
{
return 1000 * HAL_GetTick() + 1000 - (SysTick->VAL / (SystemCoreClock / 1000000));
}


void delayMicroseconds(uint32_t usecs)
{
uint32_t now = rf24_get_time_us();
uint32_t blocked_until = now + usecs;
while (blocked_until > rf24_get_time_us()) {}
}


DummySpi::DummySpi(SPI_HandleTypeDef *hspi) {
_hspi = hspi;
}


void DummySpi::begin() {
HAL_SPI_Init(_hspi);
}


uint8_t DummySpi::transfer(uint8_t data_to_send) {
const uint16_t size = 1;
uint8_t rx_data;
HAL_SPI_TransmitReceive(_hspi, &data_to_send, &rx_data, size, HAL_MAX_DELAY);
return rx_data;
}

uint32_t DummySpi::get_baud() {
// This method was tested with stm32f103c8t6. It may be different on other architectures
const uint8_t actual_config = _hspi->Init.BaudRatePrescaler;
uint16_t preescaler = 2;
if ((actual_config & SPI_CR1_BR_0) > 0)
preescaler = 2 * preescaler;
if ((actual_config & SPI_CR1_BR_1) > 0)
preescaler = 4 * preescaler;
if ((actual_config & SPI_CR1_BR_2) > 0)
preescaler = 16 * preescaler;
uint32_t baud = SystemCoreClock / preescaler;
return baud;
}