Author Topic: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code  (Read 887 times)

0 Members and 1 Guest are viewing this topic.

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
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 but not identical part number (different pincount).  I'm using a J-link to program & debug.

I know this works for an actual MK20DX256VLH7 as 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 a MK20DX256ZVLK10 (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.
« Last Edit: August 11, 2021, 08:42:47 am by Whales »
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [Solved] Clock not running: MK20DX running Teensy3.2 code
« Reply #1 on: August 10, 2021, 07:32:39 am »
Solved.  edit: half

The 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()
« Last Edit: August 11, 2021, 02:36:32 am by Whales »
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Clock not running: MK20DX running Teensy3.2 code
« Reply #2 on: August 10, 2021, 11:24:38 am »
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) :)

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Clock not running: MK20DX running Teensy3.2 code
« Reply #3 on: August 10, 2021, 11:46:48 am »
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 but this PKGBUILD is 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 to run  jlinkserver and gdb manually rather 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?

« Last Edit: August 11, 2021, 02:36:58 am by Whales »
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Clock not running: MK20DX Kinetis & Teensy3.2 code
« Reply #4 on: August 10, 2021, 12:43:12 pm »
Using addresses straight from the datasheet still doesn't seem to work, pins are still not toggling.

Code: [Select]
#include <Arduino.h>

int main()
{
int32_t *porte_pcr0 = (int32_t *)0x4004D000; //control
int32_t *gpioe_pdor = (int32_t *)0x400ff100; //data out
int32_t *gpioe_psor = (int32_t *)0x400ff104; //set
int32_t *gpioe_pcor = (int32_t *)0x400ff108; //reset
int32_t *gpioe_ptor = (int32_t *)0x400ff10c; //toggle
int32_t *gpioe_pdir = (int32_t *)0x400ff110; //data in
int32_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);
}
}

 :scared:

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.
« Last Edit: August 10, 2021, 10:24:37 pm by Whales »
 

Offline ttt

  • Regular Contributor
  • *
  • Posts: 77
  • Country: us
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #5 on: August 10, 2021, 01:55:10 pm »
Using addresses straight from the datasheet still doesn't seem to work, pins are still not toggling.

Code: [Select]
#include <Arduino.h>

int main()
{
int32_t *porte_pcr0 = (int32_t *)0x4004D000; //control
int32_t *gpioe_pdor = (int32_t *)0x400ff100; //data out
int32_t *gpioe_psor = (int32_t *)0x400ff104; //set
int32_t *gpioe_pcor = (int32_t *)0x400ff108; //reset
int32_t *gpioe_ptor = (int32_t *)0x400ff10c; //toggle
int32_t *gpioe_pdir = (int32_t *)0x400ff110; //data in
int32_t *gpioe_pddr = (int32_t *)0x400ff114; //direction

//                                001 = use as GPIO
*porte_pcr0 = 0b00000000000000000000101000000;
// set as output
*gpioe_pddr = 0b11111111111111111111111111111111;
while (1)
{
*gpioe_pdor = 0b11111111111111111111111111111111;
delay(1);
*gpioe_pdor = 0b00000000000000000000000000000000;
delay(1);
}
}


Are you sure you enabled the Port E module clock? (bit 13 on SIM_SCGC5)
 
The following users thanked this post: Whales

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #6 on: August 10, 2021, 10:40:50 pm »
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 are options for 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: [Select]
#include <Arduino.h>

int main()
{
int32_t  *sim_scgc5 = (int32_t *)0x40048048; //system clock gating control reg 5
int32_t *porte_pcr0 = (int32_t *)0x4004D000; //control
int32_t *porte_pcr1 = (int32_t *)0x4004D004; //control
int32_t *porte_pcr2 = (int32_t *)0x4004D008; //control
int32_t *porte_pcr3 = (int32_t *)0x4004D00C; //control
int32_t *gpioe_pdor = (int32_t *)0x400ff100; //data out
int32_t *gpioe_psor = (int32_t *)0x400ff104; //set
int32_t *gpioe_pcor = (int32_t *)0x400ff108; //reset
int32_t *gpioe_ptor = (int32_t *)0x400ff10c; //toggle
int32_t *gpioe_pdir = (int32_t *)0x400ff110; //data in
int32_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:
Quote
Prior to initializing a module, set the corresponding bit in SCGCx register to enable the clock. Before turning off the clock, make sure to disable the module.

Perhaps there is a way to enable/disable the GPIO modules still.  I'll keep searching the manual to see what I can find.
« Last Edit: August 10, 2021, 10:44:34 pm by Whales »
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #7 on: August 11, 2021, 12:58:53 am »
I can't find anything about enabling or disabling the GPIO module.  Some from-scratch code for a related processor suggests there shouldn't be any more registers needed.

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #8 on: August 11, 2021, 01:11:23 am »
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:912
fault_isr () at /home/valentine/.platformio/packages/framework-arduinoteensy/cores/teensy3/mk20dx128.c:129

Hohoho I think its trying to read/write somewhere it shouldn't, faulting and then repeating  8)

This 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.
« Last Edit: August 11, 2021, 01:13:08 am by Whales »
 

Offline pgo

  • Contributor
  • Posts: 31
  • Country: au
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #9 on: August 11, 2021, 01:49:50 am »
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 errors
   MPU->CESR = MPU_CESR_SPERR_MASK;
#endif

Also - 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.
« Last Edit: August 11, 2021, 01:53:43 am by pgo »
 
The following users thanked this post: Whales

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #10 on: August 11, 2021, 02:34:06 am »
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 errors
   MPU->CESR = MPU_CESR_SPERR_MASK;
#endif


Thankyou, 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 models  :-\  I guess changing chips within the family is an unusual move by customers.

Quote
Also - 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)?

It'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() in mk20dx128.c
« Last Edit: August 11, 2021, 02:49:28 am by Whales »
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #11 on: August 11, 2021, 07:26:31 am »
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: [Select]
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Code: [Select]
Performing single step...
...Target halted (DBGRQ, PC = 0x0000052C)
Reading all registers
Read 4 bytes @ address 0x0000052C (Data = 0xFE78F000)
Performing single step...
...Target halted (DBGRQ, PC = 0x00001220)
Reading all registers
Read 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 0x99628888
Performing single step...
Reading all registers
ERROR: Cannot read register 0 (R0) while CPU is running
ERROR: Cannot read register 1 (R1) while CPU is running
ERROR: Cannot read register 2 (R2) while CPU is running
ERROR: Cannot read register 3 (R3) while CPU is running
ERROR: Cannot read register 4 (R4) while CPU is running
ERROR: 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.
« Last Edit: August 11, 2021, 08:39:14 am by Whales »
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #12 on: August 11, 2021, 09:35:08 am »
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.
« Last Edit: August 11, 2021, 09:37:45 am by Whales »
 

Offline DavidMenting

  • Contributor
  • Posts: 43
  • Country: nl
    • Nut & Bolt interaction design
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #13 on: August 11, 2021, 08:11:39 pm »
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?
 
The following users thanked this post: Whales

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 2859
  • Country: fi
    • My home page and email address
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #14 on: August 12, 2021, 11:49:54 am »
The teensy environment has had (probably) months of man-hours put into it
Most definitely, yes (as discussed at forum.pjrc.com); and a lot of the startup code is in the proprietary MKL02/MKL04 bootloader chips, too.

and the chips are simply far too different.
Yep.  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 think PJRC's IC_MKL02Z32_QFN16 "bootloader" chip works with MK20DX256ZVLK10, either, but you could ask and verify this at forum.pjrc.com.

Me, I'd really like to do something similar with Teensy 4.0/4.1 (using IC_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.)
 
The following users thanked this post: Whales

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 7296
  • Country: fr
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #15 on: August 12, 2021, 05:45:17 pm »
Not sure what exactly you want to do and especially how... I suppose the Teensy 4.1 has not enough IOs for your needs?
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 2859
  • Country: fi
    • My home page and email address
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #16 on: August 13, 2021, 12:01:59 am »
Not sure what exactly you want to do and especially how... I suppose the Teensy 4.1 has not enough IOs for your needs?
The 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 how SparkFun MicroMod Teensy is 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.
 

Offline Whales

  • Super Contributor
  • ***
  • Posts: 1325
  • Country: au
    • Halestrom
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #17 on: August 13, 2021, 02:08:17 am »
Quote
And how is the 80-LQFP part connected? Did you spin a new board or is it connected to the 64-LQFP footprint somehow?
I 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. 



Have you recompiled the code to run on the ZVLK10 or are you using the same binary?

Both, 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.

Quote
I do not think PJRC's IC_MKL02Z32_QFN16 "bootloader" chip works with MK20DX256ZVLK10, either, but you could ask and verify this at forum.pjrc.com.

Not 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 :P
« Last Edit: August 13, 2021, 02:25:55 am by Whales »
 

Offline DavidMenting

  • Contributor
  • Posts: 43
  • Country: nl
    • Nut & Bolt interaction design
Re: [half-solved] Different model of MK20DX Kinetis & Teensy3.2 code
« Reply #18 on: August 13, 2021, 11:10:49 am »
I really like that hacky aesthetic :) I 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  |O
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf