Hi all,
I have a bizarre timing issue with a project which uses the (older) Teensy 3.2.
I am using IntervalTimer to trigger a portion of my main code once every 100us. This part of the code sets an IO pin high for 25us (using delayMicroseconds()) and then sets it low again, before waiting for the next trigger (via a flag variable) from the IntervalTimer ISR.
When I run this with F_CPU set to 48MHz, it works fine. The period of the output signal is 100us and the high portion is 25us.
When I change F_CPU to 72MHz, however, the period decreases to 75us and the high portion INCREASES to 37.5us. Note that neither of these changes follows the ratio of the F_CPU change (I increased F_CPU by 1.5, the IntervalTimer period changed by 0.75, and the delayMicroseconds is executing 1.5 times SLOWER)
I am changing F_CPU in the Makefile. The main.cpp file is not changed at all between the two test cases.
I did notice that IntervalTimer uses F_BUS and not F_CPU, and in kinetis.h, when F_CPU=48MHz, it sets F_BUS to 48MHz also, but if F_CPU=72MHz, it sets F_BUS to 36MHz, which seems like an odd thing to do. In any event, though, I would expect that IntervalTimer and delayMicroseconds would both compensate for the F_CPU and F_BUS settings as needed to maintain the correct timing.
Any idea what is wrong?
Thanks,
Sean
C++ source:
Makefile (the only thing I am changing is the -DF_CPU setting)
Running at 48MHz:
Running at 72MHz:
I have a bizarre timing issue with a project which uses the (older) Teensy 3.2.
I am using IntervalTimer to trigger a portion of my main code once every 100us. This part of the code sets an IO pin high for 25us (using delayMicroseconds()) and then sets it low again, before waiting for the next trigger (via a flag variable) from the IntervalTimer ISR.
When I run this with F_CPU set to 48MHz, it works fine. The period of the output signal is 100us and the high portion is 25us.
When I change F_CPU to 72MHz, however, the period decreases to 75us and the high portion INCREASES to 37.5us. Note that neither of these changes follows the ratio of the F_CPU change (I increased F_CPU by 1.5, the IntervalTimer period changed by 0.75, and the delayMicroseconds is executing 1.5 times SLOWER)
I am changing F_CPU in the Makefile. The main.cpp file is not changed at all between the two test cases.
I did notice that IntervalTimer uses F_BUS and not F_CPU, and in kinetis.h, when F_CPU=48MHz, it sets F_BUS to 48MHz also, but if F_CPU=72MHz, it sets F_BUS to 36MHz, which seems like an odd thing to do. In any event, though, I would expect that IntervalTimer and delayMicroseconds would both compensate for the F_CPU and F_BUS settings as needed to maintain the correct timing.
Any idea what is wrong?
Thanks,
Sean
C++ source:
Code:
// NOTE: We have Teensy 3.2 with MK20DX256VLH7 processor
// which is has KINETISK defined
#include "WProgram.h"
#include "IntervalTimer.h"
#define PIN_EN_SPD_CTRL 0
#define PIN_EN_CURR_CTRL 1
#define PIN_TEST 2
#define PIN_SPD_CURR_SEL 3
#define PIN_OL_WARN 4
#define PIN_OL_FAULT 5
#define PIN_UNUSED0 6
#define PIN_UNUSED1 7
#define PIN_UNUSED2 8
#define PIN_PWM_SPD 9
#define PIN_PWM_CURR 10
#define PIN_UNUSED3 11
#define PIN_UNUSED4 12
#define PIN_LED_CTRL 13
#define PIN_UNUSED5 14
#define PIN_UNUSED6 15
#define PIN_ENCA 16
#define PIN_ENCB 17
#define PIN_A_CURR_FB 18
#define PIN_A_SPD_CMD 19
#define PIN_A_CURR_CMD 20
#define PIN_UNUSED7 21
#define PIN_UNUSED8 22
#define PIN_UNUSED9 23
volatile uint8_t timerflag=0;
IntervalTimer myTimer;
void mytimerfunction ( void )
{
timerflag=1;
}
int main(void)
{
pinMode(PIN_OL_WARN, OUTPUT);
pinMode(PIN_OL_FAULT, OUTPUT);
pinMode(PIN_UNUSED0, OUTPUT);
pinMode(PIN_LED_CTRL, OUTPUT);
myTimer.begin(mytimerfunction,100); // Interrupt happens every 100 microseconds
// LAMP TEST
digitalWriteFast(PIN_LED_CTRL, HIGH);
digitalWriteFast(PIN_OL_WARN, HIGH);
digitalWriteFast(PIN_OL_FAULT, HIGH);
delay(1000);
// END LAMP TEST
digitalWriteFast(PIN_LED_CTRL, LOW);
digitalWriteFast(PIN_OL_WARN, LOW);
digitalWriteFast(PIN_OL_FAULT, LOW);
while (1)
{
while(!timerflag);
timerflag=0;
digitalWriteFast(PIN_UNUSED0,HIGH);
delayMicroseconds(25);
digitalWriteFast(PIN_UNUSED0,LOW);
}
}
Makefile (the only thing I am changing is the -DF_CPU setting)
Code:
# set your MCU type here, or make command line `make MCU=MK20DX256`
MCU=MK20DX256
# make it lower case
LOWER_MCU := $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(MCU)))))))))))))))))))))))))))
MCU_LD = $(LOWER_MCU).ld
# The name of your project (used to name the compiled .hex file)
TARGET = main
# Those that specify a NO_ARDUINO environment variable will
# be able to use this Makefile with no Arduino dependency.
# Please note that if ARDUINOPATH was set, it will override
# the NO_ARDUINO behaviour.
ifndef NO_ARDUINO
$(warning I see it)
# Path to your arduino installation
ARDUINOPATH ?= ~/Desktop/teensyutils/arduino-1.8.5
#ARDUINOPATH ?= ../../../..
endif
# configurable options
OPTIONS = -DF_CPU=72000000 -DLAYOUT_US_ENGLISH -DUSING_MAKEFILE
# options needed by many Arduino libraries to configure for Teensy 3.0
OPTIONS += -D__$(MCU)__ -DARDUINO=10613 -DTEENSYDUINO=132
# Other Makefiles and project templates for Teensy 3.x:
#
# https://github.com/apmorton/teensy-template
# https://github.com/xxxajk/Arduino_Makefile_master
# https://github.com/JonHylands/uCee
#************************************************************************
# Location of Teensyduino utilities, Toolchain, and Arduino Libraries.
# To use this makefile without Arduino, copy the resources from these
# locations and edit the pathnames. The rest of Arduino is not needed.
#************************************************************************
ifdef ARDUINOPATH
# path location for Teensy Loader, teensy_post_compile and teensy_reboot (on Linux)
TOOLSPATH = $(abspath $(ARDUINOPATH)/hardware/tools)
# path location for Arduino libraries (currently not used)
LIBRARYPATH = $(abspath $(ARDUINOPATH)/libraries)
# path location for the arm-none-eabi compiler
COMPILERPATH = $(ARDUINOPATH)/hardware/tools/arm/bin
else
# Default to the normal GNU/Linux compiler path if NO_ARDUINO
# and ARDUINOPATH was not set.
COMPILERPATH ?= "/home/sbreheny/Desktop/teensy utils/arduino-1.8.5/hardware/tools/arm/bin/"
endif
#************************************************************************
# Settings below this point usually do not need to be edited
#************************************************************************
# CPPFLAGS = compiler options for C and C++
CPPFLAGS = -Wall -g -Os -mcpu=cortex-m4 -mthumb -MMD $(OPTIONS) -I.
# compiler options for C++ only
CXXFLAGS = -std=gnu++0x -felide-constructors -fno-exceptions -fno-rtti
# compiler options for C only
CFLAGS =
# linker options
LDFLAGS = -Os -Wl,--gc-sections,--defsym=__rtc_localtime=0 --specs=nano.specs -mcpu=cortex-m4 -mthumb -T$(MCU_LD)
# additional libraries to link
LIBS = -lm
# names for the compiler programs
CC = $(COMPILERPATH)/arm-none-eabi-gcc
CXX = $(COMPILERPATH)/arm-none-eabi-g++
OBJCOPY = $(COMPILERPATH)/arm-none-eabi-objcopy
SIZE = $(COMPILERPATH)/arm-none-eabi-size
$(warning see:$(ARDUINOPATH))
# automatically create lists of the sources and objects
# TODO: this does not handle Arduino libraries yet...
C_FILES := $(wildcard *.c)
CPP_FILES := $(wildcard *.cpp)
OBJS := $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o)
# the actual makefile rules (all .o files built by GNU make's default implicit rules)
all: $(TARGET).hex
$(TARGET).elf: $(OBJS) $(MCU_LD)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
%.hex: %.elf
$(SIZE) $<
$(OBJCOPY) -O ihex -R .eeprom $< $@
ifneq (,$(wildcard $(TOOLSPATH)))
$(TOOLSPATH)/teensy_post_compile -file=$(basename $@) -path=$(shell pwd) -tools=$(TOOLSPATH)
-$(TOOLSPATH)/teensy_reboot
endif
# compiler generated dependency info
-include $(OBJS:.o=.d)
clean:
rm -f *.o *.d $(TARGET).elf $(TARGET).hex
Running at 48MHz:
Running at 72MHz: