Teensy 4.0 code security?

Hi all,

after adding loads of informative dump functions to the sketch, modifications in imxrt1662.ld, bootdata.c and startup.c and adapting the teensy4_hab.csf I finally made it. So the ROM-bootloader sucessfully passed HAB. :cool:

Here's the output of the sketch:
Code:
CPU initialized and running from 6000346D
CPU UID:  28:4A:41:D2:65:F8:29:69
SRK Hash: 357F286C 9D03F0B5 0FD17D0B BC95D1AE A4845637 0F8C747F F6E81875 F973F092

Vectors (FLS): 60002000
 [0] = 20010000 (Stack address)
 [1] = 60002009 (Entry address)
Vectors (RAM): 20003C00
 [0] = 60003691 (Stack address)
 [1] = 60003691 (Entry address)

SRC Boot Info BOOT_MODE[1:0] = 0
 BT_FUSE_SEL =    1
 DIR_BT_DIS =     1
 SEC_CONFIG =     1
 BOOT_CFG1 =      0x19
 BOOT_CFG2 =      0x00
 BOOT_CFG3 =      0x00
 BOOT_CFG4 =      0x00

HAB Version: 4.3.7
IVT detected at: 60001000
Image Vector Table (IVT) at Addr: 0x60001000
 0xD1 0x00 0x20 0x43
 0x09 0x20 0x00 0x60
 0x00 0x00 0x00 0x00
 0x30 0x10 0x00 0x60
 0x20 0x10 0x00 0x60
 0x00 0x10 0x00 0x60
 0x00 0xB0 0x00 0x60
 0x00 0x00 0x00 0x00
  Tag: 0xD1 -> IVT
  Len: 0x0020 -> 32 Bytes
  Par: 0x43 -> HABVer: 4.3
    Entry:     0x60002009
    reserved:  0x00000000
    DCD:       0x60001030
    Bootdata:  0x60001020
      ImgStart:  0x60000000
      ImgSize:   0x0000BED0 (48848 Bytes)
      Plugin:    0x00000000
    Self:      0x60001000
    CSF:       0x6000B000
    reserved:  0x00000000

CSF detected at: 6000B000
Command Sequence File (CSF) at Addr: 6000B000
  Tag: 0xD4 -> CSF
  Len: 0x0030 -> 48 Bytes
  Par: 0x41 -> HABVer: 4.1

---- CSF Command #0 ----
Command Data:
  0xBE 0x00 0x0C 0x00
  0x03 0x17 0x00 0x00
  0x00 0x00 0x00 0x30
  Tag: 0xBE -> INS_KEY
  Len: 0x000C -> 12 Bytes
  Par: 0x00
    Flags:   0 0 0 0 0 0 0 0 
             H C M F C D C A
             S I I I F A S B
             H D D D G T F S
    Proto:   0x03 -> SRK
    Algo:    0x17 -> SHA256
    Src:     0x00
    Trg:     0x00
    keyAddr: 0x00000030

---- CSF Command #1 ----
Command Data:
  0xCA 0x00 0x0C 0x00
  0x01 0xC5 0x00 0x00
  0x00 0x00 0x04 0x98
  Tag: 0xCA -> AUTH_DATA
  Len: 0x000C -> 12 Bytes
  Par: 0x00
    Key:     0x01
    Proto:   0xC5 -> CMS
    Engine:  0x00 -> ANY
    Config:  0x00
    crtAddr: 0x00000498

---- CSF Command #2 ----
Command Data:
  0xCA 0x00 0x14 0x00
  0x00 0xC5 0x00 0x00
  0x00 0x00 0x06 0x98
  0x60 0x00 0x10 0x00
  0x00 0x00 0xA0 0x00
  Tag: 0xCA -> AUTH_DATA
  Len: 0x0014 -> 20 Bytes
  Par: 0x00
    Key:     0x00
    Proto:   0xC5 -> CMS
    Engine:  0x00 -> ANY
    Config:  0x00
    crtAddr: 0x00000698
    blkAddr: 0x60001000
    blkSize: 0x0000A000 (40960 Bytes)

Linker Info
 Image: S=60000000 E=6000BECF L=0000BED0
Name     Size     VMA      LMA     
 .flsCfg 00000200 60000000 60000000 (512 Bytes)
 .text   00007CD0 60001000 60001000 (31952 Bytes)
 .itcm   00000000 00000020 60008CDC (0 Bytes)
 .data   00002200 20000000 60008CDC (8704 Bytes)
 .pad    00000124 6000AEDC 6000AEDC (292 Bytes)
 .bss    000022C0 20003000 00000000 (8896 Bytes)
 .csf    00002000 6000B000 6000B000 (8192 Bytes)
ROM-Boot ok.
Check target at address 60000000
Check target...success
HAB Configuration: 0xf0 (open) HAB State: 0x66 (non-secure)
No HAB Events Found!

And here is how the teensy4_hab.csf looks:
Code:
[Header]
	Version = 4.1
[Install SRK]
	File = "../crts/SRK_table.bin"
	Source Index = 0
[Install NOCAK]
	File = "../crts/SRK1_sha256_2048_65537_v3_usr_crt.pem"
[Authenticate CSF]
	Signature Format = CMS
[Authenticate Data]
	Verification Index = 0
	Blocks = 0x60001000 0x00001000 0x0000A000 "image.bin"
	

#[Unlock]
#	Engine = OCOTP
#	Features = JTAG
#	#UID is fuses 0x410 & 0x420 (HW_OCOTP_CFG0, HW_OCOTP_CFG1)
#	#UID = 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef


# key blob info on security manual, page 429 - blog creation only in secure mode
 
after adding loads of informative dump functions to the sketch, modifications in imxrt1662.ld, bootdata.c and startup.c and adapting the teensy4_hab.csf I finally made it. So the ROM-bootloader sucessfully passed HAB. :cool:

Awesome news!


How to get back my modifications to your repository?

The best way is to fork the code on github, then check out your fork, edit the files, commit the changes, push the changes to github, and then on github website create a pull request.

But if you get stuck on all that git & github stuff, don't worry. I'm flexible. Just posting the files here on this forum is perfectly fine (click Go Advanced to get to the full editor which lets you attach files). Or just about any other way of sharing files is fine. It's the code that matters, not the mechanics of git & github.
 
What Paul says of course ... I was assuming new to github to ask?
It can be done on the web - to be somewhat clearer ... with a github account - go to each file and edit "on Paul's repository" - and paste changed code in and save - then it will make a ghost fork in your name and then use that for the Pull request. Then allow the ghost to be 'deleted' when the pull request is honored.
 
Good News...

Depending on your machine platform, Some of the Github stuff is getting a bit simpler.

Example if you are running a windows machine, you install the Github for windows app. Then when you are up on github, and looking at a repository, you have a couple of options, you can fork it to your own github account, or you can simply download the project to your machine...

If you make changes, you can easily do commits and the like. If you had simply downloaded the repository and not forked it. Github app will notice you do not have write access and will ask you if you wish to fork the project and do the stuff to set it up for you... But again assuming you have a github account. It also has menu items and at times button to press to start up a Pull Request.

Also depending on if this is a github project that you will continue to work with. When I am making a new set of changes, I will create a new "Branch" of the code and do all of the "Commit" to the new branch, and then do the Pull Request with this new branch. This way you can always switch back to other branch if you need a clean branch. When Paul then incorporates your changes or someone elses you can sync up your master branch to Paul's...

But again Great news.
 
Looks like your program is able to parse the CSF commands!

Code:
---- CSF Command #0 ----
Command Data:
  0xBE 0x00 0x0C 0x00
  0x03 0x17 0x00 0x00
  0x00 0x00 0x00 0x30
  Tag: 0xBE -> INS_KEY
  Len: 0x000C -> 12 Bytes
  Par: 0x00
    Flags:   0 0 0 0 0 0 0 0 
             H C M F C D C A
             S I I I F A S B
             H D D D G T F S
    Proto:   0x03 -> SRK
    Algo:    0x17 -> SHA256
    Src:     0x00
    Trg:     0x00
    keyAddr: 0x00000030


Where did you find documentation about the CSF data format?
 
Wow - was just going to start reading up on HAB to play around with it but looks like its solved - really is great news. Looking forward to see what you did to get it working ?
 
Ok, just created a draft pull request for the changes I made on my branch of the forked project. It's just draft to give you fast access, but I would like to clean it up a liitle.
 
Looks like your program is able to parse the CSF commands!




Where did you find documentation about the CSF data format?

Yes, it's not explicitly written as such, but all the information is the contained in the HAB4 API documentation contained in the CST tool documentation folder.
 
Yes, it's not explicitly written as such, but all the information is the contained in the HAB4 API documentation contained in the CST tool documentation folder.

Yes, you're right. I was re-reading HAB4_API.pdf. Indeed it is documented in chapter 4 and the constants in chapter 6. Like so much of NXP's documentation, it's quite difficult to read if you don't already understand and they include very little explanation of how things are meant to work.

I merged your pull request. Later today I will begin bringing the changes into the core library. Next week I'll start working on updating the bootloader for HAB awareness.

Please email me directly with your shipping address. Within the next couple weeks I will send you 5 Teensy 4.0 boards with non-frozen fuse settings, so you can begin experimenting with burning the fuses.
 
Next week I'll start working on updating the bootloader for HAB awareness.
Can you point me to some more detailed documentation about the boot process? I do not yet have a clear picture of it. Here is, what I understand so far from what I read so far:

I read in the teensy reference (https://www.pjrc.com/teensy/check_halfkay.html) that the so called "HalfKay" bootloader is used to download and flash new hex images. Looking at the source code of the teensy loader cli it will take the input hex file extract the address information and binary contents and send it to the teensy board via USB using the HalfKay protocol. As the communication is using USB which is routed exclusively to the i.MX-RT, the HalfKay bootloader must be running from this MCU. As there is obviously no address information given to the target the HalfKay bootloader must have embedded the valid address range of the NOR flash.
After power-on the first piece of code running on the i.MX-RT is NXP's ROM-bootloader which is controlled primarily by the boot mode selection pins and secondarily by the boot config eFuses. The upper boot selection pin is pulled to GND and the lower pin is controlled by Kinetis chip the later will define the boot device. So it can potentially select between "Serial Downloader" and "Boot From Fuses". As I've never seen the "Serial Downloader" having been selected and also the teensy loader cli doesn't seam to operate according to the serial download protocol (SDP) specified in the i.MX-RT Reference Manual, I assume that normally only "Boot From Fuses" will be selected by the Kinetis, even if I think ther is a way to tell the Kinetis to drive the i.MX-RT into the "Serial Downloader" mode. So excluding this option for normal firmware updates "Booting From Fuses", according to the read out fuses, slects the boot from serial NOR flash via FlexSPI, which just loads or excecutes in place the image which has previously been downloaded and flashed into the NOR flash. So I'm wondering how the HalfKay bootloader is brought in service. To me, from reading the schematics, the only obvious other option seams to be, that the Kinetis chip interacts with the target via JTAG protocol in order to inject the code for the HalfKay bootloader. This would explain why all the JTAG-related pins are allocated and connected to the Kinetis chip and why the default setting of DAP_SJC_SWD_SEL, which is SWD, is changed to JTAG. Can you confirm my assumptions?

I'm asking this, because this has implcations on the secure boot. If you leave open the JTAG, this is a potential vulnerability. If you secure JTAG, you need some piece of SW or a HAB Command Sequence File which reenables the JTAG at will. But that piece of SW or CSF needs to be properly signed with the customer-individual key.

Ok, before thinking more deeply about how to solve this I should have a confirmation or correction of my assumptions.
 
Always assumed the bootloader MCU controlled the target and pushed HalKay to RAM to run and perform the code loading to target flash - as noted given it controls the JTAG pins.

If so then when HAB fuses are set - ideally this avenue is still open for programming with proper key in place in the new HEX - but not needing the key itself to do HalfKay FLASH write? But all is secure to the FLASH even with JTAG - it can write bytes - but on booting HAB - they have to be securely verified to be read or executed against the target's hidden internal key?
 
Ok, so assuming the bootloader image embedded in the Kinetis MCU cannot be updated in the field with a signed one, the i.MX-RT can be updated easily according to the known way only as long as JTAG access is open which probably would be the default state for a securable teensy.
Next step would be to provision the i.MX-RT with a SRK hash. Now, still open, you should prepare a signed image and check that HAB is working properly, and if so it's time to set the i.MX-RT to "closed".
From now on, the code stored to flash must be properly signed in order to run. But as the JTAG is still open, the Kinetis MCU is still able to inject the HalfKay into the CPU's RAM for updating the application image in flash. Anyway this is an potential security risc as if you de-solder the Kinetis MCU you can still access the i.MX-RT via unsecured JTAG and are able to inject malicious SW.
So one step furter with higer degree of security is to secure JTAG access, potentially loosing the way of the Kinetis MCU to inject the HalfKay and thus loosing the default way of recovery. There exist several options to still have a way of recovery:
1. You embed a mechanism in every application image that allows to enable JTAG access at will. (OCOTP_SCS[HAB_JDE])
2. You embedd a HalfKay or custom bootloader in every signed application image, so that the bootloader waits some time to be asked for updates on every reset and when timed out hands over control to the actual application.
3. The flash is partitioned so that the first running application code is a secondary bootloader, some boot code which may be of type 1 or 2. This boot code should not normally be updated when the bootloader (HalfKay or custom) updates the application. The application itself doesn'n need to always include the boot code and is flashed to another partition of the flash, starting at a higher erase sector.
With all tose options we move further away from the HalfKay injected by the Kinetis MCU to a bootloader that is part of the i.MX-RT while gaining more security.

But if something went wrong with the boot code in the i.MX-RT you potentially brick your teensy. So in my opinion it is strongly recommended to have a fool-proove recovery option which would be NXP's "Serial Downloader" which can be enabled by the Kinetis MCU. So there should be an option to drive this way if necessary.

As now with the "Serial Downloader" another bootloader is in reach, that is cappable of updating the SW on the target via USB, it could also be an option to implement a host application which substitutes the teensy loader and implements NXP's SDP protocol.

Of corse that is a long way and a lot of work to do. But hey, here are a lot of developers that should be able to do this job. So I'm glad to discuss the pros and cons of those options and Paul's possible concerns.
 
If the HAB boot code can be overwritten - the chip will still only boot from code matching the embedded encryption keys? The fuses enforce that against the internal stored keys right? If the user has the encode key to upload they can already upload working 'keyed' code - if not then changing the HAB on internal ROM won't help?

And the code on the external FLASH is still encrypted so can only run on an MCU paired with the right keys?
 
If the HAB boot code can be overwritten - the chip will still only boot from code matching the embedded encryption keys?

I'm not sure exactly what is meant by HAB boot code. HAB, once enabled is enforced by the ROM bootloader which cannot be overwritten.

The ROM bootloader does only execute user supplied code, which is properly signed with keys matching the fuse-programmed SRK. Once this user supplied code is running, it might overwrite "itself" in the flash and thus after reboot the ROM bootloader cannon verifiy anymore valid code.


The fuses enforce that against the internal stored keys right?

Yes, exactly.

If the user has the encode key to upload they can already upload working 'keyed' code - if not then changing the HAB on internal ROM won't help?

The encode key is actually the signing key which is an RSA private key. It is just used to sign the binary image you want to be able to run on a dedicated machine. How his signed image gets into the CPU is not defined by the signing. Anyway if there exists a way to download any code to the machine, you are able to download what ever you want, signed or not. The only difference is, that with the next reset, the ROM bootloder doesn't execute what has been downloaded, is not properly signed. Once HAB is enforced by setting the i.MX-RT to closed, there is no way back to execute any non-signed code, except you inject it by any other means e.g. JTAG. You can also write an application that downloads and executes other non-signed code via SPI, UART, ... But this has to be enabled by that piece of software running at the MCU after having been passed the checks of the ROM bootloader.

And the code on the external FLASH is still encrypted so can only run on an MCU paired with the right keys?
Right now we did not yet talk about encryption. That's a further step to take to get an even higher degree of security. The image in the external flash, in order to be able to run on a dedicated machine, must besides the actual code contain the RSA public key associated with the RSA private key used for signing and a signature which can only be verified with the contained RSA public key. Anyway the public key is only taken into account by the ROM bootloader, if its SHA256 signature matches the SRK-hash fuse-programmed into the CPU.

So yes, the code must have been signed for the CPU.
 
But if something went wrong with the boot code in the i.MX-RT you potentially brick your teensy.

Indeed, when PJRC sells a Teensy without certain fuses set, there will be many possible paths to bricking those boards.


Of corse that is a long way and a lot of work to do. But hey, here are a lot of developers that should be able to do this job. So I'm glad to discuss the pros and cons of those options and Paul's possible concerns.

I hope you can understand 2 less than ideal realities of this situation.

1: Other urgent projects are going to keep me from putting serious dev time into this for at least a few weeks, and possibly not until we're shipping an 1170-based Teensy sometime next year.

2: The inner workings of Teensy's bootloader are a sensitive subject. Low cost, maker-oriented boards are a highly competitive market. Several very well-known companies wish to create their own non-Teensy IMXRT products. No-name cloners desire to sell counterfeits and deflect all support costs back to PJRC.

So I'm not really ready to discuss these details right now, and some details about the bootloader really aren't open for public discussion. Much as I would like to talk openly about everything, the business reality just doesn't make that practical.

But what I will do soon is find the earlier Teensy 4.0 test fixture (which is currently somewhere in storage). I'm really can't mess with the text fixture we're currently using every week to make Teensy 4.0. But since releasing Teensy 4.0 last year, I've made 2 test fixtures. The earlier one had some annoying issues (false negatives - perfectly good boards would not always pass), but does work. I can repurpose that old one to create some boards with different fuse settings.

I will send you 5 free boards, as a special "thank you" for helping with HAB. Odds are strong they'll end up bricked or (maybe) only usable with NXP's tools. But I really want to send you something as soon as I can, because I really do appreciate your help with the HAB issue. As you experiment with them, I hope you'll keep those 2 issues in mind.


If the HAB boot code can be overwritten - the chip will still only boot from code matching the embedded encryption keys?
....
And the code on the external FLASH is still encrypted so can only run on an MCU paired with the right keys?

There are multiple keys and many optional features, so this all tends to get pretty confusing. I'm pretty sure in the long term we'll officially support only a subset of all the features, but how that's going to go is still unknown at this time.

But to simplify a bit, there are basically 2 different keys. The HAB stuff we've discussed so far is about authentication key (by "key" I mean a group of related things... a private key, public key, trust root, certificate, key hash, etc). Authentication doesn't hide your code at all. Using only the authentication key, someone could desolder the flash chip and read all your code. But they can't alter the code (unless they know your private key). Even if you don't care about prohibiting other people from running their code on your board, the authentication key is critically important because turning on the hardware security features means only authenticated code is allowed to run.

As far as I know, NXP/Freescale doesn't support any way to keep your code secret without jumping through all the authentication hoops. Maybe it can be done, but I can't see any way from all the info I've seen so far. If you use the encryption features without HAB, major security holes are left open for an attacker to capture your code in plaintext form, even if the copy stored on the flash chip is encrypted.

A separate key, or pair of keys, is used to keep your code secret. That encryption key is completely separate from the authentication key. We haven't talked about that encryption key and encryption process much. NXP's documentation on this stuff is pretty thin, and some or all might require a NDA.

When we do support code security and sell a board which can be locked, one of the important goals is creating easy-to-use tools and clear documentation about how it works, without compromising any of NXP's confidential info.
 
Last edited:
1: Other urgent projects are going to keep me from putting serious dev time into this for at least a few weeks, and possibly not until we're shipping an 1170-based Teensy sometime next year.

2: The inner workings of Teensy's bootloader are a sensitive subject. Low cost, maker-oriented boards are a highly competitive market. Several very well-known companies wish to create their own non-Teensy IMXRT products. No-name cloners desire to sell counterfeits and deflect all support costs back to PJRC.

Ok, fully understand all that. It's a pity that you don't even have much time to determine direction which to go for this topic, as I'm ready to give my support not only for development but also for architectural design. Anyway I know that even making decisions takes time as long as their impact is not fully understood. Hope, I still can support this topic, if you find some time to review my suggestions or share your concerns of stepping away from the current boot concept, probably by private mail or discussion. Would be interested to here what's the clou in your design that safes teensy from being counterfeited and thus is beeing the essential feature which has to be saved form being eliminated in new design cosiderations. Maybe with help of the security features you can also establish a anti-counterfeit protection for your boards. You may then even sell low-cost, couterfeit-protected maker-boards with security mode locked to "open" on the left hand side and securable boards at higher price on the right hand side.

I will send you 5 free boards, as a special "thank you" for helping with HAB. Odds are strong they'll end up bricked or (maybe) only usable with NXP's tools. But I really want to send you something as soon as I can, because I really do appreciate your help with the HAB issue.

Thank you very much in advance. It's a pleasure for me to be of help.

As you experiment with them, I hope you'll keep those 2 issues in mind.

I will be really careful when experimenting with them and I will share my experiences here.

By the way, is there a way to ask the Kinetis MCU to drive the BOOT_MODE[0] pin of the i.MX-RT high or can it be safely overruled externally without damaging the Kinetis MCU?
 
re p#42 - sorry inexact language - just trying to follow the concept ...

Assumed mainline T_4.x's would not be changed to use this HAB overhead?
>> If so can the DMAMEM be repurposed selectively after boot to store USB Buffers when the HAB Boot is reported as error free?

... and assumed that the goal here was to in the end do the github.com/PaulStoffregen/hab_tests - only when the 1062 was placed into encrypted mode and external code was rendered secure on 'special' devices at risk of being bricked or lost - for custom PCB's using 'special' alternate version of the HAB aware bootloader chip, and perhaps a unique run of "T_4.x encrypted" boards with special 'RED" or other marking as noted before?
 
Assumed mainline T_4.x's would not be changed to use this HAB overhead?

At least for Teensyduino 1.54-beta1, I'm going to reduce DMAMEM max size from 512K to only 504K.

In the future we might provide a mechanism for programs wishing to access the HAB logfile to reserve the first 8K.


... and assumed that the goal here was to in the end do the github.com/PaulStoffregen/hab_tests - only when the 1062 was placed into encrypted mode and external code was rendered secure on 'special' devices at risk of being bricked or lost - for custom PCB's using 'special' alternate version of the HAB aware bootloader chip, and perhaps a unique run of "T_4.x encrypted" boards with special 'RED" or other marking as noted before?

There is quite a lot of nuance & complexity to how this stuff works. Supplying "lockable" but also "brickable" boards is just one aspect of all this. All of the features are still present and usable on the regular boards, but (probably) can't be fully secured without the "lockable" hardware. I don't have time to go into the finer details, but I will quickly say the intention is to have identical software for regular versus "lockable" boards. They will use the same Tools > Board setting in Arduino and appear as identical hardware to Teensy Loader. But like with Teensy 3.x when loaded with secured code, pressing the button (either intentionally of accidentally) will destroy the loaded code, whereas with unsecured code you can recover from an accidental button press by just power cycling, since erase occurs only when Teensy Loader actually loads new code.

All Teensy 3.x boards can be bricked, but we make it as difficult as possible. You can't do it by normal uploading. You have to both erase a bit and program a bit to get into the secured state with mass erase disabled. Frank and others have done it while experimenting, but it's usually pretty far outside of the path most people follow.

With Teensy 4.x, a major goal was to make the product "unbrickable". Well, at least by all software use - you can always destroy hardware with too much voltage or other electrical abuse. A lot of work went into that special 15 sec restore process as well, and it has saved several people from problems. I'm not eager to have mainline Teensy 4.x with any way to brick the hardware, so when(if) PJRC sells lockable boards, we'll make it a different part with a clear mark on the PCB. But other than being lockable, they will be identical from a software perspective, just like Teensy 3.x is when you edit the code to turn on the FSEC bit.
 
...
There is quite a lot of nuance & complexity
...
when(if) PJRC sells lockable boards, we'll make it a different part with a clear mark on the PCB. But other than being lockable, they will be identical from a software perspective, just like Teensy 3.x is when you edit the code to turn on the FSEC bit.

Indeed it has a lot of both... - that adds some clarity.
 
At least for Teensyduino 1.54-beta1, I'm going to reduce DMAMEM max size from 512K to only 504K.

I decided to reverse course on this. All programs will be back to having 512K DMAMEM & heap available on Teensy 4.0 & 4.1.

https://github.com/PaulStoffregen/cores/commit/077f18e1230c1fd9cfede251f33d080d214b4dd1

Programs needing to access the HAB logged events can now define a special array to prevent the DMA buffers from clobbering the HAB event log memory.

https://github.com/PaulStoffregen/hab_tests/commit/910b543a71fc8fb8c31b0e900473e835fbc3aa3f
 
I decided to reverse course on this. All programs will be back to having 512K DMAMEM & heap available on Teensy 4.0 & 4.1.
...
Programs needing to access the HAB logged events can now define a special array to prevent the DMA buffers from clobbering the HAB event log memory.
...

That looks nice, and the .ld has the .hab_log that may or may not be empty and no need to adjust anything - except HAB users will have reduced DMAMEM - though they could creatively find that 8KB if needed after a clean startup.
 
Back
Top