Teensy 4.1 digitalWrite question.

Status
Not open for further replies.

Bill Greiman

Well-known member
I have been using digitalWrite() with a scope to time various operations in a new version of ChibiOS/RT. I first characterized digitalWrite() timing with this program:
Code:
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1);
  digitalWrite(LED_BUILTIN, LOW);      
}

The result is this asymmetric trace:

teensy4digital.png

I am curious why the high pulse is about 35 ns wide and the low pulse is about 45 ns wide. On Teensy 3.6 the pulses are slower but symmetric.

I doesn't bother my timing since I measure between rising edges then between falling edges to insure I subtract the correct amount for digitalWrite.

Teensy 4.1 really performs with ChibiOS 20.3.3. Context switch in 150 ns. This makes it really simple to get all the advantages of async DMA transfers by hiding the complexity using a semaphore in the driver.

Calls like SPI.transfer(buf, count) will sleep on the semaphore while the transfer happens so the thread with that call uses almost no CPU time.

ChibiOS is a tickless system so replacing delay with sleep for an interval uses no CPU time. Timer interrupts only happen if required.

I will soon post the ChibiOS update.
 
I know about digitalWriteFast().

My question is about digitalWrite(). I am trying to write simple examples for all Arduino boards and Teensy 4.1 has this strange digitalWrite() property.

I looked at the code and the execution path depends on the write value. It's amazing the code compiles to give a 10ns difference in timing between val LOW and val HIGH.

Teensy 3.6 has similar but different code. The timing difference is too small to measure.

Every board support package has quirks and when you ask why a standard function has a quirk, you get you should use this one-of-a-kind work around. Today I have STM32H7 and ESP8266 problems that need special cases.

Some MPUs like STM32, now have multiple board support packages, one by ST and one by a group of DIY guys. Each package needs special cases by board Teensy 3.6 vs Teensy 4.1, STM32F405 vs STM32F446.
 
I wonder if maybe you may want to play around with the different pin configurations information like speed, or drive strength...
i.e. look at the RM for the different IOMUXC_PAD_ values like DSE, SPEED
 
I wonder if maybe you may want to play around with the different pin configurations information like speed, or drive strength...
i.e. look at the RM for the different IOMUXC_PAD_ values like DSE, SPEED

I want providers of Arduino compatible systems to support standard Arduino functions. When I hit The Board Manager Tab I see over thirty board support packages. Not to mention things like PlatformIO.

Something like this happened in the Unix wars in the late 1980s and early 1990s to set the standard for Unix. The Open Group and POSIX emerged to provide some unity. The same is a problem for Linux which now aims for compatibility with POSIX.

I suspect Arduino will continue to fracture with companies like STMicroelectronics entering.

From ST:
The current generation of Arduino boards packs 32-bit Arm performance into robust, compact form-factors. Featuring battery management, on-board crypto-authentication chips and certified comms options spanning WiFi, BLE, LoRa, LTE Cat-M and NB-IoT means they’re ready for any IoT application. Combine them with stackable sensor shields or relay / motor carriers and build custom IoT nodes or bridge to existing RS-485 and Ethernet systems.

Low-code IoT cloud application development means achieving tangible results in a day. This lets you iteratively refine the application and quickly assess the viability of wider IoT deployments - without the need for expensive consultants or integration projects.

Consequently there’s been increasing demand from professionals using Arduino as a disruptive means to simplify and accelerate their IoT system deployments. Two primary business cases we are seeing are: 1. Improving production efficiency through monitoring, control and analysis of fields, factories or equipment. 2. Transforming businesses from traditional selling to a subscription-based model - providing better customer experience and new IoT-based revenue streams.

So far ST is no where near the hype. I get to talk to lots of ST engineers in France who say things like I verified you bug but have not found a way to fix it.

There probably is a way to use STM32Cube calls to do what I want. Wrong answer for "Arduino compatible".
 
Last edited:
I know about digitalWriteFast().

My question is about digitalWrite(). I am trying to write simple examples for all Arduino boards and Teensy 4.1 has this strange digitalWrite() property.

I looked at the code and the execution path depends on the write value. It's amazing the code compiles to give a 10ns difference in timing between val LOW and val HIGH.

Teensy 3.6 has similar but different code. The timing difference is too small to measure.

Every board support package has quirks ...

Quirks indeed ...

It was noticed in beta IIRC that there was LARGE timing asymmetry in I/O value changes. That seemed to go away - or at least not be super extreme - perhaps that was early when I/O went from 'slow' GPIO to fast' GPIO 6-9? Or maybe because the WriteFast() got more focus?

Looking at the digitalWrite() code it seems simple enough ... maybe the compiler or MCU has a preferred default case for "if (val) {"
So probably not ... The 1062 in the T_4.x's can dual execute at times. Perhaps the HIGH versus LOW code paths run differently in one case single exec and the other parallel dual instructions?

with ...
Code:
  digitalWriteHIGH(LED_BUILTIN);
  digitalWriteLOW(LED_BUILTIN);
  digitalWriteHIGH(LED_BUILTIN);
  digitalWriteLOW(LED_BUILTIN);
  digitalWriteHIGH(LED_BUILTIN);
  delay(1);
  digitalWriteLOW(LED_BUILTIN);

If these were put in ...\avr\cores\teensy4\digital.c about line 85 and called - I wonder what the scope shows?
Code:
void digitalWriteHIGH(uint8_t pin)
{
	const struct digital_pin_bitband_and_config_table_struct *p;
	uint32_t  mask;

	if (pin >= CORE_NUM_DIGITAL) return;
	p = digital_pin_to_info_PGM + pin;
	mask = p->mask;
			*(p->reg + 0x21) = mask; // set register
}
void digitalWriteLOW(uint8_t pin)
{
	const struct digital_pin_bitband_and_config_table_struct *p;
	uint32_t  mask;

	if (pin >= CORE_NUM_DIGITAL) return;
	p = digital_pin_to_info_PGM + pin;
	mask = p->mask;
			*(p->reg + 0x22) = mask; // clear register
}
 
Status
Not open for further replies.
Back
Top