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
GonzoG wrote: Mon Oct 23, 2023 7:27 pm I got 19MHz wit digitalReadFast and 33MHz with digitalWriteFast, but with typing 1000 lines of code.
While loop needs few cycles.
Sorry.. copied wrong values. Those were Mops/s, so frequency is half of those. Measured with "toy" oscilloscope and digitalWriteFast gave me 18MHz signal.ManX84 wrote: Mon Oct 23, 2023 9:43 pm @GonzoG PLease give us your code ! (I do not pretend to get the fastest .. just starting to play)
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.dannyf wrote: Wed Oct 25, 2023 9:42 pmFast IO is implemented via BRR/BSRR.18MHz signal.
Hard to imagine that they could get that 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)