[half-solved] Different model of MK20DX Kinetis & Teensy3.2 code - Page 1
Forum section: electronics / general

author: Whales
author_rank: Super Contributor
timestamp: August 10, 2021, 02:22:14 am
content: I am trying to work out if it's possible to get a Teensy3.2 project (Arduino framework in PlatformIO) working on a bare MK20DX micro of a similar butnotidentical part number (different pincount). I'm using a J-link to program & debug.I know this works for an actualMK20DX256VLH7as the Teensies use (I have an older board from this project next to me that programs & runs fine) but they're out of stock worldwide, so I'm trying aMK20DX256ZVLK10(80LQFP instead of 64LQFP).EDIT3:Debugger is showing weird behaviours, jumping around, resetting and bad stack. No idea why.EDIT2:Processor is getting stuck in fault isrs and usb isrs. Not sure why my debugger said it was proceeding into my main(), it definitely isn't.EDIT:Clock issue solved, however I can't get the output pins to toggle. Debugger says processor is executing code.The part programs OK but I can't get the main 16MHz clock to run even slightly. According to the ref manuals the OSC_CR register should be the same on both models, so I'm rather confused.Q1:Most of the time hooking up a 16MHz crystal (my case: 12pf 30ohmESR) across the two main XTAL pins should be enough? I've also tried adding some arbitrary 15pf->GND load caps, no changes.Q2:(Dumb question) who is responsible for setting OSC_CR and related oscillator registers? Is that burned at programming-time or set early in runtime (with a different/internal clocksource running first)? I'm digging through the teensy code in PIO without much luck, so I might be looking in the wrong place.Q3:(Another dumb one) it looks like reset sources other than the main reset pin are optional; or is booting up an ARM micro more complex than that?In terms of physical wiring I've done for my testing: nothing more than 3.3V power, bypass caps, reset tied high 10K + 100nF to GND, 16MHz crystal on PTA18-PTA19, a header for SWD and pullups on SWD pins.From what I gather the 32KHz crystal should be optional, so I have not hooked it up.

author: Whales
author_rank: Super Contributor
timestamp: August 10, 2021, 07:32:39 am
content: Solved.edit: halfThe RTC is not optional. You must provide it power (via VBAT pin) otherwise the microcontroller won't start driving its main 16MHz external crystal. EDIT: this may be specifically due to the Teensy/Arduino init code in mk20dx128.c:ResetHandler()

author: Whales
author_rank: Super Contributor
timestamp: August 10, 2021, 11:24:38 am
content: Clocks are working (both main 16MHz and time 32KHz), programming succeeds, but nobody is home. None of the pins ever toggle.Not sure if the processor is hanging somewhere or if the output pin modes are misconfigured. At least I have pathways for these problems (debugger + comparing port config addresses between datasheets)

author: Whales
author_rank: Super Contributor
timestamp: August 10, 2021, 11:46:48 am
content: I had to compile my own copy of ncurses.so.5 (ABI v5, not v6) to get PIO's gdb to work. I'm not on Arch butthis PKGBUILDis descriptive enough to follow by hand.Debugging with "$ pio debug --interface=gdb -x .pioinit" hangs at "Starting target CPU", I suspect I'll need to find this ".pioinit" script and see what it's doing.EDIT:The processor is indeed executing my code and the pins_teensy.c arduino framework thinks it's doing something useful when I call digitalWrite().I had torun jlinkserver and gdb manuallyrather than use pio's inbuilt debug scripts to get this far. This suggests that my problem might be different PORT/register addresses between the MK20DX models?

author: Whales
author_rank: Super Contributor
timestamp: August 10, 2021, 12:43:12 pm
content: Using addresses straight from the datasheet still doesn't seem to work, pins are still not toggling.Code:#include <Arduino.h>int main(){int32_t *porte_pcr0 = (int32_t *)0x4004D000; //controlint32_t *gpioe_pdor = (int32_t *)0x400ff100; //data outint32_t *gpioe_psor = (int32_t *)0x400ff104; //setint32_t *gpioe_pcor = (int32_t *)0x400ff108; //resetint32_t *gpioe_ptor = (int32_t *)0x400ff10c; //toggleint32_t *gpioe_pdir = (int32_t *)0x400ff110; //data inint32_t *gpioe_pddr = (int32_t *)0x400ff114; //direction// 001 = use as GPIO*porte_pcr0 = 0b00000000000000000000101000000; // edit: wrong*porte_pcr0 = 0b00000000000000000000000101000000; // edit: correct// set as output*gpioe_pddr = 0b11111111111111111111111111111111;while (1){*gpioe_pdor = 0b11111111111111111111111111111111;delay(1);*gpioe_pdor = 0b00000000000000000000000000000000;delay(1);}}I was suspicious that the wrong alternate modes might be getting selected for the pins, but that doesn't make sense anyway as 0x001 on either model of MK20DX is the GPIO mode.EDIt: I'm beginning to wonder if there is a whole GPIO-related component/peripheral of this chip that's not getting properly initialised.

author: ttt
author_rank: Regular Contributor
timestamp: August 10, 2021, 01:55:10 pm
content: Quote from: Whales on August 10, 2021, 12:43:12 pmAre you sure you enabled the Port E module clock? (bit 13 on SIM_SCGC5)

author: Whales
author_rank: Super Contributor
timestamp: August 10, 2021, 10:40:50 pm
content: Thankyou ttt. I skimmed the 'Module clocks' section last night and assumed the big table said that the system clock is always connected to GPIO, but no what it really describes areoptionsfor clock sources (and only one is listed). By default the chip initialises with clocks turned off to all(most?) modules.Enabling clocks to all of the GPIO modules does not seem to work, my pins are still not twiddling.Code:#include <Arduino.h>int main(){int32_t *sim_scgc5 = (int32_t *)0x40048048; //system clock gating control reg 5int32_t *porte_pcr0 = (int32_t *)0x4004D000; //controlint32_t *porte_pcr1 = (int32_t *)0x4004D004; //controlint32_t *porte_pcr2 = (int32_t *)0x4004D008; //controlint32_t *porte_pcr3 = (int32_t *)0x4004D00C; //controlint32_t *gpioe_pdor = (int32_t *)0x400ff100; //data outint32_t *gpioe_psor = (int32_t *)0x400ff104; //setint32_t *gpioe_pcor = (int32_t *)0x400ff108; //resetint32_t *gpioe_ptor = (int32_t *)0x400ff10c; //toggleint32_t *gpioe_pdir = (int32_t *)0x400ff110; //data inint32_t *gpioe_pddr = (int32_t *)0x400ff114; //direction// enable clock to portE module*sim_scgc5 |= 0b00000000000000000011111000000000;// set PORTE pin modes to be GPIO with no interrupts and fast transitions*porte_pcr0 = 0b00000000000000000000000101000000;*porte_pcr1 = 0b00000000000000000000000101000000;*porte_pcr2 = 0b00000000000000000000000101000000;*porte_pcr3 = 0b00000000000000000000000101000000;// set PORTE as output*gpioe_pddr = 0b11111111111111111111111111111111;// toggle all portE pins (or at least the few we have setup PCRs for)while (1){*gpioe_pdor = 0b11111111111111111111111111111111;delay(1);*gpioe_pdor = 0b00000000000000000000000000000000;delay(1);}}From the ref manual:QuotePerhaps there is a way to enable/disable the GPIO modules still. I'll keep searching the manual to see what I can find.

author: Whales
author_rank: Super Contributor
timestamp: August 11, 2021, 12:58:53 am
content: I can't find anything about enabling or disabling the GPIO module. Somefrom-scratch code for a related processor suggests there shouldn't be any more registers needed.

author: Whales
author_rank: Super Contributor
timestamp: August 11, 2021, 01:11:23 am
content: Hmm, my debugger now tells me that my micro is getting stuck in some isr routines, including:usb_isr () at /home/valentine/.platformio/packages/framework-arduinoteensy/cores/teensy3/usb_dev.c:912fault_isr () at /home/valentine/.platformio/packages/framework-arduinoteensy/cores/teensy3/mk20dx128.c:129Hohoho I think its trying to read/write somewhere it shouldn't, faulting and then repeatingThis might explain why the default platformio debugger setups are useless (it sets a breakpoint on main() but never gets there, and everything gets killed if you hit Ctrl+C so you can't manually interrupt). Not sure why earlier I actually found it running my code but now it won't.

author: pgo
author_rank: Regular Contributor
timestamp: August 11, 2021, 01:49:50 am
content: Hi,One difference between the M7 and M10 devices is that there is a MPU.To use USB you may need to include the following:#ifdef MPU_CESR_VLD_MASK// Disable MPU & clear errorsMPU->CESR = MPU_CESR_SPERR_MASK;#endifAlso - Why are you using so many magic numbers in your code?Do you have a usable device header file (as required for the above code)?Also on GPIOs - The PORTS require a clock (e.g. PCR registers) but the GPIOS do not. Mind you, you can't use the latter without the first.

author: Whales
author_rank: Super Contributor
timestamp: August 11, 2021, 02:34:06 am
content: Quote from: pgo on August 11, 2021, 01:49:50 amThankyou, I'll take a look. That might explain the constant faulting in USB related code.I wish NXP had a "difference between this chip and other similar chips in its family" chapter in the reference manual with a summary register level details. At the moment I'm comparing almost-identical 1500-page PDFs for the two modelsI guess changing chips within the family is an unusual move by customers.QuoteIt's an existing Arduino-environment codebase (ie using digitalWrite(), wire libs for I2C, etc) for a Teensy 3.2. I'm using my own magic numbers there just as a test.As it turns out: the processor isn't even getting to my code (despite it saying it was during earlier debugging, not sure why that happened), so it's mostly moot now. I'm modifying the Arduino-environment teensy code instead now, specifically the chaos that is ResetHandler() inmk20dx128.c

author: Whales
author_rank: Super Contributor
timestamp: August 11, 2021, 07:26:31 am
content: I have much more serious issues.My program counter is jumping around like mad. When I run stepi in GDB I sometimes move normally but other times leap forwards or backwards in nonsensical ways and get stuck in weird loops that don't make sense. It doesn't look like stack corruption -- it's happening far from any returns.This might explain why I thought the processor was getting to my main() code earlier on. It probably was. Sometimes.Perhaps the clock config is unstable. I'm going to read through the clock registers and try to calculate what the teensy code is setting the micro to. The original part was 72MHz rated, this new one is 100MHz, so perhaps they interpret things entirely different.(Whilst I'm here I'm going to probe the power rails a bit and see if they're flaking out too)EDIT yeah chaos, my debugger is losing control and the stack is dead:Code:Backtrace stopped: previous frame identical to this frame (corrupt stack?)Code:Performing single step......Target halted (DBGRQ, PC = 0x0000052C)Reading all registersRead 4 bytes @ address 0x0000052C (Data = 0xFE78F000)Performing single step......Target halted (DBGRQ, PC = 0x00001220)Reading all registersRead 4 bytes @ address 0x00001220 (Data = 0x47F0E92D)Read 4 bytes @ address 0x2000800C (Data = 0x99628889)Read 4 bytes @ address 0x2000800C (Data = 0x99628889)Read 4 bytes @ address 0x2000800C (Data = 0x99628889)WARNING: Failed to read memory @ address 0x99628888Performing single step...Reading all registersERROR: Cannot read register 0 (R0) while CPU is runningERROR: Cannot read register 1 (R1) while CPU is runningERROR: Cannot read register 2 (R2) while CPU is runningERROR: Cannot read register 3 (R3) while CPU is runningERROR: Cannot read register 4 (R4) while CPU is runningERROR: Cannot read register 5 (R5) while CPU is running[...]EDIT: Toggling port pins before any clock changes are made (early in boot) doesn't seem to be helping. I think that my J-link debugger stack might be completely useless.

author: Whales
author_rank: Super Contributor
timestamp: August 11, 2021, 09:35:08 am
content: I just made the mistake of downloading NXP's SDK for this part. After manually fixing parts of their ridiculously complicated cmake scripts I'm now getting brickwalled by strange flags getting passed to gcc-as that it doesn't know what to do with. Hundreds of times over.Well, I think I've answered my original question.No, it's not possible to easily get Teensy 3.2 code for a MK20DX256VLH7 working on a MK20DX256ZVLK10. The teensy environment has had (probably) months of man-hours put into it and the chips are simply far too different. I've spent a few full days on it and that feels like it's nowhere near enough.Thankyou everyone who has helped, greatly appreciated. I just don't think I'm cracked up for these complex MCUs.

author: DavidMenting
author_rank: Contributor
timestamp: August 11, 2021, 08:11:39 pm
content: I'm in the same boat as you are: a current project uses the VLH7 but seeing that they are out of stock worldwide the ZVLK10 seems like a nice replacement.Have you recompiled the code to run on the ZVLK10 or are you using the same binary? And how is the 80-LQFP part connected? Did you spin a new board or is it connected to the 64-LQFP footprint somehow?

author: Nominal Animal
author_rank: Super Contributor
timestamp: August 12, 2021, 11:49:54 am
content: Quote from: Whales on August 11, 2021, 09:35:08 amMost definitely, yes (as discussed at forum.pjrc.com); and a lot of the startup code is in the proprietary MKL02/MKL04 bootloader chips, too.Quote from: Whales on August 11, 2021, 09:35:08 amYep. I was a backer of the initial Teensy 3.0 Kickstarter project, and I seem to recall Paul mentioning the chip was particularly fiddly to bring up, especially compared to the previous Teensies, ATmega32u4 (2.0) and AT90USB1280 (2.0++). 4.x are even more so!I do not thinkPJRC's IC_MKL02Z32_QFN16"bootloader" chip works with MK20DX256ZVLK10, either, but you could ask and verify this atforum.pjrc.com.Me, I'd really like to do something similar with Teensy 4.0/4.1 (usingIC_MKL02Z32_T4_QFN16), to make a nice little graphics processing unit for ILI9488/ILI9341 and similar display modules, using a DMA'ble parallel connection, and a fast SPI/UART to control using another microcontroller or via USB from a host computer (router). But, I'm very much a software guy, a complete hobbyist with electronics, and have never even soldered a BGA before, and designed nothing more complicated than two-layer boards using datasheets as a guidance. (The funky thing here is that I'd like to use the 18-bit parallel bus, using 15-bit data (MSB copied to LSB per component), and use the high bit to denote command/data output. Might be easier to use an FPGA running at ~ 80 MHz, feeding it via SPI, instead. But I haven't used those, either.)

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 12, 2021, 05:45:17 pm
content: Not sure what exactly you want to do and especially how... I suppose the Teensy 4.1 has not enough IOs for your needs?

author: Nominal Animal
author_rank: Super Contributor
timestamp: August 13, 2021, 12:01:59 am
content: Quote from: SiliconWizard on August 12, 2021, 05:45:17 pmThe exposed pins on Teensy 4.x cannot be used as a parallel bus one can DMA to. I can bit-bang the I/O just fine, but if I could use DMA instead, there would be enough time to compose each "scan line" (in the sense that update could be done ahead of the display refresh) while the previous one is being transferred. AFAICT, I'd need 16 continuous FlexIO1 or FlexIO2 pins for 16-bit wide DMA.Basically, with the pre-programmed MKL02 IC from PJRC.com, one can design their "own" Teensy 4 variant, with a different set of pins exposed, but otherwise functioning the same, if one follows some simple rules (pins between RT1062 and MKL02 IC etc.). This is howSparkFun MicroMod Teensyis done, for example. Since the MCU itself is supported by Teensyduino, and I'd not expose any new subsystems, only a different set of pins of the already supported subsystems, the variant can be programmed as if it were a standard Teensy 4.

author: Whales
author_rank: Super Contributor
timestamp: August 13, 2021, 02:08:17 am
content: QuoteI only built enough to test if the chip could work. LQFP-to-2.54mm adaptor board. 100nf on every VSS+VDD pair, reset circuit added, SWD pulled high with 10K resistors, internal on-chip 3.3V reg being used (from 5V), J-link programmer, crystals and a few other odds and sods.I made two (just in case there were errors/shorts in my wiring), but they both behave the same. Here is the prettier one:Diodes are just convenient devices with legs that I use on the power pins. On the bottom side they have 100nf caps.Copper tape patches are GND and 3.3V.Quote from: DavidMenting on August 11, 2021, 08:11:39 pmBoth, initially tried same bins but also tried tweaks to the early startup code (eg disabling the memory protection unit as per prev posts, enabling GPIO and toggling pins very early in boot, etc). According to the datasheets the registers are all at the same locs, but it seems like are probably many fine details that I have not noticed. One I spotted were some bits in a reg being do-not-touch in the VLH7 but necessary for a peripheral in the VLK10; maybe I missed some of those do-not-touch bits somewhere and they're being set to values that cause undefined behaviour of the micro.QuoteNot using the bootloader, skipped that problem. Instead directly programming the part using a J-link programmer (SWD programmer).N.B. this is known good/working for the VLH7 (our existing/old board does this) and the VLK10 seems to program fine too, but goes all weird at runtime. I should try debugging the VLH7 just to see if it also "seems" to go weird when debugged.EDIT: Lol our old boards do actually have an 8-pin flash chip; I've been told its "not used" and there is nothing needed to get these boards running other than a single j-link program; but I suddenly have the urge to double check all of that myself

author: DavidMenting
author_rank: Contributor
timestamp: August 13, 2021, 11:10:49 am
content: I really like that hacky aestheticI can imagine some errors due to the physical layout, though. Especially the area around the crystal and the inductance of the wires leading to the decoupling caps.I had a good look around the NXP website to find substitutes. Preferably the same silicone in a different package. I would assume the following microcontrollers could be used as a (non pin-compatible) replacement as their clocks and memory configuration are the same:MK20DX256VLH7 (64-LQFP like on the Teensy 3.2)MK20DX256VLK7 (80-LQFP)MK20DX256VMC7 (121-BGA)MK20DX256VLL7 (100-LQFP)Unfortunately everything but the most annoying 121-BGA package is unavailable