MCUXpresso Config Tools Knowledge Base

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MCUXpresso Config Tools Knowledge Base

Labels

Discussions

Sort by:
A new version of the Kinetis Expert Configuration Tools has been released and is available both online (Welcome to Kinetis Expert | Kinetis Expert ) or for download as desktop tool (Software Development Kit for Kinetis MCUs|NXP ).   The set of the tools has a new member: the Clocks Tool: Simple UI for clock parameter viewing and modification Graphical view for easy navigation and visualization of settings and frequencies Generate configuration code using KSDK v2 Inspect and modify clock configuration from clock input source up to the core/peripherals Validate clock settings and calculate the resulting output clock frequencies Determines suitable clock settings for given output requirements Integrated with the Pins Tool   Main features of Pins Tool and Clocks Tool: Available as Web and Desktop application Kinetis SDK v2 support Multicore support Localized for English and Simplified Chinese Mostly Connected: On-Demand device data download Integrates with any compiler and IDE Generation of documented C code which is C++ aware   What's New Added Clocks Tool Added Support for boards, kits and templates Added Labels and Identifier support Added Log and Problems View Export downloaded data to copy or share device information data Bug fixes and improved documentation The release notes of the desktop application are attached to this article.   Clocks Tool The new member of the suite of configuration tools is the Clocks Tool.  Use the Tools menu to select and switch between the tools:   The Clocks Tool provides graphical views for configuration and navigation in the clocks of the hardware:   Templates, Kits, Boards and Processors When creating a new configuration, it offers Templates, Kits, Boards and Processors. Custom configurations can be stored as templates and then used for new configurations.   Board Specific Functions With the provided board and kit configurations, there are now pre-configured initialization functions for major blocks on the board:   Labels and Identifiers In the Pins Tool there are two new columns: Label and Identifier: The Label is a user name/string to identify or describe the pin. The Identifier is a user C/C++ identifier which is added to the generated source code to be used by the application.   Export Data To simplify downloading the device specific data for the desktop tool, the 'Export' function can be used to download and export the data. The data can be copied that way to another machine or all data for a set of devices can be loaded.     The device support for the clocks tool is staged, so initially not all SDK V2 devices are included. As of Oct 14, the the following Kinetis SDK V2 R1 devices are supported by the Clocks Tool: MK21FN1M0AVLQ12 MK21FN1M0AVMC12 MK21FN1M0AVMD12 MK21FN1M0VLQ12 MK21FN1M0VMC12 MK21FN1M0VMD12 MK21FX512AVLQ12 MK21FX512AVMC12 MK21FX512AVMD12 MK21FX512VLQ12 MK21FX512VMC12 MK21FX512VMD12 MK22FN128CAH12 MK22FN128VDC10 MK22FN128VLH10 MK22FN128VLL10 MK22FN128VMP10 MK22FN1M0AVLH12 MK22FN1M0AVLK12 MK22FN1M0AVLL12 MK22FN1M0AVLQ12 MK22FN1M0AVMC12 MK22FN1M0AVMD12 MK22FN1M0VLH12 MK22FN1M0VLK12 MK22FN1M0VLL12 MK22FN1M0VLQ12 MK22FN1M0VMC12 MK22FN1M0VMD12 MK22FN256CAH12 MK22FN256VDC12 MK22FN256VLH12 MK22FN256VLL12 MK22FN256VMP12 MK22FN512CAP12 MK22FN512VDC12 MK22FN512VLH12 MK22FN512VLL12 MK22FN512VMP12 MK22FX512AVLH12 MK22FX512AVLK12 MK22FX512AVLL12 MK22FX512AVLQ12 MK22FX512AVMC12 MK22FX512AVMD12 MK22FX512VLH12 MK22FX512VLK12 MK22FX512VLL12 MK22FX512VLQ12 MK22FX512VMC12 MK22FX512VMD12 MK24FN1M0VDC12 MK24FN1M0VLL12 MK24FN1M0VLQ12 MK26FN2M0CAC18 MK26FN2M0VLQ18 MK26FN2M0VMD18 MK26FN2M0VMI18 MK63FN1M0VLQ12 MK63FN1M0VMD12 MK64FN1M0VDC12 MK64FN1M0VLL12 MK64FN1M0VLQ12 MK64FN1M0VMD12 MK64FX512VDC12 MK64FX512VLL12 MK64FX512VLQ12 MK64FX512VMD12 MK65FN2M0CAC18 MK65FN2M0VMI18 MK65FX1M0CAC18 MK65FX1M0VMI18 MK66FN2M0VLQ18 MK66FN2M0VMD18 MK66FX1M0VLQ18 MK66FX1M0VMD18 MK80FN256CAx15 MK80FN256VDC15 MK80FN256VLL15 MK80FN256VLQ15 MK81FN256CAx15 MK81FN256VDC15 MK81FN256VLL15 MK81FN256VLQ15 MK82FN256CAx15 MK82FN256VDC15 MK82FN256VLL15 MK82FN256VLQ15 MKL13Z32VFM4 MKL13Z32VFT4 MKL13Z32VLH4 MKL13Z32VLK4 MKL13Z32VMP4 MKL13Z64VFM4 MKL13Z64VFT4 MKL13Z64VLH4 MKL13Z64VLK4 MKL13Z64VMP4 MKL17Z128VFM4 MKL17Z128VFT4 MKL17Z128VLH4 MKL17Z128VMP4 MKL17Z256VFM4 MKL17Z256VFT4 MKL17Z256VLH4 MKL17Z256VMP4 MKL17Z32VDA4 MKL17Z32VFM4 MKL17Z32VFT4 MKL17Z32VLH4 MKL17Z32VMP4 MKL17Z64VDA4 MKL17Z64VFM4 MKL17Z64VFT4 MKL17Z64VLH4 MKL17Z64VMP4 MKL27Z128VFM4 MKL27Z128VFT4 MKL27Z128VLH4 MKL27Z128VMP4 MKL27Z256VFM4 MKL27Z256VFT4 MKL27Z256VLH4 MKL27Z256VMP4 MKL27Z32VDA4 MKL27Z32VFM4 MKL27Z32VFT4 MKL27Z32VLH4 MKL27Z32VMP4 MKL27Z64VDA4 MKL27Z64VFM4 MKL27Z64VFT4 MKL27Z64VLH4 MKL27Z64VMP4 MKL33Z128VLH4 MKL33Z128VMP4 MKL33Z256VLH4 MKL33Z256VMP4 MKL33Z32VFT4 MKL33Z32VLH4 MKL33Z32VLK4 MKL33Z32VMP4 MKL33Z64VFT4 MKL33Z64VLH4 MKL33Z64VLK4 MKL33Z64VMP4 MKL43Z128VLH4 MKL43Z128VMP4 MKL43Z256VLH4 MKL43Z256VMP4 MKS22FN256VLL12 MKS22FN256VLH12 MKS22FN128VLL12 MKS22FN128VLH12   In November, the following SDK V2.0 R2 and R3 devices will be available in the Clocks Tool: MKL14Z32VFM4 MKL14Z32VFT4 MKL14Z32VLH4 MKL14Z32VLK4 MKL14Z64VFM4 MKL14Z64VFT4 MKL14Z64VLH4 MKL14Z64VLK4 MKL15Z128CAD4 MKL15Z128VFM4 MKL15Z128VFT4 MKL15Z128VLH4 MKL15Z128VLK4 MKL15Z32VFM4 MKL15Z32VFT4 MKL15Z32VLH4 MKL15Z32VLK4 MKL15Z64VFM4 MKL15Z64VFT4 MKL15Z64VLH4 MKL15Z64VLK4 MKL24Z32VFM4 MKL24Z32VFT4 MKL24Z32VLH4 MKL24Z32VLK4 MKL24Z64VFM4 MKL24Z64VFT4 MKL24Z64VLH4 MKL24Z64VLK4 MKL25Z128VFM4 MKL25Z128VFT4 MKL25Z128VLH4 MKL25Z128VLK4 MKL25Z32VFM4 MKL25Z32VFT4 MKL25Z32VLH4 MKL25Z32VLK4 MKL25Z64VFM4 MKL25Z64VFT4 MKL25Z64VLH4 MKL25Z64VLK4   MKW21D256VHA5 MKW21D512VHA5 MKW22D512VHA5 MKW24D512VHA5   In December, the SDK 2.0 R4 devices will be supported by the Clocks Tool: MKV10Z16VFM7 MKV10Z16VLC7 MKV10Z16VLF7 MKV10Z32VFM7 MKV10Z32VLC7 MKV10Z32VLF7 MKV10Z128VFM7 MKV10Z128VLC7 MKV10Z128VLF7   MKV10Z128VLH7   MKV10Z64VFM7 MKV10Z64VLC7 MKV10Z64VLF7   MKV10Z64VLH7 MKV11Z128VFM7 MKV11Z128VLC7 MKV11Z128VLF7   MKV11Z128VLH7   MKV11Z64VFM7 MKV11Z64VLC7 MKV11Z64VLF7   MKV11Z64VLH7   MKV30F128VFM10 MKV30F128VLF10 MKV30F128VLH10 MKV30F64VFM10 MKV30F64VLF10 MKV30F64VLH10 MKV46F256VLL16 MKV46F256VLH16 MKV46F128VLL16 MKV46F128VLH16 MKV44F256VLL16 MKV44F256VLH16 MKV44F128VLL16 MKV44F128VLH16 MKV44F64VLH16 MKV42F256VLL16 MKV42F256VLH16 MKV42F128VLL16 MKV42F128VLH16 MKV42F64VLH16 MKV44F128VLF16 MKV44F64VLF16 MKV42F128VLF16 MKV42F64VLF16 MKV58F1M0VMD24 MKV58F512VMD24 MKV58F1M0VLQ24 MKV58F512VLQ24 MKV58F1M0VLL24 MKV58F512VLL24 MKV56F1M0VMD24 MKV56F512VMD24 MKV56F1M0VLQ24 MKV56F512VLQ24 MKV56F1M0VLL24 MKV56F512VLL24 MKV31F128VLH10 MKV31F128VLL10 MKV31F256VLH12 MKV31F256VLL12 MKV31F512VLH12 MKV31F512VLL12   We hope you will find this new release useful.   Thanks for designing with NXP!
View full article
The new NXP Pins tool which has been showcased at FTF 2016 in Austin is now available as Web and Desktop application. The Kinetis Expert Pins Tool makes configuring, muxing and routing of pins very easy and fast. It provides real-time feedback of conflicts and provides an intuitive graphical interface with several views. The tool generates Kinetis SDK V2.0 compatible sources files which can be directly integrated into C/C++ applications. The Pins tool is available both as Web application (no installation needed) and as a Desktop application for Linux, Mac and Windows.     You can use the Web version from Welcome to Kinetis Expert | Kinetis Expert.   It is available for download as Desktop version from Software Development Kit for Kinetis MCUs|NXP (Windows, Mac OS X and Linux 64bit) under the 'Software' category: There are two different installer types: 'offline' is a 130 MByte download. This method is recommended for slower internet connections or for installation on multiple machines. 'online' is a small 500 KByte download, all the other installation data will be loaded from the internet during installation. Mac OS X and Linux installers are 64bit. For Windows there are both 32bit and 64bit installers available.   Documenation is availble on Software Development Kit for Kinetis MCUs|NXP in the documenation download section, as well attached to this article (Getting Started is available in Chinese): An overview and tutorial can be found here: https://mcuoneclipse.com/2016/06/08/tutorial-muxing-with-the-new-nxp-pins-tool/   We hope you find this tool useful!
View full article
1.  Introduction This document describes the USB configuration component and implementation of the Audio 1.0 class application example on the MIMXRT1060-EVK board. It focuses on the MCUXpresso IDE and Config Tools. It provides an example of the Quad Timer peripheral component used as a digital-to-analog converter for processing audio data. The USB Audio class is supported in the SDK packages that are available for a wide range of MCUs. One of the last i.MX Real-Time (RT) crossover MCUs is the i.MX RT1060. It is available on the MIMXRT1060-EVK evaluation board. The SDK package already contains a demo application that demonstrates the USB Audio speaker functionality. However, a detailed guide on how to develop the application and customize the processing of audio data is not provided.  2.  Prerequisites The USB Audio application is developed in the MCUXpresso IDE 11.2.1 that is available on the http://www.nxp.com/mcuxpresso/ide website. Download and install this or newer version. The Config Tools that is used for the application design is integrated into the MCUXpresso IDE. Download the MIMXRT1060-EVK SDK support package inside the MCUXpresso IDE (see Install MCUXpresso SDKs in quick access) or separately on https://mcuxpresso.nxp.com/ pages (the SDK package must be built with the USB middleware selected).   3.  USB Audio concept The USB Audio class is supported in the USB middleware of the SDK package. The Peripherals tool from provides a USB middleware component that provides GUI for the configuration of the USB class, interfaces, and generating USB code examples. The USB Audio 1.0 speaker example, enumerated as a playback device, is available as a preset in the USB component. In this demo example, the device receives audio data and stores it in the internal buffer. The playback of audio is not a part of the generated code example, and the implementation is a part of this document. The USB Audio 1.0 speaker demo application that is described in this document consists of the following parts: Figure 1. Structure of the USB audio speaker application The USB component supports the configuration of the Audio control interface and streaming interfaces for the Audio 1.0 class (see the MCUXpresso Config Tools Project chapter for the steps of creating the project with the USB component). 3.1.     Audio control Interface The Audio control subclass provides a configuration of the USB Audio device topology by using terminals and units. The USB component supports one interrupt endpoint (control endpoint) and the audio control interface settings (the topology). See the example of the Audio speaker configuration below. Figure 2. Interface setting of the USB component The USB component supports the following terminals and units of the Audio 1.0 specification: Input Terminal Feature Unit Output Terminal All these units are used in the Audio speaker example. Input Terminal The Input Terminal (IT) is used to interface between the audio function’s ‘outside world’ and other units in the audio function. It serves as a receptacle for audio information flowing into the audio function. Its function is to represent a source of incoming audio data after this data has been properly extracted from the original audio stream into separate logical channels that are embedded in this stream (the decoding process). The logical channels are grouped into an audio channel cluster and leave the Input Terminal through a single Output Pin. The configuration of the input terminal consists of the ID (must be unique), type, number of channels, and spatial location, see below. The Input Terminal provides: Figure 3. Input terminal configuration Feature Unit The Feature Unit (FU) provides basic manipulation of multiple single-parameter on the incoming logical channels. It supports the following features: Mute, Volume, Tone Control, Graphic Equalizer, Automatic Gain Control, Delay, Bass Boost, and Loudness. The configuration of the feature unit consists of the unit ID (must be unique), source unit/terminal, and selection of features for every channel. Figure 4. Feature unit configuration  Output Terminal The Output Terminal (OT) is used to interface between the units inside the audio function and the ‘outside world’. It serves as an outlet for audio information, flowing out of the audio function. Its function is to represent a sink of outgoing audio data before this data is properly packed from the original separate logical channels into the outgoing audio stream (the encoding process). The audio channel cluster enters the Output Terminal through a single Input Pin. The configuration of the output terminal consists of the ID (must be unique), type, and source ID (unit/terminal), see below. Figure 5. Output terminal configuration 3.2.     Audio streaming interface Audio Streaming (AS) interfaces are used to interchange digital audio data streams between the Host and the audio function. Each Audio Streaming interface can have at most one isochronous data endpoint and an optional associated isochronous sync endpoint for synchronization purposes. The isochronous data endpoint is required to be the first endpoint in the AS interface. The AS interface is also used for the specification of the audio data format. The USB component Audio 1.0 class supports the Format I type of audio data only. The configuration (in the Audio speaker example) does not provide any audio class-specific interface and endpoints. See the following configuration: Figure 6. Zero bandwidth interface configuration Data output alternative interface settings provide a full configuration of audio streaming class-specific settings including the audio data format. There are additional audio class-specific settings for isochronous endpoints. Figure 7. Data output interface configuration   Figure 8. Isochronous feedback endpoint configuration   The Audio speaker example uses two endpoints: #1 – isochronous data endpoint (host output) for receiving audio data from the USB host. #2 – isochronous feedback endpoint that is used for synchronization between the USB audio device and the USB host. Audio stream interface-specific settings contain the Link to terminal setting which is linked to this audio streaming interface configuration and the audio data format configuration. The USB component supports just the Format I types. There is an additional configuration of the format – number of channels, subframe size, audio data resolution, and supported sampling frequencies.   4.  MCUXpresso Config Tools project This chapter provides a for the implementation of the USB Audio 1.0 demo project the MCUXpresso IDE 11.2.1 and using SDK 2.8.5 for the MIMXRT1060-EVK board. The newer version of the MCUXpresso IDE and SDK package for the MIMXRT1060-EVK shall be also compatible. 4.1. Board support project Open the MCUXpresso IDE. In the Quickstart Panel, select New project, in the SDK Wizard write RT1060 in the filter line, select the evkmimxrt1060 board, click the Next button. Figure 9. New EVKMIMXRT1060 project In the next window, write the project name, for example, MIMXRT1062xxxxA_     and select the USB Device Audio class on the Middleware tab (all the required components of the USB middleware are automatically selected), see below: Figure 10. USB middleware components of the new project Click the Finish button (the default libraries, compiler, linker, and memory map settings can be used). The MIMXRT1062xxxxA_USB_audio_speaker project is created in the IDE. The content is available in the Project Explorer window. 4.2.     Peripherals Open the Peripherals tool by using the Config Tools -> Peripherals. Figure 11. Selection of the Peripherals tool In the Peripherals tool, select the MIMXRT1062xxxxA_USB_audio_speaker project and create an instance of the USB 2.6.0 (or newer version) component for the USB1 peripheral in the Peripherals window, see below: Figure 12. Adding of the USB component The USB component is added to the Peripherals project (in the default functional group that is named BOARD_InitPeripherals). An empty USB component is created (there is no interface created and the USB component reports errors). The easiest way to create a functional USB configuration is by selecting from a preset. Select the Audio 1.0 – speaker (bare metal) preset. Figure 13. Selection of the Audio 1.0 speaker demo project configuration When you select the Audio 1.0 – speaker (bare metal) item, the whole configuration of the example is configured. Two interfaces are created: #0 – Audio_control #1 – Audio_streaming These interfaces contain all settings that are required for the USB Audio 1.0 speaker example. configuration of all audio units is provided in the Audio_control interface. The Device role configuration is also provided for the USB Audio demo example. See details of the provided settings in the previous chapter USB Audio concept. There is still the following error in the Problem view: Issue: USB Function Clock (USBPHY1_CLK) is inactive and USB module will not work. Level: Error Type: Validation Tool: Clocks Origin: Peripherals:BOARD_InitPeripherals Target: Clocks: BOARD_BootClockRUN Resource: USBPHY1_CLK   Figure 14. USB clock source error Right-click the error and select Show problem in BOARD_BootClockRun. Figure 15. Resolving of the USB clock source error The Clocks tool is opened, and you are navigated to the problem in the Details view. The USBPHY1 PLL clock is disabled by default (to save power). You can enable it by selecting the enabled value in the USBPHY1 clock output setting: Figure 16. Enabling of the USB clock source in the Clocks tool This setting enables the 480 MHz reference clock for USBPHY1 and the USB peripheral runs. Go back to the Peripherals tool. You can see that the error was resolved, and the code is generated. If you click the Update Code button, you can see what code is provided by the Config Tools. There are the following functions. Pins initialization functions: pin_mux.c/h – initialization of the routed pins for the peripherals (USB1, TMR3 in our use case). Clocks initialization functions: clock_config.c/h – initialization function for a configuration of the clock source, selectors, dividers, PLLs, and other system clock settings of the MCU.  A configuration of the USB1 clocks for PHY that was enabled is also provided. Peripherals initialization functions and the USB code example: peripherals.c/h  initialization functions for configured peripherals (USB1, TMR3 components). usb_device_composite.c/h contains initialized structures, initialization functions, device callback function, interrupt routine, and other USB middleware-related functions. usb_device_config.h contains USB middleware configurations (definitions) that are directly included in the USB middleware. usb_device_descriptor.c/hcontains definitions of the device descriptor, device configuration descriptor, initialized interface and endpoints configuration structures, function for device speed selection, and other USB device-related functions. usb_device_interface_0_audio_control.c/h contains the generated code example of the audio speaker. There is an application code for processing USB device requests, processing audio data, and configuration structure of the audio speaker example (buffer, runtime settings, …). When any of these generated files are customized (modified in the project), uncheck the file in the Update Code dialog. Otherwise, the changes would be lost. Figure 17. Update of the generated code in MCUXpresso IDE project The USB Audio example requires the Pins, Clocks, and Peripherals tool. Therefore, the generated code is used to replace the original code that is available in the default board support project. You can click the Cancel button and continue in the project configuration. 4.3.      DAC converter The i.MX RT1060 does not contain any DAC (Digital-to-Analog Converter). The MIMXRT1060 contains an external device that can be used to provide audio playback functionality.  This use case is already covered in the SDK Audio speaker example. You can create a simple DAC converter by using a timer of the MCU.  Select. The board provides Arduino headers that can be used for this demo purpose. The J23 header provides an output of the TMR3 – channels 0 and 1 (J23[6] and J23[5] pins). You can find this information in the Pins tool. Open the Pins tool and navigate to the Pins window. Select the BOARD_InitPins functional group (it is selected by default, and it is also included in the default initialization).To order the table lines according to the TMR peripherals, click the TMR column header. You can see that QTIMER3 (TMR3) timers #0 and #1 can be routed on Arduino header J23. When you click QTIMER3_TIMER0 and QTIMER3_TIMER1 in the TMR column, these timer outputs are routed automatically to the J23[6] and J23[5] pins on the Arduino header on the board. Figure 18. Routing of the timer pins in the Pins tool Switch to the Peripherals tool and add an instance of the Quad Timer (qtmr) component to the TMR3 peripheral. Check the checkbox of the TMR3 – the Quad Timer component is the only supported component and it is added automatically. The quad timer peripheral (TMR) supports four channels. You need two channels for each audio channel – Left and Right and the third channel for frequency. Figure 19. Quad timer component selection When the Quad Timer component is added, you can see the clock source – Bus clock 150 MHz. The USB Audio streaming contains 48 kHz. It means that the PWM must work at the multiplication of this sampling frequency. It simplifies the implementation of the DAC design. 150000000 / 48000 = 3125There are 3125 ticks of the timer per sample of audio data. To provide a better DAC output, the PWM must work on a frequency higher than 48 MHz. For example, the frequency can be 48 kHz * 5 = 240 kHz. It means that the PWM output frequency is 240 kHz and each audio sample value is set for 5 periods of the timer. However, it also means that the resolution of the timer is reduced to 3125 / 5 = 625 ticks. Finally, you have a 9-bits DAC converter that can be used for playback of audio data. The PWM output signal can be processed through a low-pass filter (R1, C1) with an output filter capacitor (C2) to remove some of the DC from the signal. Figure 20. Low-pass output filter fc=1/(2πRC) For example, use the following low pass filter: R1= 4700 Ω, C1 = 1.5 nF f c = 22575 Hz   TMR3 component configuration To provide two PWM channels, use the following configuration. First channel: Chanel ID: Left Primary timer/counter reference: Bus clock divided by 1 Counting operation: Rising edge of the primary source Timer mode initialization: PWM output PWM frequency/period: 240 kHz DMA/Interrupt mode: Polling Interrupt request: enable Compare 2 Second channel: Chanel ID: Right Primary timer/counter reference: Bus clock divided by 1 Counting operation: Rising edge of the primary source Timer mode initialization: PWM output PWM frequency/period: 240 kHz DMA/Interrupt mode: Polling Third channel for invoking the interrupt routine at sample frequency: Chanel ID: SampleFreq Primary timer/counter reference: Bus clock divided by 1 Counting operation: Rising edge of the primary source Timer mode initialization: Timer PWM frequency/period: 48 kHz DMA/Interrupt mode: Interrupt Interrupt request: enable Compare 1 Interrupt vector Enable interrupt: enabled (checked) Enable custom handle name: enabled (checked) Interrupt handler name: DAC_TMR_IRQ   Note: The interrupt of the SampleFreq channel is only used to load the compare load registers of both channels at the sampling frequency. The Digital-to-Analog conversion of both channels is synchronized and one simple interrupt routine can be used.  The Quad Timer components provide initialization but you must provide runtime functionality. Therefore, you must know the details of the PWM mode functionality (specified in the reference manual of the MCU). The PWM mode with variable frequency is driven by both compare registers. The second compare register provides a high-level period of the PWM period (duty), and the first compare register specifies the inactive part of the PWM period. The sum of these two compare registers must always be the computed resolution of the timer (625). An example of the initialization of compare registers can be found in the fsl_qtmr SDK driver, in the QTMR_SetupPwm() function.Compare registers are initialized before the counter/timer is started. The next values can be stored by using compare load registers. Thus, the loading of the compare registers is synchronized automatically by the timer itself (it is a part of the initialization setting in the fsl_qtmr driver). Therefore, the interrupt routine can be used for loading the audio data into compare load registers. The audio data is sent in the following PCM 16-bit format: one sample (4 bytes) 0 1 2 3 Left channel (low byte) Left channel (high byte) Right channel (low byte) Right channel (high byte) int16_t value (little endian format) int16_t value (little endian format)   Finally, configure the TMR3 peripheral in the following way: Figure 21. Quad timer configuration for the DAC In the Problems view, an error is reported. The error is caused by the missing fsl_qtmr SDK driver in the project (it was not added in the project wizard of the MCUXpresso IDE). Figure 22. Quad timer SDK driver error To fix the error, use the context menu of the error in the Problems view and select the Add SDK component “QTMR Driver” into the project “MIMXRT1062xxxA_USB_audio_speaker. Figure 23. Adding of the Quad timer SDK driver in the MCUXPresso project. When the option is selected, the update of the files is processed and the error disappears. The initialization of the application is done, and the generated code can be used in the project. Select the Update Code command and select update of the following files: Figure 24. Update of the generated code in MCUXpresso project All generated initialization files of Pins, Clocks, and Peripherals are stored to the project and the Develop perspective of the MCUXpresso IDE is automatically selected. You can check that all generated files are available in the project now. Note: When any of these generated files are later customized (modified in the project), the file must be unchecked in the Update Code dialog. Otherwise, the changes would be lost. 4.4.     Audio application design The USB Audio code example has been generated into the project and it works. But the playback of the audio data is not provided. Only the USB_Interface0AudioControlProcessNextAudioData() function is available in the source/usb_device_interface_0_audio_control.c source file. The received audio data is available in the internal USB_Interface0AudioControlDataBuff buffer and the index () of the newly received data is s_UsbDeviceAudioSpeaker->tdWriteNumberPlay. It is used to send data into the DAC converter.The DAC converter has not been implemented yet. There are just two PWM channels of the TMR3 that generate a zero-duty PWM output signal. Use the interrupt subroutine for the implementation of the audio playback. Copy the template of the interrupt routine from the TMR3 component in the Peripherals tool, see the Interrupt settings: Figure 25. Template of the interrupt service routine. When you click the Copy to clipboard button of the Handler template setting, you obtain the following code in the clipboard. /* TMR3_IRQn interrupt handler */ void DAC_TMR_IRQ(void) { /* Place your code here */ /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping exception return operation might vector to incorrect interrupt. */ #if defined __CORTEX_M && (__CORTEX_M == 4U) __DSB(); #endif } Place this code into the main program module source/MIMXRT1062xxxxA_USB_audio_speaker.c. It is used for the implementation of the main part of the application. The USB component contains a task call that must be placed into a loop of the main process. In this simple use case, use directly the main() function: Figure 26. USB device task function call code. /* * @brief Application entry point. */ int main(void) { /* Init board hardware. */ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitBootPeripherals(); #ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL /* Init FSL debug console. */ BOARD_InitDebugConsole(); #endif /* Enter an infinite loop */ while(1) { USB_DeviceTasks(); } return 0 ; } 4.4.1.   Audio data processing The audio data can be read directly from the existing buffer. Therefore, you can update the implementation of the USB_Interface0AudioControlProcessNextAudioData() function and use parameters to pass a pointer to data and data size. See the following update of the function: #define SAMPLE_SIZE (AUDIO_FORMAT_CHANNELS * AUDIO_FORMAT_SIZE) void USB_Interface0AudioControlProcessNextAudioData(uint8_t **audioData, uint8_t *dataSize) { if ((s_UsbDeviceAudioSpeaker->audioSendTimes >= s_UsbDeviceAudioSpeaker->usbRecvTimes) && (s_UsbDeviceAudioSpeaker->startPlayHalfFull == 1)) { s_UsbDeviceAudioSpeaker->startPlayHalfFull = 0; s_UsbDeviceAudioSpeaker->speakerDetachOrNoInput = 1; } if (s_UsbDeviceAudioSpeaker->startPlayHalfFull) { /* * size of data packet that can be sent = FS_ISO_OUT_ENDP_PACKET_SIZE * pointer to data = USB_Interface0AudioControlDataBuff + s_UsbDeviceAudioSpeaker->tdWriteNumberPlay */ *audioData = &(USB_Interface0AudioControlDataBuff[s_UsbDeviceAudioSpeaker->tdWriteNumberPlay]); *dataSize = FS_ISO_OUT_ENDP_PACKET_SIZE / SAMPLE_SIZE; s_UsbDeviceAudioSpeaker->audioSendCount += FS_ISO_OUT_ENDP_PACKET_SIZE; s_UsbDeviceAudioSpeaker->audioSendTimes++; s_UsbDeviceAudioSpeaker->tdWriteNumberPlay += FS_ISO_OUT_ENDP_PACKET_SIZE; if (s_UsbDeviceAudioSpeaker->tdWriteNumberPlay >= AUDIO_SPEAKER_DATA_WHOLE_BUFFER_LENGTH * FS_ISO_OUT_ENDP_PACKET_SIZE) { s_UsbDeviceAudioSpeaker->tdWriteNumberPlay = 0; } } else { /* * size of data packet that can be sent = FS_ISO_OUT_ENDP_PACKET_SIZE * pointer to data = USB_Interface0AudioControlDataBuff */ *audioData = USB_Interface0AudioControlDataBuff; *dataSize = FS_ISO_OUT_ENDP_PACKET_SIZE / SAMPLE_SIZE; } }   The audioData pointer reference is set to point into the audio data buffer (USB_Interface0AudioControlDataBuff) that contains the audio data received from the host. The packet size is fixed. s_UsbDeviceAudioSpeaker->tdWriteNumberPlay is the index of the next data that must be converted by using DAC. Update the declaration of the function in the header file accordingly: /* * Function for procession of next audio data from the data buffer. It can be used as a callback. */ void USB_Interface0AudioControlProcessNextAudioData(uint8_t **audioData, uint8_t *dataSize); 4.4.2.   DAC interrupt routine The interrupt routine of the TMR3 peripheral provides the functionality of the DAC converter. It processes a stream of audio data packets and uses the sample values to control the duty of the output PWM signal (the first PWM channel as the left channel and the second PWM channel as the right channel). The sampling frequency is driven by the third channel of the TMR3 (the SampleFreq channel). See the implementation of the interrupt routine and related definitions: #include "usb_device_interface_0_audio_control.h" /* Size of one received packet */ #define PCM_PACKET_SIZE AUDIO_SAMPLING_RATE_KHZ /* PCM data pointer and sample index counter */ uint8_t *pcmData; uint8_t sampleIndex = PCM_PACKET_SIZE; /* Number of ticks for each PWM period */ #define PWM_PERIOD_LENGTH_IN_TICKS 625 /* size of one sample in streaming data (PCM format) */ #define SAMPLE_SIZE (USB_INTERFACE_1_AUDIO_STREAMING_SETTING_1_AUDIO_STREAM_SETTING_1_NUMBER_OF_CHANNEL * USB_INTERFACE_1_AUDIO_STREAMING_SETTING_1_AUDIO_STREAM_SETTING_1_SUBFRAME_SIZE) /* TMR3_IRQn interrupt handler */ void DAC_TMR_IRQ(void) { static uint16_t dutyValue; /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping exception return operation might vector to incorrect interrupt. */ #if defined __CORTEX_M && (__CORTEX_M == 4U) __DSB(); #endif /* Clear the Compare Flag */ TMR3_PERIPHERAL->CHANNEL[TMR3_SAMPLEFREQ_CHANNEL].CSCTRL &= ~TMR_CSCTRL_TCF1_MASK; /* audio data processing */ /* load next audio data when the whole packet has been sent */ if (sampleIndex >= PCM_PACKET_SIZE) { // load next data uint8_t dataLength; USB_Interface0AudioControlProcessNextAudioData(&pcmData, &dataLength); /* if new packet has been received */ if (dataLength == PCM_PACKET_SIZE) { sampleIndex = 0; } } /* if the buffer (packet) contain any data to be converted */ if (sampleIndex < PCM_PACKET_SIZE) { // PCM left channel data dutyValue = ((((int16_t*)pcmData)[SAMPLE_SIZE/2 * sampleIndex]) / 128) + 256; TMR3_PERIPHERAL->CHANNEL[TMR3_LEFT_CHANNEL].CMPLD2 = dutyValue; TMR3_PERIPHERAL->CHANNEL[TMR3_LEFT_CHANNEL].CMPLD1 = PWM_PERIOD_LENGTH_IN_TICKS - dutyValue; // PCM right channel data dutyValue = ((((int16_t*)pcmData)[(SAMPLE_SIZE/2 * sampleIndex) + 1]) / 128) + 256; TMR3_PERIPHERAL->CHANNEL[TMR3_RIGHT_CHANNEL].CMPLD2 = dutyValue; TMR3_PERIPHERAL->CHANNEL[TMR3_RIGHT_CHANNEL].CMPLD1 = PWM_PERIOD_LENGTH_IN_TICKS - dutyValue; /* next sample */ sampleIndex++; } }   The audio data is loaded (the pointer to audio data buffer is used) using the USB_Interface0AudioControlProcessNextAudioData() function. The whole packet of audio data is always provided (the PCM_PACKET_SIZE definition). When any audio data is available, the sample data is used to control the PWM duty of the left and right channels. The audio data is in the int16_t format, but the compare load register needs a 9-bit unsigned integer value. Therefore, these sample values are converted by the expression (see the source code above). 5.  Conclusion This tutorial provides an example of how you can use the USB component to generate a USB Audio 1.0 demo example and how you can use the generated interface to process the stream of audio data. The provided DAC example uses the interrupts and is not optimized. In a real application, use the DMA to process the audio stream data to reduce CPU usage. The volume control, mute, and suspending of the timers (when muted or zero bandwidth interface is selected) are other improvements that should be implemented in an advanced application. 6.  References USB Audio specification on https://usb.org: Universal Serial Bus Device Class Definition for Audio Devices Universal Serial Bus Device Class Definition for Audio Data Formats Universal Serial Bus Device Class Definition for Terminal Types   NXP application note and i.MX RT1060 documentation : How to Use Freescale USB Stack to Implement Audio Class Device i.MX RT1060 Processor Reference Manual MIMXRT1060/1064 Evaluation Kit Board Hardware User's Guide
View full article
This video provides an instruction to the NXP Pins tool (see New Kinetis Expert Pins Tool V1.0 Available!). It demonstrates how to use the tool and how to configure pins with the example of the FRDM-K64F Board.   Enjoy 🙂
View full article
Measuring temperature using digital sensor DS18B20 and Arduino Multifunction Shield on FRDM K64F  This tutorial describes a simple application for measuring temperature using the digital sensor DS18B20 and the Arduino Multifunction Shield connected to FRDM K64F. You can use new feature Expansion Boards (expansion shields) included in the Pins tool v9. This feature enables quick integration of shields in an application without the need to study manuals. In this paper, you can find the environment setup, 1-wire protocol basics, and the steps of preparing a code with MCUXpresso tools (Peripherals and Pins tool). Setup environment Install MCUXpresso IDE v11.3.0 or later and SDK FRDM-K64F 2.8.2 or later. Use the FRDM K64F EVK board https://www.nxp.com/webapp/Download?colCode=FRDMK64FUG. Connect the Arduino Multifunction shield (Expansion Board) to the FRDM K64F EVK board and DS18B20 to the Arduino shield. Connect the EVK board to the PC via a USB cable. Figure 1 FRDM K64F EVK board with Arduino Multi-Function shield Have the expansion board definition file arduino_multifunction_ds18b20.xml. For detailed instructions on how to create the expansion board see the following article: Creating expansion board definition file for Arduino Multifunction shield DS18B20 Programmable Resolution 1-Wire Digital Thermometer See the documentation https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf This tutorial uses powering with an external supply. Figure 2 Powering the DS18B20 with an External Supply   See the timing diagrams for communication with the DS18B20, needed for writing 1-Wire communication protocol. Figure 3 Initialization Timing Figure 4 Read/Write Time Slot Timing Diagram The application only uses the following 1-wire protocol commands: ‘CCh’ skip ROM command - only one slave on the bus supported ’44h’ convert temperature ‘BEh’ read DS18B20 registers (temperature) Create the application in MCUXpresso IDE Begin with the hello_word example from SDK, rename the project to frdmk64_termometer. Steps to configure timer in the Peripherals tool: Go to the Peripherals tool and add/configure the PIT component. Resolve the new Error in Problems view by adding the SDK component to the project. Figure 5 PIT component in the Peripherals tool Steps to apply the expansion board and configure pin in Pins tool: Apply the expansion board (arduino_multifunction_ds18b20.xml) from menu Pins -> Apply Expansion Board menu    Figure 6 Apply expansion board dialog The Expansion Board Routing dialog is automatically opened after step 1. It provides the possibility to route signals to processor pins that are connected to the expansion board. By default, all pins are routed automatically, see below. Keep only pin A4 routed which is needed for our thermometer application. Unroute the unneeded pins by clicking the Route column or later in the Routing Details view, then click Apply.   Figure 7 Expansion board routing dialog  The action results in the following setting. When selecting Expansion board in the Labels combo, you see the labels as they are marked on the Arduino shield.  Figure 8 Expansion header view In the Routing Details view, set the electrical properties of the pin (Direction, Pull select, Pull enable). Figure 9 Electrical properties in the Routing Details view Click Update Code to update the project with the code generated by the tools. Write the thermometer application and 1-wire protocol (thermometer.c)   Rename the source file hello_world.c to thermometer.c and follow the steps below. Find the completed thermometer.c in the project.  Use the PIT timer to create methods delayMS() and delayUS() for delays of μs and ms. See the PIT interrupt handler PIT_CHANNEL_0_IRQHANDLER() function.   Write methods GPIO_low() and GPIO_high() to set the ARDUINO_A4_PIN to logical 0 and 1. These methods are based on the code which is in the screenshot below. Figure 10 Generated code for ARDUINO_A4_PIN Write methods for reading/writing bytes to the 1-wire bus. Figure 11 Methods for reading/writing bytes Write methods to request the temperature conversion and read the temperature, see dsRequestConvertTemp() and dsReadTemp(). Finally, use the methods in main().   Build the project and start debugging. Figure 12 Output from the application
View full article
The MCUXpresso Config Tools is installed without the data for MCUs and boards, and the data are download on demand via internet. So this article describes how to use MCUXpresso Config Tools with offline Computer. There are two methods: - Copy and paste the data on computer; - Connect the internet when first using. About the detail steps, please have a look at attachment . Thanks for the suggestion from Petr Hradsky . Alice Yang
View full article
Creating expansion board definition file for Arduino Multifunction shield  An expansion board definition file for the Arduino Multifunction shield can be applied in Pins Tool to expansion headers available on the NXP board. This tutorial describes the steps of creating an XML expansion board file using the shield documentation and the expansion headers feature in the Pins tool. For details on the expansion headers feature, see the following article: Adding Expansion Headers to a custom board You can apply the Arduino Multifunction shield on several NXP boards. This tutorial uses the FRDM K64F EVK board.   Prerequisites: Use a  shield description/specification, for example, https://www.biomaker.org/multifunction-shields. You can use HAILANGNIAO Multi-Function shield V2. Use the XSD schema file https://mcuxpresso.nxp.com/XSD/expansion_board_1.0.xsd for the definition file validation. Use the definition of signal types - mapping of signals from the expansion board to the processor. You can find it in the Config Tools data directory: c:\ProgramData\NXP\mcu_data_{config_tools_version}\expansion_headers\signal_types\common_signal_types.xml. Use the definition of expansion header where the board can be applied: c:\ProgramData\NXP\mcu_data_{config_tools_version}\expansion_headers\frdm_arduino.xml. Get familiarized with devices that are on the shield or can be connected to the shield. Install MCUXpresso IDE v11.3.0 or later and SDK FRDM-K64F 2.8.2 or later. Create a Project for FRDM-K64F. Open Expansion Header view (Windows -> Show View -> Expansion Header). Figure 1 FRDM K64F EVK board Figure 2 Expansion Header view in the Pins tool Expansion board template  Edit the following template according to the steps below. <?xml version="1.0" encoding= "UTF-8" ?> <expansion_board id="board_id" name="board_name" xsi:schemaLocation="http://mcuxpresso.nxp.com/XSD/expansion_board_1.0 http://mcuxpresso.nxp.com/XSD/expansion_board_1.0.xsd" xmlns="http://mcuxpresso.nxp.com/XSD/expansion_board_1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <header_connection ref="expansion_header_def_id"> <connectors> <connector ref="C1"> <pins> <pin ref="1" name="pin name" signal_type="digital_in" description="pin description"/> </pins> </connector> </connectors> </header_connection> <code_identifiers prefix="ARDUINO_"/> </expansion_board> Expansion board id and name  Edit the id and name of the expansion board. <?xml version="1.0" encoding= "UTF-8" ?> <expansion_board id="arduino_multifunction_ds18b20_board" name="Arduino Multi DS18B20 board" xsi:schemaLocation="http://mcuxpresso.nxp.com/XSD/expansion_board_1.0 http://mcuxpresso.nxp.com/XSD/expansion_board_1.0.xsd" xmlns="http://mcuxpresso.nxp.com/XSD/expansion_board_1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> Expansion board - header connection The element header_connection determines the id of an expansion header where the board can be applied to. Get the type of expansion header in the FRDM-K64F board. Figure 3 Edit expansion header dialog Edit the header_connection in the expansion board XML. <?xml version="1.0" encoding= "UTF-8" ?> <expansion_board id="arduino_multifunction_ds18b20_board" name="Arduino Multi DS18B20 board" xsi:schemaLocation="http://mcuxpresso.nxp.com/XSD/expansion_board_1.0 http://mcuxpresso.nxp.com/XSD/expansion_board_1.0.xsd" xmlns="http://mcuxpresso.nxp.com/XSD/expansion_board_1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <header_connection ref="frdm_arduino">​ NOTE Some other NXP boards can provide a  single row Arduino expansion header, for example, MIMXRT1060-EVK. For these boards,  create the definition file based on the single_row_arduino expansion header. The definition file varies only in pin references. Expansion board pins The tutorial describes how to add a pin element within the connector elements in three examples. See the marked pins on the shield below. Figure 4 Arduino Multi-Function shield Pin 5V (Power supply +5V) Get the needed pin element attributes values Find the board pin in the expansion header view. The pin tooltip shows connector J3 pin 10. The connector tooltip shows the definition id for J3, which is C1. Figure 5 Connector pin and connector tooltips in the Expansion header view Pin 5V is an external pin from the processor point of view (not connected to the processor). In the common_signal_types.xml, find a suitable signal type. Add the element pin with reference 10, name on the shield 5V, signal type power_supply_5V, and the description in the connector C1. <connector ref="C1"> <pins> <pin ref="10" name="5V" signal_type="power_supply_5V" description="Power supply +5V"/>​ Pin 13 (LED - D1) Get the needed pin element attributes values Find the board pin in the expansion header view. The pin tooltip shows connector J2 pin 12. The connector tooltip shows the definition id for J2, which is C2. Figure 6 Connector pin and connector tooltips in the Expansion header view Pin 13 is connected to LED D1 on the shield. It is digital input from the shield point of view, it is output from the processor point of view. In the common_signal_types.xml, find a suitable signal type. Add the element pin with reference 12, name on the shield 13, signal type digital_in, and the description in the connector C2. <connector ref="C2"> <pins> <pin ref="12" name="13" signal_type="digital_in" description="LED - D1"/>​ Pin A4 (Thermometer DS18B20 or LM35 - U5) Pin A4 is connected to the header U5 on the shield where two different external thermometers can be applied. The definition file you create is the variant for DS18B20. See the documentation for DS18B20: https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf  Get the needed pin element attributes values Find the board pin in the expansion header view. The pin tooltip shows connector J4 pin 10. The connector tooltip shows the definition id for J4, which is C4. Figure 7 Connector pin and connector tooltips in the Expansion header view Pin A4 is connected to DS18B20 DQ pin which is Data Input/Output. In the common_signal_types.xml, find a suitable signal type.   Add the element pin with reference 10, name on the shield A4, signal type digital, and the description in the connector C4. <connector ref="C4"> <pins> <pin ref="10" name="A4" signal_type="digital" description="Thermometer DS18B20 or LM35 - U5"/>​   See the complete expansion board definition file arduino_multifunction_ds18b20.xml and arduino_single_multifunction_ds18b20.xml in the CreateExpansionBoardFile.zip. For information on the usage of this created board file see the following article: Measuring temperature using digital sensor DS18B20 and Arduino Multifunction Shield on FRDM K64F
View full article
The MCUXpresso Config Tools is an integrated suite of configuration tools that help guide users from first evaluation to production software development when designing with Arm ® Cortex ® -M-based devices from NXP, including its general purpose, crossover and wireless-enabled MCUs. These configuration tools allow developers to quickly build a custom SDK and leverage pins, clocks and peripherals to generate initialization C code for custom board support. The following tutorials help you design with the MCUXpresso software and tools. Pins Tool and Expansion Headers Apply Arduino virtual adapter into compatible header Measuring temperature using digital sensor DS18B20 and Arduino Multifunction Shield on FRDM K64F Creating expansion board definition file for Arduino Multifunction shield Adding Expansion Headers to a custom board Peripherals tool USB Audio Class Tutorial  Using TDA1543 I2S DAC with the LPC54114 board  Touch controlled led light on LPCXPRESSO845-BRK  eDMA component abilities shown on ADC measurement example Trusted Execution Environment (TEE) Getting started with TEE  Creating Secure and Non-Secure projects Calling Secure code from Non-Secure region LPC55Sxx: Securing Digital IO Pins
View full article
This paper describes using a simple audio DAC (Digital to Analog Converter) with the LPC54114 board. As the processor offers hardware I2S interface, TDA1543, a widely available low-cost 16-bit I2S DAC, is used. This tutorial describes the steps of connecting it and preparing a code for using TDA1543 in your application with leveraging MCUXpresso tools and SDK. Prerequisites MCUXpresso IDE 11.3 MCUXpresso SDK for LPCXpresso54114 version 2.9.x (use https://mcuxpresso.nxp.com) For testing on hardware: LPCXpresso54114 board, TDA1543, and related parts (see below) Hardware TDA1543 is a 16-bit DAC with stereo output. It is available in an 8-pin DIP package with 3 digital input signals. It can operate with a minimum of external parts. The following diagram shows a simple testing circuit used for this project to get an analog audio line output. This schematic can be easily wired using a breadboard. Figure 1. Schematic of an elementary audio output DAC using TDA1543 Connection and pin configuration The DAC uses the standard I2S interface which is a serial bus that consists of 3 signals: Clocks (in the nomenclature of our MCU it is the SCK signal), WS (Word select – indicating left or right channel), and DATA (serial data synchronized by the clock signal). MCUXpresso Config Tools provide the Pins tool that can be leveraged for finding appropriate pins for the connection and routing them. Steps: 1. Create a project for the LPCXpresso54114 board. If you need, you can find detailed instructions in this video. (https://www.nxp.com/design/training/basic-application-development-using-mcuxpresso-ide-and-mcuxpresso-config-tools:TIP-BASIC-APP-DEV-MCUXPRESSO-IDE-TOOLS) Hint: Ensure you select the appropriate board:  2. Open the Pins tool. You can use the tools' Menu button in the Project panel:          NOTE: Ensure you have selected the appropriate project when multiple projects are in the workspace. 3. Open the Peripheral signals view and unfold Flexcom7          NOTE: LPC 54114 MCU provides 8 instances of the Flexcomm communication peripheral that can be flexibly set for UART, SPI, I2C, but only Flexcomm6 and Flexcomm7 provide I2S interface. This tutorial uses Flexcomm7.          NOTE: I2S signals are marked red. FlexComm5 (and lower) do not offer I2S signals. 4. Check the RXD_SDA_MOSI_DATA pin. In the dialog for routing, select which pin you would like to route the signal to. This tutorial uses pin 27 Tip: Find which expansion header connector and pin the processor pin is connected to in the tooltip of each pin:   5. Repeat steps 3 and 4 for SCK and WS signals. SCK – pin 26 (connected to J1[14])  WS – pin 28 (connected to J1[12] and J9[6]) 6. In the Routing details view, set the mode of all signals to Inactive (it disables internal pull-up). Configuring I 2 S in the Peripherals tool Using the Peripherals tool, generate the initialization code for the Flexcomm I 2 S SDK driver that is used for communication with TDA1543. Steps 7. In the Peripherals tool, open the Peripherals view and check Flexcomm7 8. Select the I 2 S configuration component (category Peripheral driver). 9. The Problems view shows an error.  The FLEXCOMM driver is not present in the project. Right-click the error and select the action Add SDK component "FLEXCOMM Driver" into the project In the shown SDK Component Management dialog box, confirm the addition of the files by clicking the Yes button. 10. In the added configuration component, set up the following items: The Custom name checkbox is checked,  the Name: ‘CODEC’ Mode: Transfer (Note: Transfer mode is easy to use and provides asynchronous operation) Sample rate: 24000 Hz Transfer Configuration / Transfer functions setting / Buffer size in bytes: 32           11. The Bit clock source frequency shows an error as the clocks of Flexcom7 are not enabled (inactive).           Right-click the “bulb” icon offering possible fixes for the problem. Select the error message FXCOM7 clock is inactive and select the action Show problem in BOARD_BootClockHSRUN, which is the name of the functional group in the Clocks tool. It opens the Clocks tool and highlights the FXCOMCLK7 clock output related to                             Flexcomm7:     Configuring clocks For correct communication, enable and configure clocks for the Flexcomm7 interface. Steps 12. In the Path Details view (for FXCOM7 clock), set the FXCOM7 clock select to FRG clock, the output of…             NOTE: FRG is a Fractional Rate Generator allowing to provide non-integer ratios for clock frequencies. 13. Set the FRG clock select to FRO 12.               The clock path and frequencies are automatically updated. 14. Switch back to the Peripherals tool using the icon in the toolbar.   15. The bit clock source frequency is now 12000000 Hz and it shows a warning because it does not match a value suitable for producing the required bit clock. The nearest bit clock source frequencies show potential suitable values. Copy the first one            (11520000) to the clipboard and switch back to the Clocks tool. 16. Paste the value into the FXCOM7 clock value column and add ‘Hz’ units; otherwise, it is treated as currently used MHz.    17. An error is reported. The Clocks tool cannot satisfy the requirement, so change the accuracy to a higher value. Set it to 0.5 (which corresponds to 0.5 %): Now the requirement is satisfied (producing 11.54 instead of 11.52 MHz): Code 18. Update the generated code into the project by using the Update Code button.  Confirm the update by clicking OK in the shown dialog. 19. Add the code into the main module (stored in the Sources folder of the MCUXpresso IDE project): /* TODO: insert other definitions and declarations here. */ #define BUF_SIZE 32 // Example wave data for transfer, odd numbers are left channel, even numbers are right channel const uint16_t wave[32] = {                      0,2000,4000,6000,8000,10000,12000,14000,                      16000,18000,20000,22000,24000,26000,28000,30000, }; // I2S callback function volatile void CodecTx(I2S_Type *base, i2s_handle_t *handle, status_t completionStatus, void *userData) {     /* Enqueue the same original s_Buffer all over again */     //i2s_transfer_t *transfer = (i2s_transfer_t *)userData;     I2S_TxTransferNonBlocking(base, handle, CODEC_Tx_Transfer); } Add the following code after the existing hello world PRINTF:         PRINTF("Hello World\n");         // prepare data into the buffer         memcpy(CODEC_Tx_Buffer, wave, 32);        // Start transfer        I2S_TxTransferNonBlocking(CODEC_PERIPHERAL, &CODEC_Tx_handle, CODEC_Tx_Transfer); Testing on hardware You can test the application on the LPC54114 evaluation board with a connected DAC chip. Figure 2. DAC circuit wired with the evaluation board The output checked using the sound-card input of a PC has the following result. It corresponds to the expectations: Figure 3. Waveform measured at the output of the circuit  
View full article
  The Expansion headers feature in MCUXpresso Config Tools simplifies the usage of the Pins tool in several ways. It is easier to find appropriate pins on the board and configure them for usage in a user application. The pins can also be automatically routed by applying the expansion board file. This document describes how to add or modify the expansion headers if you are designing or using your own PCB board leveraging standard expansion headers such as those compatible with Arduino.  1. Introduction   1.1 Expansion header   An expansion header is a collection of expansion connectors placed on the development board. The pins from the connectors lead out the processor pins outside and can be identified by a label on the board. There can be multiple expansion headers on a single board.   Figure 1. Example of three expansion headers on- LPC55S69-EVK board  1.2 Expansion board   An expansion board is a circuit board that can be applied to the Expansion header, extending features of the development board. Expansion boards (sometimes called Shields) can contain special additional components such as wireless modules, sensors, and so on. The connected pins may have different names on the expansion board.    If an expansion header is defined in the configuration, then the pins tool can provide instant routing of the processor signals appropriate for the expansion board applied to this header.   Figure 2. Expansion board example - Tester click[https://www.mikroe.com/tester-click]  1.3 Expansion Headers in Pins tool  The Expansion Header view can be found in the Pins tool. The view shows the header connectors and pins in graphical form, with the layout corresponding to the layout of the real board. Figure 3. Expansion Header view  The Expansion Header view can simplify work with the pins connected to an expansion header. By moving the cursor on a connector pin, you can see the details on the pin's connection and routing. You can also route processor pins signals by left-clicking on the connector pin or by right-clicking to invoke the context menu.  The default new configurations created by MCUXpresso config tools for common evaluation boards already contain pre-populated expansion header(s) matching the expansion headers on the board that can be used out-of-box.  2. Adding Custom Expansion header   When the expansion header is not present in the configuration, or you would like to add an additional expansion header.  Open or create the configuration where you would like to add an expansion header in the Pins tool. Open the Expansion Header view if it is not open. In the standalone MCUXpresso Config tools, select the command Views > Expansion header  In the MCUXpressso IDE, select command Window > Show view > Expansion Header  Click the Add button in the Expansion Header view toolbar.      Figure 4. expansion header Add button  The Expansion Header dialog appears Set the header name, type, and connector names to match your hardware design.        Figure 5.  Add New Expansion Header dialog           NOTE: The number of connectors and arrangement is determined by the header type.      Figure 6. Example of the header types (orange: Lpc-style arduino; red: Pmod; green: Micro Bus) The values can be changed in the future in Edit Header   The created header initially contains only the disconnected pin that must be defined before it can be used in the configuration. For more information, see subchapter Connecting pins.  Note: The customized headers and their connections are saved to the configuration MEX file and in the YAML block within the generated source files, so they are not lost when you distribute the configuration to someone else.   Figure 7. Custom header in the source code   2.1 Connecting pins  The newly created custom expansion header does not contain any connected pins.    There are two ways to connect or disconnect a pin:   Dialog in the Expansion Header view Click the Connect command in the context menu of the connector pin.     Figure 8. Connect command in the context menu The Connector Pin dialog is shown   Figure 9. Connect dialog for the 3-d pin on connector “mA”, set name “mPin” and connected to processor pin on coordinates 26  You can set the name (for example, the label of the pin on the header); otherwise, the connector pin coordinates will be used instead.  If the pin is connected to the processor, check the checkbox connected with the processor pin. In this case, check the connected pin checkbox from the list. If the connector pin is used but is not connected to the processor, you can select external signal types, which will be used for validating features of the matching signals when the expansion board is applied to the header. You can also disconnect the pin by unchecking all the checked items.  It is also possible to connect Connector pins via the Pins view, see below.   3. Connections in the Pins view   The connections of each expansion header/board are also shown as a separate column in the Pins view.    The fields at processor pin rows that are filled contain a reference to the connector, the pin number and may contain a label specific for the expansion header. For example, P19[4] (A1) connects the processor pin to connector P19, pin number 4, and the label on the expansion header is A1.     Figure 10. Expansion headers/boards in the Pins view   Steps to connect connector pins in this view:  Find the cell, where the row is the processor pin you would like to connect, and the column is the expansion header to connect to.  The connection is made by setting cell value in the connector pin coordinates format “connector name”[“number of the pin”]. If you want to add an optional name, you append the name in parentheses.  Note: The external signal types of the connector pin cannot be set here.  The value is checked for the correct format, which  is described within the tooltip shown for the cell    Figure 11. Validation tooltip with advice for the header "My custom header"  Disconnecting can be done by deleting the cell value    3.1. Applying/Removing expansion board   If you have an expansion board definition file, you can apply it to the selected expansion header. After the application, the pins tool suggests routing for all used signals and it is possible to see the usage and corresponding board signals for the expansion board.   The expansion board is distributed as a simple .xml file. The type of expansion header must match the expansion header definition, other headers cannot be used. For details on the expansion board definition file, see the following article: Creating expansion board definition file for Arduino Multifunction shield To apply an expansion board, use the following steps:  In the expansion header view, select the plus button in the right part of the Expansion Header view toolbar.  Figure 12. Expansion board add button    You can also use the path Main menu Pins > Apply expansion board, where you can choose the expansion header.      Figure 13. Apply MikroE Tester click board for a micro bus header type  After clicking OK, the Expansion Board Routing dialog appears   Figure 14. Expansion board routing open after applying the expansion board  In the dialog box, you can choose which pins function group the routing will be applied to. The routing dialog contains routing tables, where processor pins are pre-autorouted based on the limitations of the expansion board. The routing is validated in real time and can be changed by clicking a cell in the Route column.   You can also decide if and what pin name will be used for the generation of the defined constants in the code for referencing from the application.    Figure 15. Generated #define for board MIKROE and pins AN, CS  The same dialog appears after clicking the edit expansion board in the Expansion header view, but the option to create a new functional group will not be enabled.  Figure 16 Expansion board edit button   NOTE: Removing expansion board does not remove configured routing. It only changes the identifier defines if they are derived from the board.   Figure 17. Source code change after removing  the expansion board      
View full article
1. Introduction  This tutorial contains the following goals: 1) How to use the main features of the eDMA component 2.4.0 (periodic trigger, peripheral request, linking, scatter-gather) in the Peripherals Configuration Tool. 2) How to set up periodic ADC autonomous (without CPU) queued measurement controlled by DMA. 2. Prerequisites  The application is developed in MCUXpresso IDE 11.5.0 which can be downloaded from https://www.nxp.com/mcuxpresso/ide website. It integrates MCUXpresso Config Tools Version 11 that is used for application design and configuration. The FRDM-K66F - Freedom Development Platform for Kinetis K66 SDK  version 2.11.0 can be downloaded from the https://mcuxpresso.nxp.com/ website or using the MCUXpresso IDE. 3. Application description  3.1. Description  The main goal of this application is to show the configuration of the DMA peripheral which can be used for the ADC channel to be measured and for collecting the results into the resulting output array. It demonstrates an approach for periodic measurement of multiple ADC channels without CPU intervention. It can be used on any MCU with a simple ADC peripheral (without a possibility to queue measured channels). 3.2. Application details  The application starts with the initialization of pins, clocks, and peripherals configured by the MCUXpresso Config Tool. After the initial state is printed to the console, it starts the PIT (periodic interrupt timer). The PIT channel named Trigger causes periodic transfer on the DMA channel named ADC, which configures the ADC peripheral’s channel to be measured. When the timer counting is completed, the ADC measures the analog signal of the DAC peripheral that has been already initialized. The interrupt routine of the PIT Trigger channel includes the actual DAC data reading sequence that will be printed at the end of the console. After the end of the measurement loop, there is the ADC peripheral’s DMA request which initiates the DMA channel named OUTPUT to read the measured ADC data. The DMA channel OUTPUT links the DMA channel named DAC, which increases the buffer read index of the DAC peripheral and generates the next analog signal to be measured by the ADC. The sample number corresponds to the number of major loops of the DMA channel OUTPUT. The major count completion interrupt of the DMA channel OUTPUT stops the measurement trigger (PIT) and enables the DMA request of the DMA channel named PROCESS. The DMA channel PROCESS processes the whole dataset by sorting it into individual data buffers using the scatter-gather function. The major count completion interrupt of the DMA channel PROCESS sets the flag for printing the results and starts the delay timer (PIT second channel named Delay) that delays individual measurements. The post-delay interrupt routine stops the PIT Delay channel and restarts the PIT Trigger channel, which initiates the whole cycle again. Figure 1. Application diagram  4. MCUXpresso Config Tool configuration  The project includes the initial configuration of the following peripherals by the Peripherals Tool: DAC (Digital to Analog Converter) ADC (Analog to Digital Converter) PIT (Periodic Interrupt Timer) eDMA (Enhanced Direct Memory Access) 4.1. DAC peripheral  The DAC peripheral is used for creating simulated data to be measured by the ADC. DAC peripheral setup: Mode – Buffered DAC reference voltage – DACREF_2 – the same voltage reference as for ADC, so that both peripherals are in the same voltage ranges. Enable DAC – true Enable DAC buffer - true Trigger mode – Software trigger (configured by DMA write to register C0, corresponds to the dac_trigger[] configuration) Work mode – Swing mode (demonstration choice) Data buffer values – 10 demonstrations of values from 100 to 1000 with step 100 Buffer read index - 0 The DAC buffer works in swing mode, so it moves the buffer read index from the first item to the last, then back to the first, and so on. After the one loop is measured by the ADC nearly the same values are printed out to the console log, due to the same voltage reference selected in both the DAC and the ADC. The DAC interrupt is not used. Figure 2. DAC Configuration  4.2. ADC peripheral  The ADC peripheral is used for measuring an analog signal (in this case, generated by the DAC peripheral) and converting it into a digital signal. ADC peripheral setup: Reference voltage source – VrefH/VrefL Input clock source – Bus clock divided by 2. Asynchronous clock output – false Divide input clock source – by 8 (to achieve better accuracy) Sample resolution mode – Single-end 12-bit (the same as DAC resolution) Perform auto-calibration – true (to achieve better accuracy) Use hardware trigger – false DMA requests – true The ADC channel selection is configured by the DMA. The adc_trigger[] array includes configurations of the SC1A register, which selects and triggers the ADC channel measurement. The clock frequency for the ADC measurement is set to 3.75 MHz. The conversion time is calculated in the following way: Conversion time = SFC adder + AverageNum * (BCT + LST adder + HSC adder) Where: SFC adder (Single or First Continuous time adder): 5 ADCK + 5 bus clock cycles AverageNum (Average Number factor): 8 BCT (Base Conversion Time: for 12-bit single-ended): 20 ADCK LST adder (Long Sample Time adder): 0 ADCK HSC adder (High-Speed Conversion time adder): 0 ADCK ADCK (ADC clock cycle period): (16/60000000) s The resulting conversion time is calculated as follows:  Conversion time = (5 ADCK + 5 bus clock cycles) + 8 * (20 ADCK + 0 ADCK + 0 ADCK) = 165 * 16/60000000 + 5/60000000 = 44.083 us Figure 3. ADC configuration  4.3. PIT peripheral  The PIT peripheral is used for setting time delays. PIT peripheral setup: Run PIT in debug mode – true (application is demonstrated in debug mode) Clock source frequency – 60 MHz PIT Channel 0 is configured to set the delay between each ADC measurement. It periodically triggers a DMA transfer of DMA channel 0 which writes to the ADC register SC1A. Setup PIT channel 0: Channel ID – Trigger (optional identifier) Channel number – 0 (corresponds to the DMA channel number) Channel period – 60 us (the period must be higher than the calculated ADC conversion time 44.083 us and DAC value stabilization) Interrupt – true Interrupt request – Enabled in the initialization Figure 4. PIT configuration channel 0 named Trigger PIT Channel 1 is configured to set a delay for printing results. It starts at the end of the measurement loop. PIT channel 1 setup: Channel ID – Delay (optional identifier) Channel number – 1 Channel period – 10 s (period of the whole measurement loop) Interrupt – true Interrupt request – Enabled in the initialization Figure 5. DMA channel OUTPUT TCD configuration 4.4. eDMA peripheral  The eDMA peripheral component initializes the DMA and DMAMUX (DMA request multiplexer) peripherals. The DMA controller enables moving data from one memory-mapped location to another without CPU involvement. Note: The error interrupt vector and channel error event for all DMA channels are enabled. It can improve the debugging process. The ISR is defined in the DMA_ERROR handler. eDMA peripheral setup: Priority arbitration mode – Round-robin (no specific channel priorities were set because channels are not used simultaneously) Debug mode enable – true (application is demonstrated in debug mode) Figure 6. General eDMA configuration overview The application example uses 4 DMA channels for control: ADC (always-on DMA request triggered by PIT) DAC (disabled DMA request) OUTPUT (ADC peripheral DMA request) PROCESS (always-on DMA request) All used DMA channels are configured as Non-transactional (TCD structures) channel API mode, which allows you to configure all TCD (Transfer Control Descriptor) registers. 4.4.1. Channel ADC The eDMA channel ADC (Figure 7) is used for setting and triggering the ADC channel to measure the analog signal generated by the DAC peripheral. It demonstrates the use-case of a triggered always-on DMA request when the selected DMA channel (0) is triggered by the corresponding PIT channel (0). The peripheral request is enabled; therefore, the channel operates immediately after the PIT trigger timer starts and completes counting. eDMA channel ADC setup: Channel API mode - Non-transactional (TCD structures) Channel ID – ADC (optional channel prefix name) eDMA channel number – 0 eDMA request – AlwaysOn (any always-on request number) Periodic trigger enable – true (requires initialization of PIT channel 0) Reset channel – true Peripheral request enable – true Figure 7. DMA channel ADC configuration The Transfer Control Descriptor for the DMA channel ADC (Figure 😎 is configured as memory-to-peripheral transfer, which configures the ADC peripheral for measurement. eDMA channel ADC TCD named ADC_trigger setup: TCD ID – ADC_trigger Source address configuration Data size [Byte] – 4 (one minor loop transfers 4 bytes, which corresponds with the destination register size) Address expression – &adc_trigger[0] (contains 2 configurations of the ADC0::SC1A register, for demonstration purposes both selected the same ADC channel 23 (0x17) interconnected with the DAC output. The configurations can be different) External definition – extern uint32_t adc_trigger[]; Offset expression – sizeof(adc_trigger[0]) (SOFF = 4 bytes) Modulo – Disable modulo Destination address configuration Data size [Byte] – 4 (one minor loop transfers 4 bytes, which corresponds to the destination register size) Address expression – ((uint32_t)(&ADC0_PERIPHERAL->SC1[0])) or (uint32_t)ADC0_PERIPHERAL (it is the first register of the peripheral ADC) Offset expression – 0 (DOFF = 0 bytes, destination address is always the same – ADC0::SC1A) Modulo – Disable modulo Minor loop configuration Minor loop transfer [Byte] – 4 Minor loop offset – Disabled Minor loop link enable – false Bandwidth control – No eDMA engine stalls Major loop configuration Major loop count – 2 (MAJOR_LOOP_COUNT – 2 ADC configurations) Source last address adjustment – -8 (SLAST = (-1) * SOFF * MAJOR_LOOP_COUNT) Destination last address adjustment – 0 (DLAST = (-1) * DOFF * MAJOR_LOOP_COUNT) Major loop link enable – false Auto stop request – false (channel operation is triggered by the hardware – PIT trigger) Scatter-gather configuration Scatter-gather enable – false Constant TCDs - true Initialize TCD - ADC_trigger Figure 8. DMA channel ADC TCD configuration 4.4.2. Channel DAC The DMA channel DAC (Figure 9) is used for setting and triggering the DAC peripheral to generate an analog signal for the ADC measurement. It demonstrates the DMA channel (1) configuration without using a DMA request. A channel without a DMA request can be enabled with a software trigger or with channel linking functionality. In this case, the DMA channel DAC is linked from the DMA channel OUTPUT.  Figure 9. DMA channel DAC configuration eDMA channel DAC setup: Channel API mode - Non-transactional (TCD structures) Channel ID – DAC (optional channel prefix name) eDMA channel number – 1 eDMA request – DMAMUX disable (without DMA request) Periodic trigger enable – false Reset channel – true Peripheral request enable – false The TCD for the DMA channel DAC (Figure 10) is configured as a memory-to-peripheral transfer, which configures the DAC peripheral for generating the next analog signal. eDMA channel DAC TCD named DAC_trigger setup: TCD ID – DAC_trigger Source address configuration Data size [Byte] – 1 (one minor loop transfers 1 byte, which corresponds to the destination register size) Address expression – &dac_trigger[0] (contains the configuration of the DAC0::C0 register (0xF0) that triggers DAC by software) External definition – extern uint8_t dac_trigger[]; Offset expression – size of(dac_trigger[0]) (SOFF = 1 bytes) Modulo – Disable modulo Destination address configuration Data size [Byte] – 1 (one minor loop transfers 1 byte which corresponds with the destination register size) Address expression – ((uint32_t)(&DAC0_PERIPHERAL->C0)) Offset expression – 0 (DOFF = 0 bytes, the destination address is always the same – DAC0::C0) Modulo – Disable modulo Minor loop configuration Minor loop transfer [Byte] – 1 Minor loop offset – Disabled Minor loop link enable – false Bandwidth control – No eDMA engine stalls Major loop configuration Major loop count – 2 (MAJOR_LOOP_COUNT – 2 ADC configurations) Source last address adjustment – -1 (SLAST = (-1) * SOFF * MAJOR_LOOP_COUNT) Destination last address adjustment - 0 (DLAST = (-1) * DOFF * MAJOR_LOOP_COUNT) Major loop link enable – false Auto stop request – false (DMA request disabled) Scatter-gather configuration Scatter-gather enable – false Constant TCDs - true Initialize TCD - DAC_trigger Note: Instead of the DAC peripheral the DMA channel can send or receive settings to/from any other peripherals that trigger the ADC measurement (for example, a communication peripheral - UART). Figure 10.  DMA channel DAC TCD configuration 4.4.3. Channel OUTPUT The DMA channel OUTPUT (Figure 11) is used for reading the ADC peripheral results and storing them in memory. It demonstrates the DMA channel (2) configuration using the DMA peripheral request (ADC). The peripheral request is enabled; therefore, the channel operates immediately after the ADC measurement is done. eDMA channel OUTPUT setup: Channel API mode - Non-transactional (TCD structures) Channel ID – OUTPUT (optional channel prefix name) eDMA channel – 2 eDMA request – ADC0 Enable periodic trigger – false Enable channel reset - true Enable peripheral request – true Asynchronous peripheral request – true Figure 11. DMA channel OUTPUT configuration The TCD for the DMA channel OUTPUT (Figure 12) is configured as a peripheral-to-memory transfer which reads the measured values by the ADC peripheral. eDMA channel OUTPUT TCD named ADC_RESULTS setup: TCD ID – ADC_RESULTS Source address configuration Data size [Byte] – 4 (one minor loop transfers 4 bytes which corresponds to the destination register size) Address expression – (uint32_t)(&ADC0_PERIPHERAL->R[0]) (reads results from ADC0::RA register) Offset expression – 0 (SOFF = 0 bytes, the source address is always the same) Modulo – Disable modulo Destination address configuration Data size [Byte] – 4 (one minor loop transfers 1 byte which corresponds to the destination register size) Address expression – &adc_results[0] External definition – extern uint32_t adc_results[]; Offset expression – sizeof(adc_results[0]) (DOFF = 4 bytes) Modulo – Disable modulo Minor loop configuration Minor loop transfer [Byte] – 4 Minor loop offset – Disabled Minor loop link enable – true Linked minor loop channel – 1(DAC) (every minor loop eDMA channel DAC is linked which triggers the DAC and increases the buffer index that changes the DAC output value) Bandwidth control – No eDMA engine stalls Major loop configuration Major loop count – 20 (MAJOR_LOOP_COUNT – 20 measured samples) Source last address adjustment – -0 (SLAST = (-1) * SOFF * MAJOR_LOOP_COUNT) Destination last address adjustment - -80 (DLAST = (-1) * DOFF * MAJOR_LOOP_COUNT) Major loop link enable – true Linked major loop channel – 1(DAC) (last minor loop increases the DAC buffer index for the next measurement cycle) Auto stop request – false Scatter-gather configuration Enable scatter-gather – false Interrupt configuration Interrupt sources – Major count completion (After the measurement cycle, the interrupt DMA_OUTPUT is invoked. The ISR clears the status flags of the DMA channel OUTPUT channel, stops the PIT trigger timer, and enables the peripheral request of the DMA channel PROCESS. This way, it initiates the next operation.) Constant TCDs - true Initialize TCD – ADC_RESULTS - Enable channel interrupt – true - Interrupt request – Enabled in initialization - Enable custom handler name - true - Interrupt handler name – DMA_OUTPUT Figure 12. DMA channel OUTPUT TCD configuration 4.4.4. Channel PROCESS The DMA channel PROCESS (Figure 13) is used for processing the results and storing them in memory. It demonstrates the DMA channel (3) configuration using a DMA always-on request. The peripheral request is disabled; therefore, the channel operates after the request is enabled by the software. In the example application, the DMA request is enabled in the interrupt routine of the DMA channel OUTPUT which is invoked after all major loops transfers are completed (measurement finished). After this DMA transfer, there are two arrays of results, one for each ADC configuration, see configuration array adc_trigger[]. eDMA channel PROCESS setup: Channel API mode - Non-transactional (TCD structures) Channel ID – PROCESS (optional channel prefix name) eDMA channel – 3 eDMA request – AlwaysOn (any always-on request number) Periodic trigger enable – false Reset channel – true Peripheral request enable – false Figure 13. DMA channel PROCESS configuration The DMA channel PROCESS contains pre-configured TCDs as memory-to-memory transfers that process the measured data using scatter-gather functionality. In the example application, the data from one source data-array adc_results[] is scattered into two destination data-arrays, data0[], and data1[]. The DMA channel ADC contains two ADC configurations to be measured. The values measured by the first ADC channel configuration are stored into the data0, and after that, the second ADC channel configuration data into the data1. eDMA channel TCD Data0 setup: TCD ID – Data0 Source address configuration Data size [Byte] – 4 (sample size) Address expression – &adc_results[0] (first sample) Offset expression – 2*sizeof(adc_results[0]) (SOFF = 8 bytes, read every second sample) Modulo – Disable modulo Destination address configuration Data size [Byte] – 4 Address expression – &data0[0] External definition – extern uint32_t data0[]; Offset expression – sizeof(data0[0]) (DOFF = 4 bytes) Modulo – Disable modulo Minor loop configuration Minor loop transfer [Byte] – 4 Minor loop offset – Disabled Minor loop link enable – false Bandwidth control – No eDMA engine stalls Major loop configuration Major loop counts – 10 (MAJOR_LOOP_COUNT – 10 samples) Source last address adjustment – -80 (SLAST = (-1) * SOFF * MAJOR_LOOP_COUNT) Destination last address adjustment – Disabled due to scatter-gather mode Major loop link enable – false Auto stop request – false (always-on request still enabled) Scatter-gather configuration Enable scatter-gather – true Scatter-gather TCD address – Data1 Setup eDMA channel TCD Data1: TCD ID – Data1 Source address configuration Data size [Byte] – 4 (sample size) Address expression – &adc_results[1] (second sample) Offset expression – 2*sizeof(adc_results[0]) (SOFF = 8 bytes, read every second sample) Modulo – Disable modulo Destination address configuration Data size [Byte] – 4 Address expression – &data1[0] External definition – extern uint32_t data1[]; Offset expression – sizeof(data1[0]) (DOFF = 4 bytes) Modulo – Disable modulo Minor loop configuration Minor loop transfer [Byte] – 4 Minor loop offset – Disabled Minor loop link enable – false Bandwidth control – No eDMA engine stalls Major loop configuration Major loop counts – 10 (MAJOR_LOOP_COUNT – 10 samples) Source last address adjustment – -80 (SLAST = (-1) * SOFF * MAJOR_LOOP_COUNT) Destination last address adjustment – Disabled due to scatter-gather mode Major loop link enable – false Auto stop request – true  (stops always-on request) Scatter-gather configuration Enable scatter-gather – true Scatter-gather TCD address – Data0 Interrupt configuration Interrupt sources – Major count completion (After the last major loop of the TCD Data1, the interrupt DMA_PROCESS is invoked. The ISR clears the status flags of the DMA channel PROCESS channel, sets the print flag, and starts the PIT delay timer. The results are printed in the console.) Constant TCDs - true Initialize TCD – Data0 Enable channel interrupt – true - Interrupt request – Enabled in initialization - Enable custom handler name - true - Interrupt handler name – DMA_DATA_PROCESSED Figure 14. DMA channel PROCESS TCD configuration Data0 Figure 15. DMA channel PROCESS TCD configuration Data1 5. Application design  Global variables and definitions: Definitions: • SAMPLE_COUNT - number of the measured values from one measurement loop – one swing through DAC buffer (10 values) to top and back => 2 * 10 • DATA_COUNT - number of the data in each separated output array • ADC_CONFIGURATIONS - number of values (channel settings) for ADC0_SC1A register • DAC_TRIGGER_CONFIGURATIONS - number of values (SW trigger) for DAC0_C0 register Main global variables: • dac_output - Result buffer with DAC output, the array of DAC values filled from the actual pointed buffer index – used for printing purposes/* Result buffer with ADC measurement output - interleaved channels measured data, one by one */ AT_NONCACHEABLE_SECTION_INIT(uint32_t adc_results[SAMPLE_COUNT]) = {0}; /* Process data buffers – output separated measured data from the two selected ADC channels into these two arrays */ AT_NONCACHEABLE_SECTION_INIT(uint32_t data0[DATA_COUNT]) = {0}; AT_NONCACHEABLE_SECTION_INIT(uint32_t data1[DATA_COUNT]) = {0}; /* ADC channel selection: twice channel 23 configuration – 0x17; here you can specify your own channels numbers when you transform the tutorial to real application */ AT_NONCACHEABLE_SECTION_INIT(uint32_t adc_trigger[ADC_CONFIGURATIONS]) = {0x17, 0x17}; /* Set DAC software trigger configuration – 0xF0 */ AT_NONCACHEABLE_SECTION_INIT(uint8_t dac_trigger[DAC_TRIGGER_CONFIGURATIONS]) = {0xF0}; Functions and interrupt handler's description: int main(void) { /* Initialization of MCU (pins, clocks and peripherals) */ . . . /* Start the DMA trigger */ PIT_StartTimer(PIT_PERIPHERAL, PIT_TRIGGER); /* Inside infinite loop */ if(printFlag){ printBuffers(); } } /* PIT0_IRQn interrupt handler */ void PIT_TRIGGER_IRQHANDLER(void) { /* After each ADC trigger */ /* Fill dac_output array by the actual value */ } /* PIT1_IRQn interrupt handler */ void PIT_DELAY_IRQHANDLER(void) { /* At the end of the measurement loop after printing out */ /* Stop delay timer */ PIT_StopTimer(PIT_PERIPHERAL, PIT_DELAY); /* Start triggering in the next measurement loop */ PIT_StartTimer(PIT_PERIPHERAL, PIT_TRIGGER); } /* DMA2_DMA18_IRQn interrupt handler */ void DMA_OUTPUT(void) { /* After all measurement results in actual loop is transferred by DMA to adc_results[] */ /* Stop DMA trigger */ PIT_StopTimer(PIT_PERIPHERAL, PIT_TRIGGER); /* Enable data process DMA channel request */ EDMA_EnableChannelRequest(DMA_DMA_BASEADDR, DMA_PROCESS_DMA_CHANNEL); } /* DMA3_DMA19_IRQn interrupt handler */ void DMA_DATA_PROCESSED(void) { /* After finishing separation DMA transfers from adc_results[] to the data0[] and data1[] */ /* Start delay next measurement and results printing */ PIT_StartTimer(PIT_PERIPHERAL, PIT_DELAY); } /* DMA_Error_IRQn interrupt handler */ void DMA_ERROR(void) { /* Just for sure */ } void printBuffers() { /* Printed out the DAC values with ADC measured values for comparison */ } 6. Conclusion The tutorial shows: 1) How to use the main abilities of the DMA component 2.4.0 (periodic trigger, peripheral request, linking, scatter-gather). 2) How to set up periodic ADC autonomous (without CPU) queued measurement controlled by DMA.        
View full article
This tutorial is how to start working with TEE
View full article
This article was written for MCUXpresso Config tools v12 and older. Newer MCUXpresso Config tools can map Arduino expansion boards into compatible expansion headers automatically, without the need for any virtual adapter and even with possibility to utilize all the spare pins!   This tutorial shows how to apply and use the appropriate Arduino virtual adapter file (virtual adapters are attached) to utilize Arduino compatibility across different expansion headers. Benefit Virtual adapter board files allow users of the Pins tool from the MCUXpresso Config tools suite to use the expansion board file intended for a standard Arduino expansion header with other NXP expansion headers that are compatible with the Arduino standard but not mechanically identical (for example, they use two rows of pins).   Arduino-compatible expansion headers Freedom Header (Kinetis FRDM boards) LPCXpresso V3 (LPC boards) LPCXpresso V3 Mirrored Normally, such expansion headers are treated as different in the Pins tool, but the virtual adapter file transforms the current board header into the standard Arduino header so the user can apply the expansion boards referencing the standard Arduino header. For details on the expansion board, see Creating expansion board definition file for Arduino Multifunction shield.   Step 1: Open the Expansion Header view   Open the Expansion Header view if it is not open. In the standalone MCUXpresso Config tools, select the command Views > Expansion header  In the MCUXpresso IDE, select the command Window > Show view > Expansion Header    Step 2: Apply the Arduino virtual adapter file   The application of the virtual adapter file is the same as the application of the expansion board definition file. Use the attached virtual adapter files. Press the “Apply expansion board” button Locate the virtual adapter file and confirm Select if you want to create the functional group (recommended) Choose which names you would like to use in your source code Apply the expansion board   Step 3: Switch to the newly created header   Choose the Arduino adapter header option and select the newly created “Arduino adapter” header. Using the “+” button, select and apply an expansion board intended for the standard single-row Arduino header, and it will be connected to appropriate pins automatically.    
View full article
Creating Secure and Non-Secure projects The LPC55S69 MCU series contains Arm TrustZone® and Trusted Execution Environment extension from NXP. It allows users to assign cores, memories, and peripherals to the Secure or the Non-Secure World and restrict access between them. Manufacturers can use it to secure critical functionality of a device. For example, the Secure code is provided on the device by the manufacturer and could not be modified by users. However, a user can create a Non-Secure application and download it to the device. A secure code can communicate over a channel which security cannot be exposed to the Non-Secure World. This example is shown in the tutorial. This tutorial demonstrates how to create Secure and Non-Secure projects and their basic configuration using MCUXpresso IDE and Config Tools. LPCXpresso55S69 Board is used for the demonstration of functionality. Project description Two projects, a Secure and a Non-Secure, are created. Both projects are used on a single core. USART is used for sending data and it is configured as a Secure peripheral. S1 (ISP) button is used for sending data from the Secure world. S2 (WAKEUP) button is used for sending data from the Non-Secure world, which is not allowed due to a security violation. Prerequisites MCUXpresso IDE 11.3.0 LPCXpresso55S69 SDK 2.9.0 LPCXpresso55S69 Board You are familiar with the security extension used on LPC55S69. You are familiar with MCUXpresso IDE and Config Tools – Getting started with TEE. Steps 1.  Create a Secure project Create a new project, select the security type (Secure), and set memory regions in New Project Wizard. You must do it as Secure and Non-Secure projects use different parts of memories. In addition, secure memories use aliases – the 28 th bit is set to 1.  To download the firmware to the secure flash, select the Secure flash driver „LPC55xx_S.cfx“. 2. Create a Non-Secure project Create a new project and set security and memories as follows. 3. Connect the projects It is not mandatory but it makes things easier. Reference the Secure project from the Non-Secure project. It makes importing memory regions into the TEE tool easier.  The current and the linked or linking projects are preselected in the import dialog. In the  Secure project set the Non-Secure project to be preprogrammed.  Both projects are automatically downloaded to the board prior to debugging the Secure project. 4. Disable generation of  a Secure gateway library This feature is not used in this tutorial, therefore it must be turned off to compile the project. Change it in project properties (right-click the project and select Properties). 5. Route Secure pins Open Pins tool. Route S1 pin to SECGPIO. For detecting button press, peripheral SPINT is used and it must be routed to the same pin. Flexcom, which is used as USART, is routed by default in a board configuration. Do not change anything there. 6. Setup Secure peripherals Flexcomm is used for USART communication. Open Peripherals tool. Add USART component in Peripherals tool. Use the default configuration. Problems related to clocks must be resolved in the Clocks tool by enabling peripheral clock. Right-click the problem in Problems view and select Show problem. It opens the Clocks tool and highlights the problematic clock path. Add PINT component. Uncheck the checkbox „Show only components in toolchain project“  as the PINT driver is not in the project yet. Otherwise, it is not listed in the dialog. Select SECPINT peripheral. Configure it to invoke a callback function upon falling edge is detected on S1. Add the  PINT driver to the project via quick-fix in the Problems view. 7. Setup security extension in TEE tool Import memory regions from both projects in the User Memory Regions tab. As nothing is configured for the security extension, there are errors and warnings in the Security Level column. In Security Access Configuration, Miscellaneous tab enable Secure check for AHB matrix and Non-Secure access to floating point extension (CP10 access). FPU is turned on by default. Enable SAU and set Non-Secure regions. Other memory is considered Secure. Set MPC to allow only Secure transactions for Secure memory regions. It resolves errors and warnings in User Memory regions. Set SECGPIO and SECPINT peripherals as Secure. Keep Flexcomm as Non-Secure for now for demonstration purposes. Set PINT interrupt security as Non-Secure. Sending data from the Non-Secure world is also triggered by button press so its interrupt security must be set accordingly. It is the last setting of the Secure project in Config Tools, at this stage update the code. 8. Update Secure project settings After updating the code, create a  TrustZone folder. By default, new folders are excluded from the build. Right-click the folder and uncheck Exclude resource from build in the folder properties. Add the path to the folder into Include paths in project settings. 9. Add missing drivers If you use this version of tools,  add the inputmux driver in the Secure project. It is required for code generated by the Pins tool. 10. Update the Secure source code Do the following updates in source/Secure.c file. Add TEE initialization function call. As security is the first thing that should be configured,  place it SystemInitHook function. This way it is called before entering the main function. The initialization function is implemented in resource_config.h which must be included.       /*! * @brief Application-specific implementation of the SystemInitHook() * weak function. */ void SystemInitHook(void) { BOARD_InitTEE(); }       Implement SECPINT callback function. After pressing S1,  some data is sent from the Secure world via USART. For simplicity, character ‚s‘ is sent from the Secure world and character ‚n‘  is sent from the Non-Secure world.       /* * @brief Send on byte over secure channel * @param data data to be sent */ void sendSecureByte(uint8_t data) { USART_WriteByte(FLEXCOMM0_PERIPHERAL, data); } /* * @brief S1 button interrupt callback * @param pintr pin interrupt type * @param pmatch_status match status */ void secureButtonCallback(pint_pin_int_t pintr ,uint32_t pmatch_status) { sendSecureByte('s'); }       When you do the initialization in the Secure world, the MCU can continue with executing instructions from the Non-Secure world. The switching consists of setting a Non-Secure stack, a vector table, and calling a reset handler. The Non-Secure flash was previously configured to start at address 0x10000.       /* Start address of Non-secure application */ #define NON_SECURE_START 0x10000 /* typedef for non-secure callback functions */ typedef void (*funcptr_ns)(void) __attribute__((cmse_nonsecure_call)); int main(void) { /* Init board hardware. */ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitBootPeripherals(); #ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL /* Init FSL debug console. */ BOARD_InitDebugConsole(); #endif PRINTF("Secure World\n"); /* Set non-secure main stack (MSP_NS) */ __TZ_set_MSP_NS(*((uint32_t *)(NON_SECURE_START))); /* Set non-secure vector table */ SCB_NS->VTOR = NON_SECURE_START; /* Get non-secure reset handler */ funcptr_ns ResetHandler_ns; ResetHandler_ns = (funcptr_ns)(*((uint32_t *)((NON_SECURE_START) + 4U))); /* Jump to normal world */ ResetHandler_ns(); /* Force the counter to be placed into memory. */ volatile static int i = 0 ; /* Enter an infinite loop, just incrementing a counter. */ while(1) { i++ ; /* 'Dummy' NOP to allow source level single stepping of tight while() loop */ __asm volatile ("nop"); } return 0 ; }       11. Route Non-Secure pins Configure the Non-Secure project properly. Route S2 pin to GPIO as input. Route  PINT for pin #64. Flexcomm is routed by default, remove this routing as it is already routed in the Secure project. 12. Setup Non-Secure peripherals Set up PINT to use callback on falling edge of the S2 button press.  Add the driver, for example, via quick fix. 13. Update the Non-Secure source code Keep the initialization of Pins and Peripherals and remove the other initialization as it was done in the Secure world. That also includes the overriding SystemInit function.       /* * @brief System initialization * * Intentionally empty. Required initialization was done in the Secure project. * */ void SystemInit(void) { } /* * @brief Application entry point. */ int main(void) { /* Init board hardware. */ BOARD_InitBootPins(); BOARD_InitBootPeripherals(); ...       Add the code for sending data from the Non-Secure world. To use the USART_WriteByte function and the imputmux driver, include fsl_usart.h.       /* * @brief S2 button interrupt callback * @param pintr pin interrupt type * @param pmatch_status match status */ void nonSecureButtonCallback(pint_pin_int_t pintr ,uint32_t pmatch_status) { USART_WriteByte((USART_Type *)FLEXCOMM0, 'n'); }       Now the projects are ready. When debug is executed for the Secure project, the Non-Secure project is also downloaded to the board. After pressing S1, 's' is sent from the Secure world. When S2 is pressed, 'n' is sent from the Non-Secure world because Flexcomm is configured as Non-Secure in the TEE tool. 14. Securing USART Open the TEE tool from the Secure project and set the Flexcomm slave as Secure. After this change, you can send data from the Secure world but an attempt to send data from the Non-Secure world results in bus fault.  
View full article
This post will include a history of releases for the MCUXpresso Config Tools.    Most Recent Release: MCUXpresso Config Tools v11 - Released on January 17, 2022   Download Links: MCUXpresso IDE with integrated Config Tools Standalone MCUXpresso Config Tool   Standalone MCUXpresso Config Tool vs MCUXpresso IDE integrated version The functionality of the MCUXpresso Config Tools is integrated directly within the MCUXpresso IDE as tool perspectives (Pins, Clock, Peripheral, etc).  The configuration tools/perspective will provide a seamless way to configure and modify projects developed within MCUXpresso IDE.  The MCUXpresso Config Tools are also provided as a standalone installation for use with other IDEs (IAR and Keil).  Additionally these tools can be used without an IDE for generating configuration files and generated source file for use without an IDE.   Receive email notification for new releases: If you would like to receive email notifications when a new version of the MCUXpresso Config Tools is released, consider adding an "Email Watch" to this post.   Previous Release History: MCUXpresso Config Tools v10 - Released on July 15, 2021 MCUXpresso Config Tools v9 - Released on January 15, 2021 MCUXpresso Config Tools v8 - Released on July 21, 2020 MCUXpresso Config Tools v7 - Released on Dec 19, 2019  MCUXpresso Config Tools v6 - Released on June 13, 2019 MCUXpresso Config Tools v5 - Released on January 10, 2019
View full article
The following article describes how the data files of the Pins Tool can be downloaded either for offline usage or processed further, for example in an automated build system or how to use it on a machine without network connection: https://mcuoneclipse.com/2016/07/29/nxp-pins-tool-understanding-data-for-offline-usage/   I hope you find this useful, Erich
View full article
The following article has quick steps and videos how to get started with Kinetis Expert SDK and Design Studio:   https://community.freescale.com/docs/DOC-329662   Enjoy!
View full article
This community and forum is for the growing set of Kinetis Expert System Conguration Tools. The tools are acessible online on Welcome to Kinetis Expert | Kinetis Expert and include right now the 'Build an SDK' and 'Power Estimation' tools: So if you have any questions or need any further advice and information about the Kinetis Expert System Configuration Tools, this is the community for it!
View full article
  A Digital Rights Management (DRM) use case   In the Creating Secure and Non-Secure projects tutorial, you have attempted to access a Secure (S) FlexComm0 (USART) peripheral from a Non-Secure (NS) code and failed with the SecureFault exception. This was expected, as TrustZone® for ARM®v8-M protects Secure resources from Non-Secure access.   Now imagine a use case where the platform manages (protects) access to all its peripherals and firmware logic and requires all 3 rd party extensions, for example plugins or widgets, to be certified (approved) for use. The result of this approval process is some form of identification, a license key for instance, the untrusted code needs to supply to the trusted code to gain peripheral access and be able to communicate via USART. This kind of behavior can be achieved with the help of Non-Secure Callable (NSC) memory.   NSC is a type of Secure memory exclusively permitted to hold the Secure Gateway (SG) instruction that allows transition from NS to S state. When a Non-Secure program calls a function in the Secure side, the first instruction in the API must be an SG instruction. The Branch with exchange to Non-secure state (BXNS) will return execution to the Non-Secure side after the API call. While it’s possible for NSC memory to contain entire functions, its typical usage is holding tables of SG instructions with entry points, called veneers.   With GCC, ARMCC, ARMCLANG, IARCC, and LLVM compilers, you must specify the __attribute__((cmse_nonsecure_entry)) function attribute to declare an entry C/C++ function callable from NS state; SG and BXNS instructions are generated automatically. GNU linker puts the resulting code into the .gnu.sgstubs section aligned at 32 bytes.   With the solution outlined, you can reuse projects from the “TEE projects creation” tutorial to speed things up. To extend an existing project with NSC functions, the workflow is as follows: Secure state Configure project and  SAU/IDAU Implement NSC functions Generate NSC library Non-Secure state Configure project (import NSC library) Implement calls for Secure code     S project update   Start with the Secure project conveniently named “Secure”. Reserve some flash memory space for SG_veneer_table first. Navigate to Project > Properties > C/C ++ Build. Locate the MCU settings in SDK MCUs. Click Add Flash and add SG_veneer_table at 0x1000fe00, size 0x200 bytes. Click Apply.   To tell the MCU Linker to generate the NSC import library, navigate to Project > Properties > C/C ++ Build > Settings > MCU Linker > TrustZone. Select the Enable generation of Secure Gateway Import Library checkbox. Click Apply and Close.   Now setup the newly added flash memory region as NSC in the TEE tool. To switch to the TEE tool, click the Open MCUXpresso Configuration button in the Project Explorer, and select Open TEE.   The TEE tool is capable of importing project-wide memory regions from multiple projects at once. To import memory regions, click the Import button in the User Memory Regions view.   In the Select Project dialog, select both NonSecure and Secure projects and click OK.   Quick-fix the reported error Issue: SAU+IDAU: The following security requirements are not satisfied: NS_CALLABLE by right-clicking the cell and selecting the quick-fix from the context menu.   To save the changes, click Update Code.   MCUXpresso IDE v11.3.0 and earlier versions contain a bug that messes up linker script and puts SG veneers into PROGRAM_FLASH instead of SG_veneer_table when you’re modifying an existing project. To work around the problem, navigate To Project > Properties > C/C ++ Build > Settings > MCU Linker > Managed Linker Script. Deselect the Manage linker script checkbox and click Apply and Close.   Edit the script manually by opening the Debug/Secure_Debug.ld inside the IDE, find the .gnu.sgstubs section and direct it to SG_veneer_table instead of PROGRAM_FLASH.         NS project update   If you attempt to build the S project now, you’ll receive several linker errors telling you the NSC library could not be built as there are no NSC functions (yet) including the name of the said library: Secure_CMSE_lib.o. You’re going to use it to configure the Non-Secure project named “Non-Secure”. Navigate to Project > Properties > C/C ++ Build > Settings > MCU Linker > TrustZone. Click the Import button next to the Secure Gateway Import Library field, and select Workspace.   In the Input Secure Gateway Import Library dialog, select Secure_CMSE_lib.o and click OK.   You will see “${workspace_loc:/Secure/Debug/Secure_CMSE_lib.o}” in the Secure Gateway Import Library field of the MCU Linker Setting dialog.     NSC API   The source/Secure.c file already contains the sendSecureByte function implementation you need to make accessible through the NSC space. What’s missing is a few lines of code for its NSC equivalent and function prototype. Create source/nsc_api.h and source/nsc_api.c files in the Secure project workspace. The following code needs go into the newly created header file. #ifndef NSC_API_H_ #define NSC_API_H_ #include <stdint.h> void sendSecureByteNSC(uint8_t data); #endif /* NSC_API_H_ */ Add the following code into the source file. #include <arm_cmse.h> #include "fsl_debug_console.h" #include "nsc_api.h" #include "comm.h" void __attribute__((cmse_nonsecure_entry)) sendSecureByteNSC(uint8_t data) { if (cmse_nonsecure_caller()) { PRINTF("sendSecureByteNSC called from NS space\r\n"); } else { PRINTF("sendSecureByteNSC called from S space\r\n"); } sendSecureByte(data); } To rebuild the Secure project and generate the NSC import library click the Build ‘Debug’ for project ‘Secure’ button in the Toolbar.   Next in line is the Non-Secure project. The NSC library is already set to be imported. Copy Secure/source/nsc_api.h to the NonSecure/source folder. Call the sendSecureByteNSC function instead of USART_WriteByte from source/NonSecure.c. #include "nsc_api.h" …                   USART_WriteByte((USART_Type *)FLEXCOMM0, 'n'); sendSecureByteNSC('n'); Rebuild the Non-Secure project and debug both. Select the Secure project in the workspace and select Debug either from the Quickstart panel or the project context menu. Once the code is running, each press of the WAKEUP (S2) button on the LPCXpresso55S69 board will display the “sendSecureByteNSC called from NS space” message in the IDE console and send a single character via USART instead of failing with the SecureFault exception.    
View full article
Description This tutorial shows how to create a touch-controlled LED light strip to place it over the kitchen counter, for example. For this tutorial, the LED strip is abstracted by the onboard LED instead of using MOSFET (with a proper MOSFET driver circuit) that would control a higher voltage LED strip. The touch control must be encoded due to the presence of only a single touch pad for multiple actions. Used components LPCXpresso845-BRK breakout board SDK 2.8.0 for LPC845 MCUXpresso 11.3 Used peripherals CAPT Capacitive touch (CAPT) control allows you to place the button under the product cover for keeping the design of the product consistent. You can cover touch pads with dielectric materials and hide them inside the product. The CAPT peripheral in YH mode works by counting cycles until the charge is transferred from the small charging capacitor to the larger measuring one.  A human finger or capacitive stylus causes partial grounding of the charge that causes an increase or decrease of the cycles needed to fully charge the measuring capacitor. CTIMER A counter triggers a toggle of the output pin’s logic level that creates a PWM signal on that pin. The peripheral increases the counter with each peripheral clock cycle and when the counter matches the required number the output logic level is toggled. MRT A counter triggers interrupts after a defined number of peripheral clock cycles.  This peripheral can be programmed to create an interrupt repetitively or only after a specified number of cycles. Figure 1 Block diagram Touch control Description As mentioned previously, the board has only a single touch pad, and there are 3 different actions in this tutorial that must be controlled by it. Turn on/off the PWM output by tapping and removing the finger/stylus from the pad. Increase the PWM duty cycle by keeping the finger/stylus over the touch pad for a long time, keep touched for more increase. Decrease the PWM duty cycle by taping the touch pad, removing the finger, and taping again with keeping the finger/stylus over the touch pad, keep touched for more decrease. The touch pad is periodically measured for touch or no touch events. Such events can store the state of the touch pad in a ring buffer. The ring buffer represents the history of the touches over a short time and can be analyzed for a long uninterrupted touch or double tap. Figure 2 Encoding state diagram Steps IDE project Create a project and select the lpc845 breakout from your installed SDK version. Figure 3 Creating a project in MCUXpresso IDE In the project setup wizard, click the Drivers tab in the Components section in the lower half of the wizard. Select CAPT, CTIMER, and MRT in this table. Figure 4 Adding required peripheral drivers to the project To make active the newly created project (if it is not active yet), select it and open the Pins tool either in the context menu or by clicking the Config tools button. Figure 5 The Config tools button Pin routing Open the Pins tool and create a functional group for our application. Set it to be called by the default initialization function and set other functional groups not to be called by the initialization function. Figure 6  Properties of Pins tool functional groups Figure 7 Routing details Steps: Route CTIMER channel 0 to the pin that is connected to the onboard LED. Route X0 signal of CAPT to one side of the touch pad. Route signals YL and YH to the other side of the touch pad. Enable the invert function of the CTIMER channel 0 signal (see notes). Set the mode of all configured CAPT and CTIMER pins to Inactive (see notes). NOTE: The LED is connected to the MCU in a way that 90 % of the duty cycle would create only 10 % of the on-time.  To achieve the expected behavior, invert the signal. The CAPT peripheral requires the mode of the pins to be inactive to work properly. Activating a pull-up, pull-down resistor, or any other integrated circuit causes false measurements, and touch control does not work or causes false touch events. Clock configuration Open the functional group's dialog and select BOARD_BootClockFRO30M as the initialized functional group. Figure 8 Properties of Clocks tool functional groups Steps: Set SYSAHBCLKDIV to /3 Activate the output of CAPTCLKSEL and choose fro as the input clock Figure 9 System clock divider setting Figure 10 Selection of clock source for CAPT peripheral NOTE: The system clock is slowed down to 10 MHz because it is used for the MRT peripheral as a source and the period with 30 MHz is too short for the purposes of this tutorial. Peripheral configuration MRT This peripheral is used to delay the execution of events. Steps: Add the MRT component (use the version that is part of your SDK version). Add 1 channel. Set Channel ID to Channel_wait. Set Time interval input to 400 ms. Set Start timer to false by unchecking the checkbox. Enable Interrupt request of the channel by checking the checkbox. Enable Interrupt vector by checking the checkbox. Copy the handler template by clicking the button. Paste the handler template to the application code. Figure 11 Configuration of the MRT peripheral NOTE: For this application, the delay must be 400 ms. You can achieve it only by using a 10 MHz clock or by creating a counter in memory that is increased every time the interrupt handler is executed. Only when the counter has the required value, the delayed event executes, and the counter is reset. You need a counter because the MRT register, which has only 24 bits and overflows before reaching the number of ticks calculated from 400 ms. CTIMER For the PWM output, configure the CTIMER peripheral in the following way. Figure 12 Configuration of the CTIMER peripheral Steps: Add the CTIMER component (use the version that is part of your SDK version). Select the PWM mode of the CTIMER peripheral. Set the prescaler to 1 (see note for explanation). Check the checkbox Start timer in the initialization code if it is not checked already. Set the PWM frequency to 100 Hz (see note for explanation). Add 1 channel if it is not present already. Set the PWM duty of the channel to half of the value that is displayed below the PWM frequency setting notes: NOTE: The prescaler set to 1 (no prescaling) allows the most precise duty cycle (for example, if the resolution must be more than one percent).  The frequency of the output must be in the range between not noticing the flickering of the LED and potential unintentional overheating of the MOSFET that could be connected to the output due to high frequency. The frequency of 100 Hz is selected because unless the board is moving the LED looks dim and does not flicker, and the potential MOSFET does not overheat. The duty cycle is set in ticks, and at runtime is computed as a percentage. CAPT Steps: Create an instance of the CAPT component (use the version that is part of your SDK version). Set the Function clock divider setting to 15 to obtain a 2 MHz clock. Enable pin 0 by checking the checkbox in the X pins selection table. Select the value User calibration function (default name) in the setting Default function name. Copy the name and create the function in the application code. Select Counter higher than threshold could in the setting Touch activation. Set Time out count to the highest available value. Select Don’t wait for Measurement delay. Set Reset delay to the highest available value. Set Poll delay to 100 ms. Check the checkbox Initialize poll mode. Select Continuous in the setting Polling mode. Figure 13 Configuration of the CAPT peripheral NOTE: The CAPT peripheral requires the input clock to be maximally 4 MHz. Therefore, a frequency of 2 MHz was chosen as it was easily achievable and easy to calculate the resulting period. On the breakout board, only signal 0 is routed to the touch pad, and other signals can be routed to external connectors on the board. For the CAPT to function properly, calibrate touch and no touch events to obtain the number of cycles required to transfer the charge. Enable the usage of the calibration method and either use the default name or provide your name of the function. The other method is to use a constant that was measured during development. However, keep in mind that the measured value might differ when the board is inside the final product and covered by a layer of material. A touch event can happen either when the counter is higher or lower than the threshold. The selection depends on the final product design. A value higher than the threshold option was used in this tutorial because the finder/stylus grounds a part of the charge that is transferred and causes a higher cycles count required to fully charge the measured capacitor. The timeout count is a counter of the number of ticks when a timeout interrupt is created. It is not used in this example, so set the highest value to avoid timeout instead of touch or no touch events. The measurement delay setting represents the number of ticks until the measuring capacitor is sampled. When the YH method is used, it must be measured immediately. The reset delay is a wait after a touch or no touch event and waiting discharges the capacitors before the next measurement cycle. The poll delay is a delay between repetitive measurement cycles and should be high since the physical movement of the finger/stylus is slow relative to the speed of the MCU and unnecessary measurements can be avoided. Update code The changes you made must be written on the disk before using them in the application code. Open the Update code dialog and confirm the changes. Figure 14 Update code action on the main panel Figure 15 Update code dialog Application code For the convenience of working with the code, create the following defines: #define WAIT_MS 400U // How long to wait before making decisions #define POLL_WAIT_MS 100U // How long it takes before next CAPT measurement #define TOUCH_DATA_SIZE 32U // Size of ring buffer Create the ring buffer, index of the current position, and functions that fill and analyze it. The ring buffer must hold 2-3 seconds of data and since the poll delay of the CAPT is 100 ms then 32 is sufficient. Functions for analysis scan the ring buffer and let the application know whether a double tap was performed, for how many measurements the touch pad was held, and how many measurements ago the touch pad was touched. Create functions for storing and clearing data in the ring buffer. unsigned int g_touchDataIndex = 0; bool g_touchData[TOUCH_DATA_SIZE] = {false}; /**  * Checks whether double tap was performed  */ bool wasDoubleTap() {        bool untouched = false;        for (int i = 0; i < TOUCH_DATA_SIZE; i++) {               if (!g_touchData[(g_touchDataIndex - i) % TOUCH_DATA_SIZE]) {                      untouched = true;               } else if (untouched) {                      return true;               }        }        return false; } /**  * Returns number of data writes that represent continuous touch.  */ int getContinuousTouchCount() {        int count = 0;        for (int i = 0; i < TOUCH_DATA_SIZE; i++) {               if (g_touchData[(g_touchDataIndex - i) % TOUCH_DATA_SIZE]) {                      count++;               } else {                      return count;               }        }        return -1; } /**  * Returns number that represents count of data writes until tap is found in history.  * Returns -1 in case nothing is found.  */ int getPreviousTouch() {        for (int i = 0; i < TOUCH_DATA_SIZE; i++) {               if (g_touchData[(g_touchDataIndex - i) % TOUCH_DATA_SIZE]) {                      return i;               }        }        return -1; } /**  * Clears touch data in ring buffer  */ void clearTouchData() {        for (int i = 0; i < TOUCH_DATA_SIZE; i++) {               g_touchData[(g_touchDataIndex - i) % TOUCH_DATA_SIZE] = false;        } } /**  * Stores touch data in ring buffer  */ void storeTouchData(bool data) {        ++g_touchDataIndex;        g_touchDataIndex = g_touchDataIndex % TOUCH_DATA_SIZE;        g_touchData[g_touchDataIndex] = data; } Create storage for the current state of the PWM signal and the state machine. Create a function to change the PWM output of the CTIMER channel.  The function must check the wanted duty cycle to be in a reasonable range. int currentPWMDuty = 50; bool PWMOutputEnabled = true; enum STATE {        IDLE = 0,        WAITING_FOR_TIMER = 100,        TOGGLE = 200,        INCREASE = 300,        DECREASE = 400 }; enum STATE state = IDLE; /**  * Sets PWM output according to currently wanted duty cycle if output is enabled  */ void setPWMOutput() {        if (currentPWMDuty < 5) {               currentPWMDuty = 5;        }        if (currentPWMDuty > 100) {               currentPWMDuty = 100;        }        int ticks = PWMOutputEnabled ? ((CTIMER0_PWM_PERIOD / 100) * currentPWMDuty) : 0;        CTIMER_SetupPwmPeriod(CTIMER0_PERIPHERAL, CTIMER0_PWM_0_CHANNEL, CTIMER0_PWM_PERIOD, ticks, false); } Calibration of the CAPT peripheral must be done in the CAPT_doCalibration function as it was set in the Peripherals tool. /*  * @brief   Calibration of the CAPT peripheral. Returns number of charge cycles in not activated state  */ uint32_t CAPT_doCalibration(CAPT_Type *base) {        // Here can be placed code that uses one time polling multiple times and the results would be averaged        // or a constant returned        return 70; } When a 400 ms delay passes,  the MRT peripheral runs this interrupt and after clearing the status flag the logic follows. After obtaining information on whether the touch pad is touched and for how many measurement cycles it is not held, the decision of what state follows is made. When the touch pad is not touched and it is more than or equal to 4 (400 ms/100 ms) measurement cycles, the PWM output will be disabled. If it is touched, the decision whether the INCREASE or DECREASE state should follow is made. To increase the PWM duty cycle, the touch pad must be currently held touched, it must be held for more than or equal to 4 (400 ms/100 ms) measurement cycles and the PWM output must be enabled. To decrease the PWM duty cycle, the touch pad must be held,  double-tap (not holding for at least one measurement cycle) is done and output is enabled. In all other cases, the state falls back to IDLE since it is not a valid encoding of the command. /* MRT0_IRQn interrupt handler */ void MRT0_IRQHANDLER(void) {   /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F      Store immediate overlapping exception return operation might vector to incorrect interrupt. */   #if defined __CORTEX_M && (__CORTEX_M == 4U)     __DSB();   #endif        uint32_t mrtWaitStatus = MRT_GetStatusFlags(MRT0, MRT0_CHANNEL_WAIT);        MRT_ClearStatusFlags(MRT0, MRT0_CHANNEL_WAIT, mrtWaitStatus);     if (mrtWaitStatus != 0) {               int previousTouch = getPreviousTouch();               bool currentlyTouched = g_touchData[g_touchDataIndex];               if (!currentlyTouched && previousTouch >= (WAIT_MS / POLL_WAIT_MS) - 1) { // Tap, currently not pressed and no taps after the initial one                      PWMOutputEnabled = !PWMOutputEnabled;                      setPWMOutput();                      clearTouchData();                      state = IDLE;           } else if (currentlyTouched && getContinuousTouchCount() >= (WAIT_MS / POLL_WAIT_MS) && PWMOutputEnabled) { // Tap, currently pressed and touch pad held until now                      state = INCREASE;        } else if (currentlyTouched && wasDoubleTap() && PWMOutputEnabled) { // Tap, currently pressed and double tap was performed                           state = DECREASE;           } else {                           state = IDLE; // Error -> reset           }     } } The interrupt from CAPT is performed every 100 ms and the data with interrupt status must be read and status cleared. When the touch pad is touched, the current state is checked and one of the following actions happens: When the current state is IDLE, a 400 ms delay is started and the state changes to WAITING_FOR_TIMER. When the INCREASE state is active, the PWM duty cycle is increased every 100 ms for as long as the touch pad is touched. The DECREASE state decreases the PWM duty cycle every 100 ms for as long as the touch pad is touched. When the touch pad is not touched, the INCREASE or DECREASE state is changed to IDLE state and ring buffer is cleared. In other states nothing happens. /* CMP_CAPT_IRQn interrupt handler */ void CAPT_IRQHANDLER(void) {   /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F      Store immediate overlapping exception return operation might vector to incorrect interrupt. */   #if defined __CORTEX_M && (__CORTEX_M == 4U)     __DSB();   #endif     uint32_t mask;     capt_touch_data_t g_data;        CAPT_GetTouchData(CAPT, &g_data);        mask = CAPT_GetInterruptStatusFlags(CAPT);        CAPT_ClearInterruptStatusFlags(CAPT, mask);        if (mask & kCAPT_InterruptOfYesTouchEnable && g_data.yesTouch)        {               PRINTF("Touch\n");               storeTouchData(true);               switch(state) {                      case IDLE: {                            MRT_StartTimer(MRT0, MRT0_CHANNEL_WAIT, MRT0_CHANNEL_WAIT_TICKS);                            state = WAITING_FOR_TIMER;                            break;                      }                      case INCREASE: {                            currentPWMDuty += 5;                            setPWMOutput();                            break;                      }                      case DECREASE: {                            currentPWMDuty -= 5;                            setPWMOutput();                            break;                      }                      default: {                            // Do not react - unexpected state                      }               }        }        if (mask & kCAPT_InterruptOfNoTouchEnable) {               PRINTF("No touch\n");               storeTouchData(false);               switch(state) {                      case INCREASE: {                            state = IDLE;                            clearTouchData();                            break;                      }                      case DECREASE: {                            state = IDLE;                            clearTouchData();                            break;                      }                      default: {                            // Do not react - unexpected state                      }               }        } } /*  * @brief   Application entry point.  */ int main(void) {     /* Init board hardware. */     BOARD_InitBootPins();     BOARD_InitBootClocks();     BOARD_InitBootPeripherals(); #ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL     /* Init FSL debug console. */     BOARD_InitDebugConsole(); #endif     while(1) {           __asm__("nop");     }     return 0; } Summary Now you can compile the application and upload it to the board. You do not require additional steps to make the application work.
View full article