Is there a M4 and M7 Usage for dummies document :D

I had to modify PCMaster's code slightly to first enable TIM2 clock, and then for my purposes I tweaked the PSC calculation to give 10x the resolution. But now it's working perfectly for my needs of a tenth of a microsecond timing source.

PCMaster thanks for such a nice concise and simple example!

const uint32_t M4_CLOCK_SPEED = 240000000;
void setupTenthsTimer() {
  RCC->APB1LENR |= RCC_APB1LENR_TIM2EN;
  TIM2->CR1 = 0;
  TIM2->CNT = 0;
  TIM2->PSC = (M4_CLOCK_SPEED / 10000000) - 1;
  TIM2->ARR = 0xFFFFFFFF;
  TIM2->EGR = TIM_EGR_UG;
  TIM2->CR1 |= TIM_CR1_CEN;
}

uint32_t getMicrosecondTenths() {
  return (uint32_t)TIM2->CNT;
}

Hello, About pin's name, I noted that M7 and M4 can use the name port like this
pinMode(PG_10, OUTPUT) = pinMode(44, OUTPUT)
pinMode(PG_10, OUTPUT) work fine with M4 and M7
pinMode(44, OUTPUT) work only on M7
But the EXE speed is different.

digitalWrite(44, HIGH); = 125 ns
digitalWrite(44, LOW); = 125 ns

but

digitalWrite(PG_10, HIGH); = 1.5 µs (1500 ns)
digitalWrite(PG_10, LOW);

Why ?

I tried this code but doesnt work :

static inline void digitalWriteFast(uint8_t pin, PinStatus val) attribute((always_inline, unused));
static GPIO_TypeDef * const port_table[] = { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK };
static const uint16_t mask_table[] = { 1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7,
1 << 8, 1 << 9, 1 << 10, 1 << 11, 1 << 12, 1 << 13, 1 << 14, 1 << 15 };
static inline void digitalWriteFast(pin_size_t pin, PinStatus val) {
PinName hardware_port_pin = g_APinDescription[pin].name;
//uint16_t mask = 1 << (hardware_port_pin & 0xf);
uint16_t mask = mask_table[hardware_port_pin & 0xf];
GPIO_TypeDef * const port = port_table[hardware_port_pin >> 8];
if (val) port->BSRR = mask;
else port->BSRR = (uint32_t)(mask << 16);
}
If somebody knows... thank's

My digitalWriteFast and digitalToggleFast are up on github.
Probably should move it to a giga project...

UNOR4-stuff/libraries/GIGA_digitalWriteFast/GIGA_digitalWriteFast.h at main · KurtE/UNOR4-stuff (github.com)

#ifndef _GIGA_DIGITALWRITEFAST_H_
#define _GIGA_DIGITALWRITEFAST_H_
#include <Arduino.h>
#include "pinDefinitions.h"
#if !defined(ARDUINO_GIGA) && !defined(ARDUINO_PORTENTA_H7_M7)

#error "Only works on Arduino GIGA or Portenta H7 boards"
#endif


static  GPIO_TypeDef * const port_table[] = { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK };
static const uint16_t mask_table[] = { 1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7,
                                       1 << 8, 1 << 9, 1 << 10, 1 << 11, 1 << 12, 1 << 13, 1 << 14, 1 << 15 };

// quick and dirty digitalWriteFast

// Sets the state of an IO pin
// Two versions - this version you takes in a pin number as pin_size_t type - uint8_t
static inline void digitalWriteFast(pin_size_t pin, PinStatus val) __attribute__((always_inline, unused));
static inline void digitalWriteFast(pin_size_t pin, PinStatus val) {
  PinName pin_name = g_APinDescription[pin].name;
  uint16_t mask = mask_table[pin_name & 0xf];
  GPIO_TypeDef  * const port = port_table[pin_name >> 4];
  if (val) port->BSRR = mask;
  else port->BSRR = (uint32_t)(mask << 16);
}

// This version you takes in a pin name (PinName) like LED_RED
static inline void digitalWriteFast(PinName pin_name, PinStatus val) __attribute__((always_inline, unused));
static inline void digitalWriteFast(PinName pin_name, PinStatus val) {
  uint16_t mask = mask_table[pin_name & 0xf];
  GPIO_TypeDef  * const port = port_table[pin_name >> 4];
  if (val) port->BSRR = mask;
  else port->BSRR = (uint32_t)(mask << 16);
}



// Toggles the state of an IO pin - pin number version
static inline void digitalToggleFast(pin_size_t pin) __attribute__((always_inline, unused));
static inline void digitalToggleFast(pin_size_t pin) {
  PinName pin_name = g_APinDescription[pin].name;
  uint16_t pin_mask = mask_table[pin_name & 0xf];
  GPIO_TypeDef  * const portX = port_table[pin_name >> 4];

  if (portX->ODR & pin_mask) portX->BSRR = (uint32_t)(pin_mask << 16);
  else portX->BSRR = pin_mask;
}

// Toggles the state of an IO pin - pin name version
static inline void digitalToggleFast(PinName pin_name) __attribute__((always_inline, unused));
static inline void digitalToggleFast(PinName pin_name) {
  uint16_t pin_mask = mask_table[pin_name & 0xf];
  GPIO_TypeDef  * const portX = port_table[pin_name >> 4];

  if (portX->ODR & pin_mask) portX->BSRR = (uint32_t)(pin_mask << 16);
  else portX->BSRR = pin_mask;
}


// Reads the state of an IO pin - pin number version
static inline uint16_t digitalReadFast(pin_size_t pin) __attribute__((always_inline, unused));
static inline uint16_t digitalReadFast(pin_size_t pin) {
  PinName pin_name = g_APinDescription[pin].name;
  uint16_t pin_mask = mask_table[pin_name & 0xf];
  GPIO_TypeDef  * const portX = port_table[pin_name >> 4];

  return (portX->IDR & pin_mask);
}

// Reads the state of an IO pin - pin name version
static inline uint16_t digitalReadFast(PinName pin_name) __attribute__((always_inline, unused));
static inline uint16_t digitalReadFast(PinName pin_name) {
  uint16_t pin_mask = mask_table[pin_name & 0xf];
  GPIO_TypeDef  * const portX = port_table[pin_name >> 4];

  return (portX->IDR & pin_mask);
}


#endif

Which was working the last times I played with it...

Thank you so much for your "writefast" answer :slight_smile: I try....

It works very fine ! Time for switch is 125ns with digitalWrite(44, HIGH) and 25 ns with digitalWriteFast(44, HIGH);

Thank you so much