Re: Speed Up your IO !!
Posted: Wed Oct 25, 2023 12:26 am
those numbers probably explain why bit-banding is rarely mentioned in the datasheets of modern CMx chips.
Everything relating to using STM32 boards with the Arduino IDE and alternatives
https://www.stm32duino.com/
Code: Select all
/* note bit banding is used here */
inline void dc_command() { *dc_addr = 0; } // 0
inline void dc_data() { *dc_addr = 1; } // 1
inline void cs_clear() { *cs_addr = 0; }
inline void cs_set() { *cs_addr = 1; }
Code: Select all
#define BB_PERI_REF 0x40000000
#define BB_PERI_BASE 0x42000000
volatile bb_perip(volatile void *address, uint8_t bit) {
return (volatile uint32_t *)(BB_PERI_BASE + ((uint32_t) address - BB_PERI_REF) * 32 + bit * 4);
}
#ifdef ARDUINO_ARCH_STM32
__IO uint32_t *base = portOutputRegister(digitalPinToPort(_cs));
cs_addr = bb_perip(base, STM_PIN(digitalPinToPinName(_cs)));
base = portOutputRegister(digitalPinToPort(_dc));
dc_addr = bb_perip(base, STM_PIN(digitalPinToPinName(_dc)));
#elif defined(ARDUINO_ARCH_STM32F1)
volatile uint32 *base = &(PIN_MAP[_cs].gpio_device->regs->ODR);
cs_addr = bb_perip(base, PIN_MAP[_cs].gpio_bit);
base = &(PIN_MAP[_dc].gpio_device->regs->ODR);
dc_addr = bb_perip(base, PIN_MAP[_dc].gpio_bit);
#elif defined(ARDUINO_ARCH_STM32F4)
volatile uint32 *base = portOutputRegister(digitalPinToPort(_cs));
cs_addr = bb_perip(base, digitalPinToBit(_cs));
base = portOutputRegister(digitalPinToPort(_dc));
dc_addr = bb_perip(base, digitalPinToBit(_dc));
#endif
Code: Select all
//for (tmp=0; tmp<1000/5; tmp++) {*odrptr = 1; *odrptr = 0;*odrptr = 1; *odrptr = 0;*odrptr = 1; *odrptr = 0;*odrptr = 1; *odrptr = 0;*odrptr = 1; *odrptr = 0;} //3.7K/1K
Sorry.. copied wrong values. Those were Mops/s, so frequency is half of those. Measured with "toy" oscilloscope and digitalWriteFast gave me 18MHz signal.
Code: Select all
digitalWriteFast(PA1,1);
digitalWriteFast(PA1,0);
Fast IO is implemented via BRR/BSRR.18MHz signal.
digitalWriteFast and digitalReadFast are using LL functions. With O3 (fastest) optimization they can go this fast.
without knowing what the cpu is running at, the raw GPIO speed doesn't mean a whole lot.This is what I get with F411CE:
Code: Select all
//four alternative ways of flipping a GPIO pin
//uncomment one of them at a time to test the speed
#define PC13FLP() do {FIO_SET(GPIOC, 1<<13); FIO_CLR(GPIOC, 1<<13); } while (0); //using BRR/BSRR
//#define PC13FLP() FIO_FLP(GPIOC, 1<<13) //flipping ODR
//#define PC13FLP() do {*odrptr = 1; *odrptr = 0;} while (0) //bit-banding. odrptr points to the bit banding alias address for PC13
//#define PC13FLP() do {PC13FAST(1); PC13FAST(0);} while (0) //mimicking digitalWriteFAST()
//helper macros to make the coding easier
#define PC13FAST(val) do {if (val) FIO_SET(GPIOC, 1<<13); else FIO_CLR(GPIOC, 1<<13);} while (0) //simulate FASTIO
#define PC13FLPx5() do {PC13FLP(); PC13FLP(); PC13FLP(); PC13FLP(); PC13FLP(); } while (0)
#define PC13FLPx10() do {PC13FLPx5(); PC13FLPx5(); } while (0)
#define PC13FLPx50() do {PC13FLPx10(); PC13FLPx10(); PC13FLPx10(); PC13FLPx10(); PC13FLPx10(); } while (0)
#define PC13FLPx100() do {PC13FLPx50(); PC13FLPx50(); } while (0)
#define PC13FLPx500() do {PC13FLPx100();PC13FLPx100();PC13FLPx100();PC13FLPx100();PC13FLPx100();} while (0)
#define PC13FLPx1K() do {PC13FLPx500();PC13FLPx500(); } while (0)