LPC Microcontrollers Knowledge Base

cancel
Showing results for 
Search instead for 
Did you mean: 

LPC Microcontrollers Knowledge Base

Discussions

INTRODUCTION The goal of this example is to demonstrate basic LIN communication between two devices where one active as Master another as Slave. In this case, the two devices used are LPC55S16 EVK's. LIN master will send a specific publisher frame and a subscriber frame, the LIN slave will detect the master data and feedback the data accordingly. This article will mainly focus on the software side, for hardware please refer https://community.nxp.com/t5/LPC-Microcontrollers-Knowledge/LPC54608-LIN-master-basic-usage-sharing/ta-p/1118103. LIN MASTER EXAMPLE LIN master sends the LIN publisher data and the subscriber ID data, the software code is modified from the SDK_2.8.2_LPCXpresso55S16 usart_interrupt_rb_transfer project, the detailed code is as follows: /* USART callback */ void FLEXCOMM3_IRQHandler() { if(DEMO_USART->STAT & USART_STAT_RXBRK_MASK) // detect LIN break { Lin_BKflag = 1; cnt = 0; state = RECV_DATA; DisableLinBreak; } if((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(DEMO_USART)) { USART_ClearStatusFlags(DEMO_USART,kUSART_TxError | kUSART_RxError); rxbuff[cnt] = USART_ReadByte(DEMO_USART);; switch(state) { case RECV_SYN: if(0x55 == rxbuff[cnt]) { state = RECV_PID; } else { state = IDLE; DisableLinBreak; } break; case RECV_PID: if(0xAD == rxbuff[cnt]) { state = SEND_DATA; } else if(0XEC == rxbuff[cnt]) { state = RECV_DATA; } else { state = IDLE; DisableLinBreak; } break; case RECV_DATA: Sub_rxbuff[recdatacnt++]= rxbuff[cnt]; if(recdatacnt >= 3) // 2 Bytes data + 1 Bytes checksum { recdatacnt=0; state = RECV_SYN; EnableLinBreak; } break; case SEND_DATA: recdatacnt++; if(recdatacnt >= 4) // 2 Bytes data + 1 Bytes checksum { recdatacnt=0; state = RECV_SYN; EnableLinBreak; } break; default:break; } cnt++; } /* 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 } void Lin_Master_Publisher(void) { unsigned int i=0; unsigned char ch =0xa0;//dummy byte //===============================LIN master send===================== DEMO_USART->CTL |= USART_CTL_TXBRKEN_MASK;//enable TX break; while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteBlocking(DEMO_USART,&ch,1);//dummy data break; //just send one byte, otherwise, will send 16 bytes } DEMO_USART->CTL &= ~(USART_CTL_TXBRKEN_MASK); //disable TX break // Send the sync byte 0x55. while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X55); break; //just send one byte, otherwise, will send 16 bytes } //protected ID while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0Xad); break; //just send one byte, otherwise, will send 16 bytes } //Data1 while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X01); break; //just send one byte, otherwise, will send 16 bytes } //Data2 while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X02); break; //just send one byte, otherwise, will send 16 bytes } //Data3 while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X03); break; //just send one byte, otherwise, will send 16 bytes } // checksum byte while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X4c);//0X4c break; //just send one byte, otherwise, will send 16 bytes } } void Lin_Master_Subscribe(void) { unsigned int i=0; unsigned char ch=0xf0;//dummy byte DEMO_USART->CTL |= USART_CTL_TXBRKEN_MASK;//enable TX break; while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteBlocking(DEMO_USART,&ch,1); break; //just send one byte, otherwise, will send 16 bytes } DEMO_USART->CTL &= ~(USART_CTL_TXBRKEN_MASK); //disable TX break // Send the syncy byte 0x55. while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X55); break; //just send one byte, otherwise, will send 16 bytes } //protected ID while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X3C); break; //just send one byte, otherwise, will send 16 bytes } state = RECV_DATA; } The main task here was to generate and detect the LIN break field. If one look closely, to generate the LIN break field in publisher and subscriber frame, we first set the Tx break and then send a dummy byte and then disable the Tx break. The function used to send the dummy byte is USART_WriteBlocking whereas USART_WriteByte is used to send data other than dummy byte. This is because if we use USART_WriteByte during dummy byte then it was not a continuous low as in the other case. I still need to find the reason for this, will update here once done.   LIN SLAVE EXAMPLE LIN Slave receives the LIN publisher data and the subscriber ID data from Master and respond back id required, the software code is modified from the SDK_2.8.2_LPCXpresso55S16 usart_interrupt_rb_transfer project, the detailed code is as follows: void FLEXCOMM3_IRQHandler() { if(DEMO_USART->STAT & USART_STAT_RXBRK_MASK) // detect LIN break { Lin_BKflag = 1; cnt = 0; state = RECV_SYN; DisableLinBreak; } if((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(DEMO_USART)) { USART_ClearStatusFlags(DEMO_USART,kUSART_TxError | kUSART_RxError); rxbuff[cnt] = USART_ReadByte(DEMO_USART);; switch(state) { case RECV_SYN: if(0x55 == rxbuff[cnt]) { state = RECV_PID; } else { state = IDLE; DisableLinBreak; } break; case RECV_PID: if(0xAD == rxbuff[cnt]) { state = RECV_DATA; } else if(0X3C == rxbuff[cnt]) { state = SEND_DATA; senddata(); } else { state = IDLE; DisableLinBreak; } break; case RECV_DATA: recdatacnt++; if(recdatacnt >= 4) // 3 Bytes data + 1 Bytes checksum { recdatacnt=0; state = RECV_SYN; EnableLinBreak; } break; default:break; } cnt++; } /* 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 } void senddata(void) { { while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X01); break; //just send one byte, otherwise, will send 16 bytes } while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X02); break; //just send one byte, otherwise, will send 16 bytes } while (kUSART_TxFifoNotFullFlag & USART_GetStatusFlags(DEMO_USART)) { USART_WriteByte(DEMO_USART, 0X10);// 0X10 correct 0Xaa wrong break; //just send one byte, otherwise, will send 16 bytes } recdatacnt=0; state = RECV_SYN; EnableLinBreak; } } In the next revison, I will update the CRO traces of the LIN frames also. Attaching herewith the codes of the Master and Slave. I hope it helps!!
View full article
Some customers want to generate CRC checksum during compile project, while the GUN tool chain in MCUXpresso IDE doesn’t include CRC checksum calculation function, so we need  the help of CRC checksum tools. In this article, use SRecord. About detail theoretical knowledge of SRecord, please refer to https://mcuoneclipse.com/2015/04/26/crc-checksum-generation-with-srecord-tools-for-gnu-and-eclipse/ In this thread, mainly describe the steps about how to generate CRC checksum with MCUXpresso IDE post-build, through a hands on.   Environment: LPC54S018 chip MCUXpresso IDE SRecord tool ( http://srecord.sourceforge.net/ )   Purpose: Generate and place CRC checksum to 0x10000170 of LPC54s018 after compile project. In image header for LPC540xx devices, the offset 0x10 is crc_value, in LPC54s018 , the address is 0x10000170. so we need save CRC checksum value in  this  place.   Steps: Import SDK demo “led_blinky” into MCUXpresso IDE (Just use this demo to demonstrate).   Enable Compute CRC, because there is one bit in Image header for LPC540xx, Just add “ADD_CRC” or “ADD_CRC =1”, build project.     Can check from S19 file: When choose no CRC computation (no defined “ ADD_CRC “ symbol), the data in address 0x0164 bit0 is 1,   When choose compute CRC, the data in address 0x0164 bit0 is 0,        Download SRecord from http://srecord.sourceforge.net/ After download, srec_cat.exe is the main program we used. Place srec_cat.exe utility in a common directory (to reuse it even if you change the project or even the MCUXpresso IDE version). Be sure you add that “common directory” in the PATH environment variable, then be sure the eclipse was restarted to “see” the PATH content.   Create command file crc_add.txt, and place it under" Debug" folder of project. (About detail commands, please refer to SRecord Reference Manual.) # srec_cat command file to add the CRC and produce application file to be flashed # Usage: srec_cat @filename #first: create CRC checksum lpcxpresso54s018m_led_blinky.srec # input file -fill 0xFF 0x10000180 0x10010000 # fill code area with 0xff -crop 0x10000180 0x10010000 # just keep code area for CRC calculation below (CRC will be at 0x1FFFE..0x1FFFF) -CRC16_Big_Endian 0x10000170 -CCITT # calculate big endian CCITT CRC16 at given address. -crop 0x10000170 0x10000172 # keep the CRC itself #second: add application file lpcxpresso54s018m_led_blinky.srec # input file -fill 0xFF 0x10000180 0x10010000 # fill code area with 0xff -crop 0x10000000 0x10000170 0x10000172 0x10010000 #keep all except CRC #finally, produce the output file -Output # produce output lpcxpresso54s018m_led_blinky_crc.srec   Add post-build command to create srecord file with CRC checksum. arm-none-eabi-objcopy -v -O srec "${BuildArtifactFileName}" "${BuildArtifactFileBaseName}.srec" & srec_cat.exe @CRC_add.txt   7 ) Build project, the .srec with CRC checksum file will under Debug folder:         Pay attention: For the format of image header of LPC540xx devices, we need enable compute CRC and put the CRC value in the specific address. while for other chips, maybe do not need enable, and also can place it in your own address.   Reference: https://mcuoneclipse.com/2015/04/26/crc-checksum-generation-with-srecord-tools-for-gnu-and-eclipse/        
View full article
For the CM33 of LPC55S6x family, the trust zone module is integrated, the memory space and peripherals are classified as security and non-security space. In order to generate interrupt in non-security mode, the NVIC module including the NVIC_ITNSx register must be initialized in security mode so that interrupt module can generate interrupt in non-security mode. The example demos that MRT0 module generates interrupt in non-security mode, the NVIC module is initialized at security mode, MRT0 is initialized at non-security mode. The project is based on MCUXpresso IDE ver11.1 tools, LPC55S69-EVK board and SDK_2.x_LPCXpresso55S69 SDK package version 2.7.1.
View full article
Introducing the LPC550x/S0x family of MCUs The LPC550x/S0x is an extension of the LPC5500 MCU series based on the Arm® Cortex®-M33 technology, featuring up to 256kB of Flash memory and 96kB of on chip RAM. There are up to 8 Flexcomm (choice of any 8 serial –I2C/UART/SPI) and one dedicated 50MHz SPI, and CAN FD(CAN 2.0 for LPC550x). The dual 16-bit ADC can do two independent conversions simultaneously at 2MSPS, there are up to 10 ADC input channels. The comparator has 5 input pins and an external reference voltage.   LPC55S0x MCUs have the Arm TrustZone® technology support and are powered with a security acceleration engine (CASPER) and Secure ROM to provide the support for RSA base authentication. The on chip Physical Unclonable Function (PUF) uses a dedicated SRAM for silicon fingerprint instead of storing the Root key, which means there is no way to read the root key without powering the device up. It also features a True Random Number Generator (TRNG), AES encryption/decryption engine, 128 bit unique device serial number for identification (UUID) and Secure GPIO.   Powering the System Operating at up to 96MHz, the active power consumption of the LPC550x is only 32uA/MHz. The on chip flash is optimized for low power hence it does not perform well in pure Flash and CPU benchmark like the EEMBC Coremark. However in practice, most applications have relatively slow peripherals like I2C, UART, being the bottleneck.  The MCU’s low power consumption performance means that a lot of power is being saved for the system. In addition, high power efficiency enables the LPC550x devices to run much cooler than most 32-bit MCUs. The on-chip DC-DC gives >85% power conversion efficiency, result in very little energy loss as heat inside the chip. In fact LPC5500 MCU series has <2 deg C self-heating when operating at the max frequency. The highly accurate (+/-2% at full temp range, +/-1% from 0 to 85 deg C) on chip Free Running Oscillator (FRO) provides the 96MHz without the need of addition PLL or external crystal for running UART, reducing power consumption. The simple power modes:  Sleep, deep-sleep with RAM retention, power-down with RAM retention and CPU retention, and deep power-down with RAM retention; Provide user the choice on what to keep alive when going into low power mode. In addition, LPC550x/S0x MCUs can be woken-up from configurable peripherals interrupts like the 32kHz RTC, resulting in more power savings.   Powering the Future The LPC550x/S0x family provide a powerful 32-bit MCU with 256kB Flash, low power (active and leakage) at a price point the current existing Cortex-M33 base MCU in the market cannot meet.   Let the LPC550x/S0x power your next product! Learn more about this family at www.nxp.com/LPC550x. Here's the picture of the LPC55S06 EVK board    
View full article
A demonstration of decoding animated GIF files from internal flash on the LPC55S69.   I ported this library:   GitHub - bitbank2/AnimatedGIF: A lightweight Arduino GIF decoder for playing animated files from memory or files on SD c…    The code for the MiniMonkey can be found here:   https://bitbucket.org/ehughes_/minimonkey-sw/src/master/   
View full article
There are two ways to program LPC chips using Flash Magic, ISP mode and  Single Wire Debug (SWD) mode. ISP mode support COM port, USB, CAN and Ethernet. SWD support LINK2(LPC1800/lpc4300) bridge and LPC11u35 bridge. This article uses four demonstrations to show these programming methods.   1. ISP mode   1.1 UART ISP Mode Demonstration   1.2 USB ISP Mode Demonstration 2. Single Wire Debug(SWD) Mode   2.1 SWD over Link2 Bridge     2.1.1 Introduction     2.1.2 Demonstration  2.2 SWD over LPC11U35    2.2.1 Introduction    2.2.2 Demonstration    2.2.3 Recover board   Download Flash Magic tool from: https://www.flashmagictool.com/ Pay attention use the new version Flash Magic v13.10 or later.   About detail steps please refer to attachment. Thanks!
View full article
This document describes the different source clocks and the main modules that manage which clock source is used to derive the system clocks that exists on  LPC’s devices. It’s important to know the different clock sources available on our devices, modifying the default clock configuration may have different purposes since increasing the processor performance, achieving specific baud rates for serial communications, power saving, or simply getting a known base reference for a clock timer. The hardware used for this document is the following: LPC: LPCXpresso55S69 Keep in mind that the described hardware and management clock modules in this document are a general overview of the different platforms and the devices listed above are used as a reference example, some terms and hardware modules functionality may vary between devices of the same platform. For more detailed information about the device hardware modules, please refer to your specific device Reference Manual. LPC platforms The System Control Block (SYSCON) facilitates the clock generation in the LPC platforms, many clocking variations are possible and the maximum clock frequency for an LPC55S6x platform is @150MHz. For example, the LPC55S69 device supports 2 external and 3 internal clock sources. ·     External Clock Sources    Crystal oscillator with an operating frequency of 1 MHz to 32   MHz.    RTC Crystal oscillator with 32.768 kHz operating frequency.   ·    Internal Clock Sources Internal Free Running Oscillator (FRO).   This oscillator provides a selectable 96 MHz output, and a 12 MHz output (divided down from the selected higher frequency) that can be used as a system clock. These 96MHz and 12MHz output frequencies come from a Free Running Oscillator of 192MHz. The 12MHz output provides the default clock at reset and provides a clean system clock shortly after the supply pins reach operating voltage. Note that the 96MHz clock can only be used for a USB device and is not reliable for USB host timing requirements of the data signaling rate.   32 kHz Internal Free Running Oscillator FRO. The FRO is trimmed to +/- 2% accuracy over the entire voltage and temperature range. This FRO can be enabled in several power-down modes such as Deep-Sleep mode, Power-Down mode, and Deep power-down mode, also is used as a clock source for the 32-bit Real-time clock (RTC).   Internal low power oscillator (FRO 1 MHz). The accuracy of this clock is limited to +/- 15% over temperature, voltage, and silicon processing variations after trimming made during assembly. This FRO can be enabled in Deep-Sleep mode, used as a clock source for the PLL0 & PLL1, and for the WWDT(Windowed Watchdog Timer). The LPC55S69 can achieve up to 150MHz but the clock sources are slower than the final System Clock frequency (@150MHz), inside the SYSCON block two Phase Loop Locked (PLL0 & PLL1) allow CPU operation up to the maximum CPU rate without the need for a high-frequency external clock. These PLLs can run from the Internal FRO @12 MHz, the external oscillator, internal FRO @1 MHz, or the 32.768 kHz RTC oscillator. These multiple source clocks fit with the required PLL frequency thanks to the wide input frequency range of 2kHz to 150   MHz.   The PLLs can be enabled or disabled by software. The following diagram shows a high-level description of the possible internal and external clock sources, the interaction with the SYSCON block, and the PLL modules.     Figure   1 . General SYSCON diagram   SYSCON manages the clock sources that will be used for the main clock, system clock, and peripherals. A clock source is selected and depending on the application to develop the PLL modules are used and configured to perform the desired clock frequency. Also, the SYSCON module has several clock multiplexors for each peripheral of the board   i.e ( Systick ,   FullSpeed -USB,   CTimer ), so each peripheral can select its source clock regardless of the clock source selection of other peripherals. For example, the following figure shows these described multiplexers and all the possible clock sources that can be used at the specific module.   Figure  2 . Source clock selection for peripherals   For more detailed information, refer to “Chapter 4. System Control (SYSCON)” from the   LPC55S6x User Manual.  Example:   Enabling/Disabling PLLs The Clock tools available in MCUXpresso IDE, allows you to understand and configure the clock source for the peripherals in the platform. The following diagram shows the default PLL mode configured @150MHz, the yellow path shows all the internal modules involved in the clock configuration. Figure  3 . Default PLL mode @150MHz at Reset of LPC55S69   For example, you can use the Clock tools to configure the clock source of the PLL to use the   clk_in   coming from the internal 32MHz crystal oscillator, the PLL is configured in bypass mode, therefore the PLL gets inactive resulting in power saving. Figure  4 . Bypass of the PLL For more detailed information about PLL configuration, refer to “Chapter 4.6.6. PLL0 and PLL1 functional description” from the   LPC55S6x User Manual.  Example:   The next steps describe how to select a clock source for a specific peripheral using Clock Tools. 1.1   Configure clock for specific peripheral T o configure a peripheral as shown in figure 17, Clock Tools is also useful to configure the clock source for the desired peripheral. For example, using the CTimer0 the available clock sources are the following: Main Clock PLL0 Clock FRO 96MHz Clock   FRO 1MHz Clock MCLK Clock   Oscillator 32KHz Clock No Clock(Inactive)                   Figure 5. CTimer0 Clock Source Selector Select CTIMERCLKSEL0 multiplexor and then switch to one of the mentioned clock sources, for example, the   main_clk (Main Clock @150MHz) the clock multiplexor gets active and the yellow path is highlighted as shown in the following image.     Figure  6 . CTimer0, Main Clock attached 1.2   Export clock configuration to the project After you complete the clock configuration, the Clock Tool will update the source code in   clock_config.c   and   clock_config.h , including all the clock functional groups that we created with the tool. This will include   the clock source for specific peripherals. In the previous example, we configured the CTimer0 to use the   main_clk ; this is translated to the following instruction in source code: “ CLOCK_AttachClk (kMAIN_CLK_to_CTIMER0);” inside the “BOARD_BootClockPLL150M();” function.                         Figure  7 . API called from   clock_config.c   file Note. Remember that before configuring any internal register of a peripheral, its clock source needs to be attached, otherwise, a hard fault occurs. References LPC55S6x/LPC55S2x/LPC552x User Manual Also visit RT's System Clocks Kinetis System Clocks
View full article
LWIP debug output or application messages can be routed out to one of the serial ports by configuring the debug options. Enabling debug output in LWIP To enable debug code in LWIP, the "LWIP_DEBUG" flag needs to be defined when compiling the LWIP code. This can usually be done by using the "-D" option to define the flag as part of the argument list for the compiler. For example in the Keil tools, you can add the define C/C++ tab of the target options dialog. To enable specific debug messages in LWIP, just set the specific define value for the LWIP *_DEBUG value to " LWIP_DBG_ON". A full list of debug defines that can be enabled can be found in the opts.h file. Just copy the defines for the debug messages you want to enable into the lwipopts.h file for your project and enable them there. A few examples are shown below. #define TCP_DEBUG                       LWIP_DBG_ON #define ETHARP_DEBUG                    LWIP_DBG_ON #define PBUF_DEBUG                      LWIP_DBG_ON Selecting debug output The UART channel used for debug outputcan be selected by setting the UART_REDIRECT define to the UART number. On the LPC177x_8x devices, setting this to 0, 1, or 2 will enable output for UART ports 0, 1, or 2, respectively. You can completely disable output (while keep the debug code inside LWIP) by setting UART_REDIRECT to -1. As of release v1.01, simply enabling LWIP_DEBUG as the compilation define will automatically select the right UART for debug output. You can still override the UART for output if needed, but will need to edit the UART in the debug framework file. Caveats of enabling debug output Enabling debug output can add significant size to the generated code based on the debug options selected for the build. It will also slow down performance of the LWIP code due to required run-time checks and output. It's is recommended to enable debug support only if needed. Enabling just the UART for debug output adds about 4KBytes to the code size and about 512 bytes to the data size. The UART driver uses a ring buffer for buffering debug output with the UART IRQ to feed that data to the UART. The ring buffer size can be changed by changing the "UART_RING_BUFSIZE" define value in the serial.c file. Note: The call to initialize the debug framework used for LWIP debug output and printf() is active in the examples by default. Just remove the call to debug_frmwrk_init() in the examples to save some additional code and data memory. You may have also to remove the redirect.c file from the project for this change. Enabling debug output in the LWIP code uses a varying amount of memory based on which LWIP *_DEBUG defines are enabled. Without LWIP debug output enabled and the options selected below, the code size is increased by an additional 23.5KBytes and the data size increased by 1.6KBytes. #define LWIP_DEBUG #define TCP_DEBUG                       LWIP_DBG_ON #define ETHARP_DEBUG                    LWIP_DBG_ON #define PBUF_DEBUG                      LWIP_DBG_ON #define IP_DEBUG                        LWIP_DBG_ON #define TCPIP_DEBUG                     LWIP_DBG_ON #define DHCP_DEBUG                      LWIP_DBG_ON #define UDP_DEBUG                       LWIP_DBG_ON Note memory usage was checked at the 'default' compiler optimization setting. Example debug output Some example debug output use for capturing TCPIP, ethernet ARP, PBUF allocaiton and de-allocation, etc. are shown in the example output below captured from a LWIP run. Ethernet link not yet detected, will continue Starting LWIP ping server... dhcp_start(netif=1000eddc) en0 dhcp_start(): starting new DHCP client dhcp_start(): allocated dhcpudp_bind(ipaddr = 0.0.0.0, port = 68) udp_bind: bound to 0.0.0.0, port 68 udp_connect: connected to 0.0.0.0,port 68 dhcp_start(): starting DHCP configuration dhcp_discover() pbuf_alloc(length=308) pbuf_alloc(length=308) == 200018b4 transaction id xid(abcd0001) dhcp_discover: making request dhcp_discover: realloc()ing dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT) pbuf_header: old 200018fc new 200018f4 (8) udp_send: added header in given pbuf 200018b4 udp_send: sending datagram of length 316 udp_send: UDP packet length 316 udp_send: UDP checksum 0xdee0 udp_send: ip_output_if (,,,,IP_PROTO_UDP,) pbuf_header: old 200018f4 new 200018e0 (20) ip_output_if: en0 IP header: +-------------------------------+ | 4 | 5 |  0x00 |       336     | (v, hl, tos, len) +-------------------------------+ |        0      |000|       0   | (id, flags, offset) +-------------------------------+ |  255  |   17  |    0xba9d     | (ttl, proto, chksum) +-------------------------------+ |    0  |    0  |    0  |    0  | (src) +-------------------------------+ |  255  |  255  |  255  |  255  | (dest) +-------------------------------+ netif->output()pbuf_header: old 200018e0 new 200018d2 (14) etharp_send_ip: sending packet 200018b4 dhcp_discover: deleting()ing pbuf_free(200018b4) pbuf_free: deallocating 200018b4 dhcp_discover: SELECTING dhcp_discover(): set request timeout 2000 msecs tcp_bind: bind to port 7 dhcp_discover() pbuf_alloc(length=308) pbuf_alloc(length=308) == 200018b4 transaction id xid(abcd0002) dhcp_discover: making request dhcp_discover: realloc()ing dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT) pbuf_header: old 200018fc new 200018f4 (8) udp_send: added header in given pbuf 200018b4 udp_send: sending datagram of length 316 udp_send: UDP packet length 316 udp_send: UDP checksum 0xdde0 udp_send: ip_output_if (,,,,IP_PROTO_UDP,) pbuf_header: old 200018f4 new 200018e0 (20) ip_output_if: en0 IP header: +-------------------------------+ | 4 | 5 |  0x00 |       336     | (v, hl, tos, len) +-------------------------------+ |        1      |000|       0   | (id, flags, offset) +-------------------------------+ |  255  |   17  |    0xba9c     | (ttl, proto, chksum) +-------------------------------+ |    0  |    0  |    0  |    0  | (src) +-------------------------------+ |  255  |  255  |  255  |  255  | (dest) +-------------------------------+ netif->output()pbuf_header: old 200018e0 new 200018d2 (14) etharp_send_ip: sending packet 200018b4 dhcp_discover: deleting()ing pbuf_free(200018b4) pbuf_free: deallocating 200018b4 dhcp_discover: SELECTING dhcp_discover(): set request timeout 2000 msecs etharp_request: sending ARP request. pbuf_alloc(length=42) pbuf_alloc(length=42) == 200018b4 etharp_raw: sending raw ARP packet. pbuf_free(200018b4) pbuf_free: deallocating 200018b4 pbuf_alloc(length=594) pbuf_alloc(length=594) == 20004cc0 ethernet_input: dest:00:60:37:12:34:56, src:00:26:f3:a2:6b:b2, type:800 pbuf_header: old 20000050 new 2000005e (-14) ip_input: iphdr->dest 0x1d0a010a netif->ip_addr 0x0 (0x0, 0x0, 0x1d0a010a) ip_input: UDP packet to DHCP client port 68 ip_input: DHCP packet accepted. ip_input: IP header: +-------------------------------+ | 4 | 5 |  0x00 |       576     | (v, hl, tos, len) +-------------------------------+ |        0      |000|       0   | (id, flags, offset) +-------------------------------+ |   64  |   17  |    0x508e     | (ttl, proto, chksum) +-------------------------------+ |   10  |    1  |   10  |    1  | (src) +-------------------------------+ |   10  |    1  |   10  |   29  | (dest) +-------------------------------+ ip_input: p->len 576 p->tot_len 576 pbuf_header: old 2000005e new 20000072 (-20) udp_input: received datagram of length 556 UDP header: +-------------------------------+ |        67     |        68     | (src port, dest port) +-------------------------------+ |       556     |     0x8880    | (len, chksum) +-------------------------------+ udp (10.1.10.29, 68) <-- (10.1.10.1, 67) udp_input: calculating checksum pbuf_header: old 20000072 new 2000007a (-8) dhcp_recv(pbuf = 20004cc0) from DHCP server 10.1.10.1 port 67 pbuf->len = 548 pbuf->tot_len = 548 searching DHCP_OPTION_MESSAGE_TYPE DHCP_OFFER received in DHCP_SELECTING state dhcp_handle_offer(netif=1000eddc) en0 dhcp_handle_offer(): server 0x010a010a dhcp_handle_offer(): offer for 0x1d0a010a dhcp_select(netif=1000eddc) en0 pbuf_alloc(length=308) pbuf_alloc(length=308) == 200018b4 transaction id xid(abcd0003) pbuf_header: old 200018fc new 200018f4 (8) udp_send: added header in given pbuf 200018b4 udp_send: sending datagram of length 316 udp_send: UDP packet length 316 udp_send: UDP checksum 0x9958 udp_send: ip_output_if (,,,,IP_PROTO_UDP,) pbuf_header: old 200018f4 new 200018e0 (20) ip_output_if: en0 IP header: +-------------------------------+ | 4 | 5 |  0x00 |       336     | (v, hl, tos, len) +-------------------------------+ |        2      |000|       0   | (id, flags, offset) +-------------------------------+ |  255  |   17  |    0xba9b     | (ttl, proto, chksum) +-------------------------------+ |    0  |    0  |    0  |    0  | (src) +-------------------------------+ |  255  |  255  |  255  |  255  | (dest) +-------------------------------+ netif->output()pbuf_header: old 200018e0 new 200018d2 (14) etharp_send_ip: sending packet 200018b4 pbuf_free(200018b4) pbuf_free: deallocating 200018b4 dhcp_select: REQUESTING dhcp_select(): set request timeout 2000 msecs pbuf_free(20004cc0) pbuf_free: 20004cc0 has ref 1, ending here. pbuf_free(20004cc0) pbuf_free: deallocating 20004cc0
View full article
Recently I have several customers experience HardFault error when perform AHB FLASH memory read on LPC55S69. If a FLASH sector has never been programed after mass erase, performing AHB reads of the FLASH memory contents will cause a hardware fault if an unrecoverable error is detected. Why? LPC55Sxx parts are delivered from the factory mass erased with ECC unset. When MCUXpresso IDE connects a chip via LinkServer, it will firstly erase the sectors that will be used for the image being programed, then program the code with a correct ECC set. The sectors beyond the end of the image will be left unchanged, which keep in “erased” states without ECC set on them.   When LPC55Sxx executes FLASH read code ( for example, mytemp = *( uint32_t *)0x4000 ) through AHB bus, it checks FLASH ECC while AHB read. No issue to read programed sectors because ECC has already set. But, read unprogrammed sectors with invalid ECC values leads to fail to read and go to HardFault_Handler as below: If performing AHB reads of the flash memory contents AFTER a sector erase, we will have the same HardFault issue. Solutions There are two solutions to fix the error. 1. Read FLASH Content after Programing the FLASH Sector Unlike mass erasing, programing FLASH updates the related ECC value. Thus with a successful ECC check, read AHB can be realizable by below code. volatile uint32_t mytemp ; …… mytemp = * ( uint32_t * ) 0x1000 ; //read memory content 0x1000 to mytemp‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ NOTE: 0x1000 MUST be a “programed” address. If the unused FLASH sector is in “erased” state, in order to read it, we need manually program it before AHB read. FLASH programming demo code can be referred in flashiap demo under MCUXpresso SDK package. See function FLASH_Program. 2. Read FLASH Content Using FLASH Controller Command Read operations using FLASH controller commands (See UM11126 Section “Command listing (CMD)” ) will not cause hard fault. This is the UM recommended method of read FLASH content. Note: Flash operations (erase, blank check, program) and reading a single word can only be performed for CPU frequencies of up to 100 MHz. These operations cannot be performed for frequencies above 100 MHz. So far I haven’t found a FLASH read demo code. Please follow below steps to create your demos. Environment: IDE: MCUXpresso IDE v11.1.0 SDK MCUXpresso SDK v2.7.0 Steps: See attached document. Thanks for the suggestion from  Alex Yang  and andybeeson‌
View full article
1 Abstract       This post is mainly about the LPC54608 LIN slave basic usage, it is similar to the post about the LPC54608 LIN master basic usage.            NXP LPC54608 UART module already have the LIN master and slave function, so this post will give a simple slave code and test result which is associated with the LIN analyzer. Use the LIN analyzer as the LIN master, LPC54608 as the LIN slave, master will send the specific ID frame (publish frame and the subscribe frame) to LIN slave, and wait the feedback from LIN slave side. 2 LPC54608 LIN slave example      Now use the LPCXpresso54608 board as the LIN slave, the PCAN-USB Pro FD LIN analyzer as the LIN master, give the hardware connection and the simple software code about the LIN slave. 2.1 Hardware requirement        Hardware : LPCXpresso54608 , TRK-KEA8 , PCAN-USB Pro FD(LIN analyzer), 12V DC power supply        LIN bus voltage is 12V, but the LPCXpresso54608 board don’t have the on-board LIN transceiver chip, so we need to find the external board which contains LIN transceiver chip, here we will use the TRK-KEA8, this board already have the MC33662LEF LIN transceiver, or the board KIT33662LEFEVB which is mentioned in the LPC54608 LIN master post.  The MC33662LEF LIN transceiver circuit from TRK-KEA8 just as follows: Fig 2-1. LIN transceiver schematic 2.1.1 LPCXpresso54608 and TRK-KEA8 connections      LPCXpresso54608 UART port need to connect to the LIN transceiver: No. LPCXpresso54608 TRK-KEA8 note 1 P4_RX J10-5 UART0_RX 2 P4_TX J10-6 UART0_TX 3 P4_GND J14-1 GND 2.1.2 TRK-KEA8 and LIN master analyzer tool connections        LIN analyzer LIN bus is connected to the TRK-KEA8 LIN bus.        LIN analyzer GND is connected to the TRK-KEA8 GND.             TRK-KEA8 P1 port powered with 12V, LIN master analyzer Vbat pin also need to be connected to 12V.        TRK-KEA8 J13_2 need to connect to 3.3V DC power, but because TRK-KEA8 is the 5V and 12V, so need to find another 3.3V supply to connect J13_2, here use the FRDM-KL43 as the 3.3V supply. Just make sure the LIN transceiver can input 3.3V and output the 3.3V signal to the UART port.    2.1.3 Physical connections 2.2 Software flow and code        This part is about the LIN publisher data and the subscriber ID data between the LIN master and slave. The code is modified based on the SDK  LPCXpresso54608 usart interrupt project.  2.2.1 software flow chart 2.2.2 software code    Code is modified based on SDK_2.3.0_LPCXpresso54608 usart interrupt, the modified code is as follows: void DEMO_USART_IRQHandler ( void ) {      if ( DEMO_USART -> STAT & USART_INTENSET_DELTARXBRKEN_MASK ) // detect LIN break      {        DEMO_USART -> STAT | = USART_INTENSET_DELTARXBRKEN_MASK ; // clear the bit        Lin_BKflag = 1 ;        cnt = 0 ;        state = RECV_SYN ;        DisableLinBreak ;            }     if ( ( kUSART_RxFifoNotEmptyFlag | kUSART_RxError ) & USART_GetStatusFlags ( DEMO_USART ) )      {        USART_ClearStatusFlags ( DEMO_USART , kUSART_TxError | kUSART_RxError ) ;           rxbuff [ cnt ] = USART_ReadByte ( DEMO_USART ) ; ;                   switch ( state )          {             case RECV_SYN :                           if ( 0x55 == rxbuff [ cnt ] )                           {                               state = RECV_PID ;                           }                           else                           {                               state = IDLE ;                               DisableLinBreak ;                           }                           break ;             case RECV_PID :                           if ( 0xAD == rxbuff [ cnt ] )                           {                               state = RECV_DATA ;                           }                           else if ( 0XEC == rxbuff [ cnt ] )                           {                               state = SEND_DATA ;                           }                           else                           {                               state = IDLE ;                               DisableLinBreak ;                           }                           break ;             case RECV_DATA :                           recdatacnt ++ ;                           if ( recdatacnt >= 4 ) // 3 Bytes data + 1 Bytes checksum                           {                               recdatacnt = 0 ;                               state = RECV_SYN ;                               EnableLinBreak ;                           }                           break ;          default : break ;                                    }                   cnt ++ ;      }       /* 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 } /*! * @brief Main function */ int main ( void ) {     usart_config_t config ;     /* attach 12 MHz clock to FLEXCOMM0 (debug console) */     CLOCK_AttachClk ( BOARD_DEBUG_UART_CLK_ATTACH ) ;     BOARD_InitPins ( ) ;     BOARD_BootClockFROHF48M ( ) ;     BOARD_InitDebugConsole ( ) ;     /*      * config.baudRate_Bps = 19200U;      * config.parityMode = kUSART_ParityDisabled;      * config.stopBitCount = kUSART_OneStopBit;      * config.loopback = false;      * config.enableTxFifo = false;      * config.enableRxFifo = false;      */     USART_GetDefaultConfig ( & config ) ;     config . baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE ;     config . enableTx = true ;     config . enableRx = true ;     USART_Init ( DEMO_USART , & config , DEMO_USART_CLK_FREQ ) ;     /* Enable RX interrupt. */     DEMO_USART -> INTENSET | = USART_INTENSET_DELTARXBRKEN_MASK ; //USART_INTENSET_STARTEN_MASK |     USART_EnableInterrupts ( DEMO_USART , kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable ) ;     EnableIRQ ( DEMO_USART_IRQn ) ;     while ( 1 )     {          if ( state == SEND_DATA )        {         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X01 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X02 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X10 ) ; // 0X10 correct 0Xaa wrong             break ;   //just send one byte, otherwise, will send 16 bytes                    }               recdatacnt = 0 ;           state = RECV_SYN ;           EnableLinBreak ;        }          } } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ 3 LPC54608 LIN slave test result   Master define two frames : Unconditional ID Protected ID Direction Data checksum 0X2C 0XEC subscriber 0x01,0x02 0x10 0X2D 0XAD Publisher 0x01,0x02,0x03 0x4c   Now, LIN master send the above two frame to the slave LIN, give the test result and the wave from the LIN bus. 3.1 LIN master configuration Uart baud rate is: 19200bps 3.2 send 0X2C,0X2D frames From the above test result, we can find 0X2D send successfully, 0X2C can receive the data from the LIN save side, the received data is 0X01,0X02 and the checksum 0x10. 3.2.1 0X2D frame LIN bus wave and debug result   From the LIN slave debug result, we can find LIN slave can receive the correct data from the LIN master, and after check, the checksum also correct. 3.2.2 0X2C frame LIN bus wave From the LIN Master tool interface, we can find if the slave give the wrong checksum 0XAA, the master will also can find the checksum is wrong. This is the according LIN bus wave with wrong checksum. From the above test result, we can find LPC54608 LIN slave, can receive the correct LIN bus data, and send back the correct LIN data to the master.
View full article
AN12037 is a commonly adopted solution among LPC users when USB DFU Secondary Bootloader. However when customers run the demo code, they would find their PCs has problem of recognizing LpcDevice. Scenario 1: “ LpcDevice flashes in Device Manager in a very short time then disappear for ever… “ Scenario 2: “ Device Manager can’t recognize LpcDevice…”     This is because the default demo code set DFU device only exist in 5 seconds. User must type dfu command ( dfu-util.exe -l ) very fast before de-initialize USB     So we suggest modify the code to increase the DFU device existence time. Change if ( dwSysTicks > 5 ) ‍ to if ( dwSysTicks > 30 ) ‍   Theoretically, the DFU existance time increases to 30 seconds. Thus we can have enough time slot to type DFU command.
View full article
Overview          Ping-pong is a special case of a linked transfer which typically used more frequently than more complicated versions of linked transfers. A ping-pong transfer usually uses at least two buffers. At any one time, one buffer is being loaded or unloaded by DMA operations. The other buffers have the opposite operation being handled by software, readying the buffer for use when the buffer currently being used by the DMA controller is full or empty. The Fig 1 illustrates an example of descriptors for ping-pong from a peripheral to two buffers in memory. Fig 1 Implementation detail         To continuous transfer the converted result of the ADC to RAM, I’m going to use four 4 DMA descriptors to work in Ping-Pong mode to achieve this goal as the Fig 2 shows. Fig 2 Data flow via Ping-Pong mode Hardware introduction         LPCXpressor54114 Board ( OM13089 ) Fig 3 LPCXpressor54114 Board        Demo code: LPCOpen Library Example code        The code is based on the periph_adc demo, using the SCTimer output as the hardware trigger of ADC, meanwhile, the ADC converted value is transferred to the appointed area of RAM automatically. #include "board.h" #define SCT_PWM            LPC_SCT #define NUM_BUFFERS 4 #define DMA_TRANSFER_SIZE 8 #define ADC_INPUT_CHANNEL 1 #define SCT_PWM_RATE   10000          /* PWM frequency 10 KHz */ #define SCT_PWM_PIN_OUT    7          /* COUT7 Generate square wave */ #define SCT_PWM_OUT        1          /* Index of OUT PWM */ uint16_t adcOut ; ALIGN ( 512 ) DMA_CHDESC_T ADC_TransferDescriptors [ NUM_BUFFERS ] ; uint16_t CapturedData [ 32 ] ; uint16_t DMA_Sum = 0 ; /** * * ADC IRQ not Used right now... Only for testing */ void ADC_SEQA_IRQHandler ( void ) {             /* If SeqA flags is set i.e. data in global register is valid then read it */         Chip_GPIO_SetPinState ( LPC_GPIO , 0 , 6 , true ) ;         //DEBUGOUT("ADC Output = %d\r\n", adcOut);         Chip_GPIO_SetPinState ( LPC_GPIO , 0 , 6 , false ) ;         Chip_ADC_ClearFlags ( LPC_ADC , 0xFFFFFFFF ) ; } void DMA_IRQHandler ( void ) {         static uint16_t DMA_Sum = 0 ;                 DMA_Sum ++ ;                  if ( DMA_Sum == 8 )          {            DMA_Sum = 4 ;          }             Chip_GPIO_SetPinState ( LPC_GPIO , 0 , 7 , true ) ;      /* Rrror interrupt on channel 0? */      if ( ( Chip_DMA_GetIntStatus ( LPC_DMA ) & DMA_INTSTAT_ACTIVEERRINT ) != 0 )      {           /* This shouldn't happen for this simple DMA example, so set the LED              to indicate an error occurred. This is the correct method to clear              an abort. */           Chip_DMA_DisableChannel ( LPC_DMA , DMA_CH0 ) ;           while ( ( Chip_DMA_GetBusyChannels ( LPC_DMA ) & ( 1 << DMA_CH0 ) ) != 0 ) { }           Chip_DMA_AbortChannel ( LPC_DMA , DMA_CH0 ) ;           Chip_DMA_ClearErrorIntChannel ( LPC_DMA , DMA_CH0 ) ;           Chip_DMA_EnableChannel ( LPC_DMA , DMA_CH0 ) ;           Board_LED_Set ( 0 , true ) ;      }      Chip_GPIO_SetPinState ( LPC_GPIO , 0 , 7 , false ) ;      /* Clear DMA interrupt for the channel */      LPC_DMA -> DMACOMMON [ 0 ] . INTA = 1 ; }      /***       *      ____  __  __    _       *     |  _ \|  \/  |  / \       *     | | | | |\/| | / _ \       *     | |_| | |  | |/ ___ \       *     |____/|_|  |_/_/   \_\       *     / ___|  ___| |_ _   _ _ __       *     \___ \ / _ \ __| | | | '_ \       *      ___) |  __/ |_| |_| | |_) |       *     |____/ \___|\__|\__,_| .__/       *                          |_|       */ void DMA_Steup ( void ) {         DMA_CHDESC_T Initial_DMA_Descriptor ;                 ADC_TransferDescriptors [ 0 ] . source = ( uint32_t ) & LPC_ADC -> SEQ_GDAT [ 0 ] ;      ADC_TransferDescriptors [ 1 ] . source = ( uint32_t ) & LPC_ADC -> SEQ_GDAT [ 0 ] ;      ADC_TransferDescriptors [ 2 ] . source = ( uint32_t ) & LPC_ADC -> SEQ_GDAT [ 0 ] ;      ADC_TransferDescriptors [ 3 ] . source = ( uint32_t ) & LPC_ADC -> SEQ_GDAT [ 0 ] ;      ADC_TransferDescriptors [ 0 ] . dest = ( uint32_t ) & CapturedData [ ( 0 + 1 ) * DMA_TRANSFER_SIZE -1 ] ;      ADC_TransferDescriptors [ 1 ] . dest = ( uint32_t ) & CapturedData [ ( 1 + 1 ) * DMA_TRANSFER_SIZE -1 ] ;      ADC_TransferDescriptors [ 2 ] . dest = ( uint32_t ) & CapturedData [ ( 2 + 1 ) * DMA_TRANSFER_SIZE -1 ] ;      ADC_TransferDescriptors [ 3 ] . dest = ( uint32_t ) & CapturedData [ ( 3 + 1 ) * DMA_TRANSFER_SIZE -1 ] ;      //The initial DMA desciptor is the same as the 1st transfer descriptor.   It      //Will link into the 2nd of the main descriptors.      ADC_TransferDescriptors [ 0 ] . next = ( uint32_t ) & ADC_TransferDescriptors [ 1 ] ;      ADC_TransferDescriptors [ 1 ] . next = ( uint32_t ) & ADC_TransferDescriptors [ 2 ] ;      ADC_TransferDescriptors [ 2 ] . next = ( uint32_t ) & ADC_TransferDescriptors [ 3 ] ;      //Link back to the 1st descriptor      ADC_TransferDescriptors [ 3 ] . next = ( uint32_t ) & ADC_TransferDescriptors [ 0 ] ;      //For a test,  stop the transfers here.   The sine wave will look fine.      //ADC_TransferDescriptors[3].next = 0;      ADC_TransferDescriptors [ 0 ] . xfercfg = ( DMA_XFERCFG_CFGVALID |                                DMA_XFERCFG_RELOAD  |                                DMA_XFERCFG_SETINTA |                                DMA_XFERCFG_WIDTH_16 |                                DMA_XFERCFG_SRCINC_0 |                                DMA_XFERCFG_DSTINC_1 |                                DMA_XFERCFG_XFERCOUNT ( DMA_TRANSFER_SIZE ) ) ;      ADC_TransferDescriptors [ 1 ] . xfercfg = ADC_TransferDescriptors [ 0 ] . xfercfg ;      ADC_TransferDescriptors [ 2 ] . xfercfg = ADC_TransferDescriptors [ 0 ] . xfercfg ;      ADC_TransferDescriptors [ 3 ] . xfercfg = ( DMA_XFERCFG_CFGVALID |                                DMA_XFERCFG_RELOAD  |                                DMA_XFERCFG_SETINTA |                               DMA_XFERCFG_WIDTH_16 |                               DMA_XFERCFG_SRCINC_0 |                               DMA_XFERCFG_DSTINC_1 |                               DMA_XFERCFG_XFERCOUNT ( DMA_TRANSFER_SIZE ) ) ;      Initial_DMA_Descriptor . source = ADC_TransferDescriptors [ 0 ] . source ;      Initial_DMA_Descriptor . dest =    ADC_TransferDescriptors [ 0 ] . dest ;      Initial_DMA_Descriptor . next =   ( uint32_t ) & ADC_TransferDescriptors [ 1 ] ;      Initial_DMA_Descriptor . xfercfg = ADC_TransferDescriptors [ 0 ] . xfercfg ;      /* DMA initialization - enable DMA clocking and reset DMA if needed */      Chip_DMA_Init ( LPC_DMA ) ;      /* Enable DMA controller and use driver provided DMA table for current descriptors */      Chip_DMA_Enable ( LPC_DMA ) ;      Chip_DMA_SetSRAMBase ( LPC_DMA , DMA_ADDR ( Chip_DMA_Table ) ) ;      /* Setup channel 0 for the following configuration:         - High channel priority         - Interrupt A fires on descriptor completion */      Chip_DMA_EnableChannel ( LPC_DMA , DMA_CH0 ) ;      Chip_DMA_EnableIntChannel ( LPC_DMA , DMA_CH0 ) ;      Chip_DMA_SetupChannelConfig ( LPC_DMA , DMA_CH0 ,      //(DMA_CFG_PERIPHREQEN     |                                    ( DMA_CFG_HWTRIGEN        |                                     DMA_CFG_TRIGBURST_BURST |                                                          DMA_CFG_TRIGTYPE_EDGE   |                                        DMA_CFG_TRIGPOL_LOW    |     //DMA_CFG_TRIGPOL_HIGH                                        DMA_CFG_BURSTPOWER_1    |                                     DMA_CFG_CHPRIORITY ( 0 )                                          )                                        ) ;      //make sure ADC Sequence A interrupts is selected for for a DMA trigger      LPC_INMUX -> DMA_ITRIG_INMUX [ 0 ] = 0 ;      /* Enable DMA interrupt */      NVIC_EnableIRQ ( DMA_IRQn ) ;      // The 1st descriptor is set up through the registers.      /* Setup transfer descriptor and validate it */      Chip_DMA_SetupTranChannel ( LPC_DMA , DMA_CH0 , & Initial_DMA_Descriptor ) ;      //Use the transfer configuration for our 4 main descriptors      Chip_DMA_SetupChannelTransfer ( LPC_DMA , DMA_CH0 ,      ADC_TransferDescriptors [ 0 ] . xfercfg ) ;      Chip_DMA_SetValidChannel ( LPC_DMA , DMA_CH0 ) ;       } void SCT_PWM_Generate ( void ) {          /* Initialize the SCT as PWM and set frequency */      Chip_SCTPWM_Init ( SCT_PWM ) ;      Chip_SCTPWM_SetRate ( SCT_PWM , SCT_PWM_RATE ) ;      /* Setup Board specific output pin */      Chip_IOCON_PinMuxSet ( LPC_IOCON , 1 , 14 , IOCON_FUNC3 | IOCON_MODE_INACT | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF ) ;      /* Use SCT0_OUT7 pin */      Chip_SCTPWM_SetOutPin ( SCT_PWM , SCT_PWM_OUT , SCT_PWM_PIN_OUT ) ;              /* Start with 50% duty cycle */      Chip_SCTPWM_SetDutyCycle ( SCT_PWM , SCT_PWM_OUT , Chip_SCTPWM_PercentageToTicks ( SCT_PWM , 10 ) ) ;      Chip_SCTPWM_Start ( SCT_PWM ) ;     }      /***            *         _    ____   ____            *        / \  |  _ \ / ___|            *       / _ \ | | | | |            *      / ___ \| |_| | |___            *     /_/__ \_\____/ \____|            *     / ___|  ___| |_ _   _ _ __            *     \___ \ / _ \ __| | | | '_ \            *      ___) |  __/ |_| |_| | |_) |            *     |____/ \___|\__|\__,_| .__/            *                          |_|            */ void ADC_Steup ( void ) {     /*Set Asynch Clock to the Main clock*/     LPC_SYSCON -> ADCCLKSEL = 0 ;     //Set the divider to 1 and enable.  note,  the HALT bit (30) and RESET (29) are not in the manual     LPC_SYSCON -> ADCCLKDIV = 0 ;      /* Initialization ADC to 12 bit and set clock divide to 1 to operate synchronously at System clock */     Chip_ADC_Init ( LPC_ADC , ADC_CR_RESOL ( 3 ) | ADC_CR_CLKDIV ( 0 ) | ADC_CR_ASYNC_MODE ) ;        //select ADC Channel 1 as input     Chip_IOCON_PinMuxSet ( LPC_IOCON , 0 , 30 , IOCON_FUNC0 | IOCON_ANALOG_EN | IOCON_INPFILT_OFF ) ;        LPC_ADC -> INSEL = 0x01 ;     Chip_ADC_SetupSequencer ( LPC_ADC , ADC_SEQA_IDX ,                                                                           ADC_SEQ_CTRL_SEQ_ENA |                               ADC_SEQ_CTRL_CHANNEL_EN ( ADC_INPUT_CHANNEL ) |                                                 ADC_SEQ_CTRL_TRIGGER ( 2 ) |                               ADC_SEQ_CTRL_HWTRIG_POLPOS |                                                 ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS |                               ADC_SEQ_CTRL_MODE_EOS |                                                 ADC_SEQ_CTRL_SEQ_ENA ) ;     /* Enable Sequence A interrupt */     Chip_ADC_EnableInt ( LPC_ADC , ADC_INTEN_SEQA_ENABLE ) ;         /* Calibrate ADC */     if ( Chip_ADC_Calibration ( LPC_ADC ) == LPC_OK ) {         /* Enable ADC SeqA Interrupt */         NVIC_EnableIRQ ( ADC_SEQA_IRQn ) ;     }     else {         DEBUGSTR ( "ADC Calibration Failed \r\n" ) ;         return ;     } } int main ( void ) {       SystemCoreClockUpdate ( ) ;     Board_Init ( ) ;         DMA_Steup ( ) ;     ADC_Steup ( ) ;     SCT_PWM_Generate ( ) ;         while ( 1 )     { }     } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍  Verification      Building the project, then click the   to debug;        Generate the sine wave: 1 KHz, 幅度:0~2 V,feed the wave the ADC via the J9_1(P0_30-ADC1);         Setting the breakpoint (Fig 4) to observe the ADC converted value CapturedData[32]; Fig 4                        4. To verifying the result, I collect several group of data and use the Excel to make these data graphical for checking. Fig 6 is an example. Fig 5 Fig 6 Fig 7 Fig 8
View full article
1 Abstract       In the previous time, I have shared one post about the kinetis L series LIN slave basic usage. Now, because the LPC54608 still don’t have any sample code about the LIN, so this post, I will share a simple code about the LPC54608 LIN master usage, and use the LPCXpresso 54608 board associated with the LIN analyzer to test the result.       This document will realize the LIN master and LIN slave communication, LIN master will send the specific publisher frame and the subscriber frame, the LIN slave will detect the master data’s correction, and feedback the according data. 2 LPC54608 LIN master example      Now use the LPCXpresso54608 board as the LIN master, the LIN analyzer tool as the LIN slave, test the LIN send and receive function between the LIN master and LIN slave. 2.1 Hardware requirement      Hardware : LPCXpresso54608 , KIT33662LEFEVB , PCAN-USB Pro FD       LIN bus voltage is 12V, but the LPCXpresso54608 board don’t have the on board LIN transceiver, so we need to find the external LIN transceiver, then connect the LPC54608 UART port to the LIN transceiver. About the external LIN transceiver, we use the NXP official LIN driver board KIT33662LEFEVB, this board schematic can be found from this link: https://www.nxp.com/docs/en/user-guide/KT33662UG.pdf          Fig 2-1. LIN transceiver schematic    If you don’t have the KIT33662LEFEVB board, don’t worry, you also can use the TRK-KEA8, just like the kinetis LIN post which I have shared. TRK-KEA8 have the on board transceiver chip. 2.1.1 LPCXpresso5460 and IT33662LEF EVB connections No. LPCXpresso54608 KIT33662LEFEVB note 1 P4_RX J4-2 UART0_RX 2 P4_TX J4-1 UART0_TX 3 P4_GND J5-1 GND 4 JP2_3 J5_2 3.3V power supply   2.1.2 KIT33662LEFEVB 12V power supply and LIN slave connection KIT33662LEFEVB board J2_1: 12V power supply, also connect to LIN analyzer VBAT pin J2_3: 12V ground, also connect to LIN analyzer GND pin J2_2: LIN bus, connect to the LIN analyzer LIN pin   2.1.3 Use TRK-KEA8 on board LIN transceiver       This chapter just for those don’t have KIT33662LEFEVB board, but have the TRK-KEA8 board. 1 ) LPCXpresso54608 and TRK-KEA8 connections      LPCXpresso54608 need to connect the UART pin to the LIN transceiver, the connections like this: No. LPCXpresso54608 TRK-KEA8 note 1 P4_RX J10-5 UART0_RX 2 P4_TX J10-6 UART0_TX 3 P4_GND J14-1 GND 2 ) TRK-KEA8  and LIN analyzer connections         LIN bus is the single wire, connect to LIN analyzer LIN pin, GND also need to connect together.        TRK-KEA8 need to use the P1 powered by 12V DC power supply, LIN analyzer also need to connect to the 12V DC.        Because the LPC54608 board is powered by the 3.3V, then also need to power the LPC54608 board with a 3.3V DC power supply. 2.1.4 Physical connections                Fig 2-2. Physcial connections 2.2 Software code       Now, talk about the LIN master send the LIN publisher data and the subscriber ID data, the software code is modified from the SDK_2.3.0_LPCXpresso54608 usart interrupt project, the detail code just as follows: void DEMO_USART_IRQHandler ( void ) {   if ( DEMO_USART -> STAT & USART_INTENSET_DELTARXBRKEN_MASK ) // detect LIN break      {        DEMO_USART -> STAT | = USART_INTENSET_DELTARXBRKEN_MASK ; // clear the bit        Lin_BKflag = 1 ;        cnt = 0 ;        state = RECV_SYN ;        DisableLinBreak ;        }     if ( ( kUSART_RxFifoNotEmptyFlag | kUSART_RxError ) & USART_GetStatusFlags ( DEMO_USART ) )      {        USART_ClearStatusFlags ( DEMO_USART , kUSART_TxError | kUSART_RxError ) ;           rxbuff [ cnt ] = USART_ReadByte ( DEMO_USART ) ;                  switch ( state )          {             case RECV_SYN :                           if ( 0x55 == rxbuff [ cnt ] )                           {                               state = RECV_PID ;                           }                           else                           {                               state = IDLE ;                               DisableLinBreak ;                           }                           break ;             case RECV_PID :                           if ( 0xAD == rxbuff [ cnt ] )                           {                               state = SEND_DATA ;                           }                           else if ( 0XEC == rxbuff [ cnt ] )                           {                               state = RECV_DATA ;                           }                           else                           {                               state = IDLE ;                               DisableLinBreak ;                           }                           break ;             case RECV_DATA :                          Sub_rxbuff [ recdatacnt ++ ] = rxbuff [ cnt ] ;                           if ( recdatacnt >= 3 ) // 2 Bytes data + 1 Bytes checksum                           {                               recdatacnt = 0 ;                               state = RECV_SYN ;                               EnableLinBreak ;                           }                           break ;             case SEND_DATA :                           recdatacnt ++ ;                           if ( recdatacnt >= 4 ) // 2 Bytes data + 1 Bytes checksum                           {                               recdatacnt = 0 ;                               state = RECV_SYN ;                               EnableLinBreak ;                           }                           break ;                                    default : break ;                                  }               cnt ++ ;      }     /* 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 } /********************************************************************************************/ /*Publisher LIN frame /*13bit break+0x55 sync+0xad(0x2D's protected ID)+0x01+0x02+0x03+0x4C(check sum) //All the above byte is sent by the LIN master /********************************************************************************************/ void Lin_Master_Publisher ( void ) {     unsigned int i = 0 ; //===============================LIN master send=====================        DEMO_USART -> CTL | = USART_CTL_TXBRKEN_MASK ; //enable TX break;        while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0Xff ) ; //dummy byte, no means             break ;   //just send one byte, otherwise, will send 16 bytes         }          for ( i = 0 ; i < 10000 ; i ++ ) ; // delay for the break generation.        DEMO_USART -> CTL & = ~ ( USART_CTL_TXBRKEN_MASK ) ; //disable TX break        // Send the syncy byte 0x55.         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X55 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }          //protected ID         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0Xad ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }         //Data1        while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X01 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }            //Data2         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X02 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }         //Data3         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X03 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }               // checksum byte         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X4c ) ; //0X4c             break ;   //just send one byte, otherwise, will send 16 bytes         }      } void Lin_Master_Subscribe ( void ) {   unsigned int i = 0 ;        DEMO_USART -> CTL | = USART_CTL_TXBRKEN_MASK ; //enable TX break;        while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0Xff ) ; //dummy byte, no means             break ;   //just send one byte, otherwise, will send 16 bytes         }          for ( i = 0 ; i < 10000 ; i ++ ) ; // delay for the break generation.       // for(i=0;i<5000;i++);        DEMO_USART -> CTL & = ~ ( USART_CTL_TXBRKEN_MASK ) ; //disable TX break        // Send the syncy byte 0x55.         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0X55 ) ;             break ;   //just send one byte, otherwise, will send 16 bytes         }          //protected ID         while ( kUSART_TxFifoNotFullFlag & USART_GetStatusFlags ( DEMO_USART ) )         {             USART_WriteByte ( DEMO_USART , 0XEC ) ; //0XEC             break ;   //just send one byte, otherwise, will send 16 bytes         } } /*! * @brief Main function */ int main ( void ) {     unsigned int i = 0 ;     usart_config_t config ;     /* attach 12 MHz clock to FLEXCOMM0 (debug console) */     CLOCK_AttachClk ( BOARD_DEBUG_UART_CLK_ATTACH ) ;     BOARD_InitPins ( ) ;     BOARD_BootClockFROHF48M ( ) ;     BOARD_InitDebugConsole ( ) ;     /*      * config.baudRate_Bps = 19200U;      * config.parityMode = kUSART_ParityDisabled;      * config.stopBitCount = kUSART_OneStopBit;      * config.loopback = false;      * config.enableTxFifo = false;      * config.enableRxFifo = false;      */     USART_GetDefaultConfig ( & config ) ;     config . baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE ;     config . enableTx = true ;     config . enableRx = true ;     USART_Init ( DEMO_USART , & config , DEMO_USART_CLK_FREQ ) ;     /* Enable RX interrupt. */     DEMO_USART -> INTENSET | = USART_INTENSET_DELTARXBRKEN_MASK ; //USART_INTENSET_STARTEN_MASK |        //enable USART interrupt     cnt = 0 ;             USART_EnableInterrupts ( DEMO_USART , kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable ) ;     EnableIRQ ( DEMO_USART_IRQn ) ; //All ID datas will be received in the interrupt         Lin_Master_Publisher ( ) ; //LIN master send publisher ID 0x2D     for ( i = 0 ; i < 65535 ; i ++ ) ; //delay     Lin_Master_Subscribe ( ) ; //LIN master send subscriber ID 0x2c     while ( 1 )     {     } } ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍     In USART_Init function , add the LIN function enable code :     /* setup configuration and enable USART */     base->CFG = USART_CFG_PARITYSEL(config->parityMode) | USART_CFG_STOPLEN(config->stopBitCount) |                 USART_CFG_DATALEN(config->bitCountPerChar) | USART_CFG_LOOP(config->loopback) | USART_CFG_ENABLE_MASK | USART_CFG_LINMODE_MASK;// 3 LPC54608 LIN master test result   Master side define two ID frame : Unconditional ID Protected ID Direction Data checksum 0X2C 0XEC subscriber 0x01,0x02 0x10 0X2D 0XAD Publisher 0x01,0x02,0x03 0x4c   Now, LIN master will send the above two ID frame to the slave, then give the test result about the feedback from the slave and the LIN bus wave. 3.1 LIN slave configuration The LIN baud rate is defined as 9600bps. The following picture is from the LIN analyzer (PEAK LIN tool) software: To get the data from the LIN slave, the master need to send the 0x2C frame at first, then the slave will send back the according data. The master subscriber frame is the slave’s publisher frame; the master publisher frame is the slave’s subscriber. Master send, slave receive. Master receive, then the slave is the send side.       In the slave software side, need to configure the 0X2C ID according data, then press the space key, the slave will wait for the master’s according frame. 3.2 Send 0X2C and 0X2D frame From the slave side, we can find 0X2D is received successfully from the master, 0X2C can send the correct data to the master. 3.2.1 0X2D frame data LIN bus wave and debug result Yellow wave is the LPC54608 UART TX pin wave. Blue wave is the LIN bus wave. From the LIN bus wave, we can find that the LIN master can send out the correct LIN data, and the checksum also correct from the slave received side. 3.2.2 0X2C data LIN bus wave and debug result Yellow wave is the LPC54608 UART TX pin wave. Blue wave is the LIN bus wave. From the wave, we can find that after the LIN master send the 0X2C data, the slave will send back the according data to the master, now check the LPC54608 debug data from IAR: From the received data and the checksum data,  we can find the slave feedback is correct. So, the above modified code can realize the LPC54608 LIN master frame basic send and receive function.  Next time, I will also share a post about the LPC54608 LIN slave code. Wish it helps you!  
View full article
        In recent years of MCU technology evolving, booting from the external flash seems to become more and more popular, actually, LPC already has employed this technology for many years.         NXP's recently released the LPC540xx family which continues the trend of high-performance flash-less MCU.         The developers may be a bit confused with the external FLASH which is used for storing the program, as they are used to directly using the internal FLASH for programming and debugging the chip. But, don't worry, let me introduce it in the following sections. LPC54018's three ways of loading program        In general, RAM stores data, however, RAM can also store programs. In previous projects, we occasionally move some key functions in RAM in order to improve the execution speed of these programs. The current implementation is to put all the programs in RAM more thoroughly. Based on this idea, you can directly use the debugger to load the executable image into the on-chip RAM and this method is called RAM TARGET.       After downloading the executable program image file to the external flash, when the bootloader loads the complete image to on-chip RAM to run, the method is called the Plain Load Image method.             Actually, both of these above ideas are routine, chip designers have also created a "super-capability" that allows the chip to directly execute external FLASH programs (Execute In Place, XIP). With this 'superpower', no matter whether the program boot from the external FLASH or the internal FLASH, there is no difference in operating performance.       The RAM TARGET method mentioned above is only suitable for debugging the application. Once the chip is powered off or reset, the downloaded program in the RAM will disappear. Meanwhile, the size of the RAM also give some restrictions for debugging.        In the Plain Load and XIP modes, the executable image file is stored in the external flash. After MCU is powered, the bootloader which is resided in ROM copies the first 512 bytes from the image (vector components and image header) into internal SRAMX at location 0x0000 0000 to validate the vector table and image header to confirm the booting mode. And the program will not be lost after power-off or reset. Fig1 illustrates the boot process of LPC54018. Fig1 LPC54018 boot process flow Experiment show         Board: LPCXpresso54018 board (OM40003) Fig1 LPCXpresso54018 board       Demo code: Hello world (From the SDK), m odifying the hello world code in below way, which points out the load program way and date time. PRINTF ( "hello world. XXXXXXXX \r\n" ) ;     PRINTF ( "hello world, %s, %s.\r\n" , __DATE__ , __TIME__ ) ; ‍‍‍‍‍‍‍‍‍‍ ‍ ‍ Experiment 1: RAM Target         Demo code: Hello world (From the SDK), m odifying the hello world code in below way. PRINTF ( "hello world. RAM Target \r\n" ) ; PRINTF ( "hello world, %s, %s.\r\n" , __DATE__ , __TIME__ ) ; ‍‍‍‍‍‍‍‍ ‍ ‍       Note: Setting the Reset: Core when debugging the demo Fig2 Setting the Reset: Core Running testing: As the Fig3 illustrates, it would print the below message when debugging the demo, however, after reset, it would run the plain load image which is programmed before, as the RAM lost the hello world demo. Fig3 RAM Target runing testing Experiment 2: Plain Load Image        Demo code: Hello world (From the SDK), modifying the hello world code in below way. PRINTF ( "hello world. PLAIN LOAD IMAGE \r\n" ) ; PRINTF ( "hello world, %s, %s.\r\n" , __DATE__ , __TIME__ ) ; ‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍       Download image to external flash:        1. Build the demo to generate a bin file.           This plainload example linked the vector table to 0x00000000, but program to external flash 0x10000000.        2. Program the bin file to external on board flash via SEGGER J-FLASH Lite(V6.22 or higher):             a. Open SEGGER J-FLASH Lite, select device LPC54018.             b. Click the 'Erase Chip' to erase the extrenal flash.(if can not success, press SW4 button and reset the board, and try to erase again)                 Note: if can not success( press SW4 and reset the board, and try to erase again) Fig4 Erase the external flash              c. Select the bin data file, set the '.bin/Erase Start' address to 0x10000000, then click 'Program Device' Fig5 Program the external flash Running testing: Fig6 illustrates the result of  running the plain load image. Fig6 Plain load image runing testing Experiment 3: XIP Image        Demo code: Hello world qspi_xip (From the SDK), modifying the code in below way. PRINTF ( "hello world. PLAIN LOAD IMAGE \r\n" ) ; PRINTF ( "hello world, %s, %s.\r\n" , __DATE__ , __TIME__ ) ; ‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍       Download image to external flash:        1. Build the demo to generate a bin file.        2. Program the bin file to external on board flash via SEGGER J-FLASH Lite(V6.22 or higher):            a. Open SEGGER J-FLASH Lite, select device LPC54018.            b. Click the 'Erase Chip' to erase the extrenal flash.(if can not success, press SW4 button and reset the board, and try to erase again)            Note: if can not success( press SW4 and reset the board, and try to erase again) Fig7 Erase the external flash           c. Select the bin data file, set the '.bin/Erase Start' address to 0x10000000, then click 'Program Device' Fig8 Program the external flash      Running testing:      Fig9 illustrates the result of  running the plain load image. Fig9 XIP image runing testing  
View full article
Previously, I wrote two articles about LPC55xx AHB read ( How to fix AHB Read HardFault Error ) and LPC55xx FLASH alignment ( Why FLASH Program cannot Success?  ). In this article, we will go on investigating LPC55xx erased memory state. For most of NXP MCU, the erased FLASH state is 0xFF. Writing action is to change 1 to 0. However for LPC55, when we perform mass erase or section erase, we see the related memory turns to all 0 in MCUXpresso IDE debugger Memory view. This all-0-erased-status confuses many LPC55 beginners. Is this real memory state? The answer is yes, IDE debugger display is correct. LPC55xx FLASH uses 0x00 as erased value, which is opposite to most of the other FLASH devices which use 0xFF as erased value) There is no way to verify the erased FLASH state with code in runtime. NXP enhanced LPC55xx FLASH with ECC added. This means that there is now a functional block between the read entity (for example the CPU) and the FLASH itself. When erasing, both the erased FLASH and its ECC are set as 0. The reading can’t be successful if the erased memory and its ECC don’t match. Thus we can’t read memory in erased state. AHB read hardfault error is produced if do so.  Because of ECC mechanism, you can't read FLASH until you have written to it. see   How to fix AHB Read HardFault Error The User's Manual mentions the reading and writing operation in UM11126 chapter 5.7.13: When writing, parity is automatically computed and stored alongside user data. When reading, data and parity are used to reconstruct correct data, even in the case of a 1-bit error. When reading an erased location, an uncorrectable error is flagged. Use the “blank check” command to test for successful erase. The LinkServer debug in MCUXpresso IDE takes some precautions to avoid this problem while programming the FLASH before starting a debug session. That’s the reason we can see erased memory state in debugger memory view window, Admittedly, this is something not really pre-eminent in the documentation. The only reference we could spot is in UM11126. See below: “ The selected pages are checked for the erased condition (all 0 including parity)”   Thanks for the valuable comment from Radu Theodor Lazarescu.
View full article
For LPC55(S)1x/2x/6x users, please update your fsl_power_lib to SDK2.8.2. The previous SDK(2.6.x and 2.7.x)'s power library have two known function bugs,  1. FRO trim value can not be recovery correctly after wakeup from deep-sleep / power-down / deep power-down.    -- this means the 12MHz FRO frequency is different for after boot-process(11.99 MHz for example) and wakeup from low-power modes(11.89MHz for example).     -- The reason is the FRO trim value not recovery after wakeup.  2. Cap-bank value can not be set correctly by use power lib capbank trim API.    -- This is a software bug which fixed in SDK2.8.2 already. Just replacement the power_lib library file should be workable for most of customers. the API should be compatible. Thank you! Magicoe
View full article
Introduction Amazon Web Services (AWS) is the world’s most comprehensive and broadly adopted cloud platform, offering over 165 fully-featured services from data centers globally. Millions of customers —including the fastest-growing startups, largest enterprises, and leading government agencies—trust AWS to power their infrastructure, become more agile, and lower costs.This document will take you step-by-step in a simple approach to adding peripherals to your AWS IOT and Alexa skills project. This is in continuation of the demo established in the following link, it is important to have this completed before continuing with this guide: Connecting the LPC55S69 to Amazon Web Services  Prerequisites - LPC55S69-EVK - Mikroe WiFi 10 Click - AWS Account - Alexa Developer Account - MCUXpresso IDE 11.2 - LPC55S69 SDK 2.8.0 Modifying "AWS_REMOTE_CONTROL_WIFI" In this example I will be adding a single-ended ADC peripheral. 1. First, create a separate .c and .h files in my source folder to keep it organized.  2. Initialize your peripheral. This includes your global variables, pins, clocks, interrupt handlers and other necessary peripheral configurations yours may have.  In my new_peripherals.c file, I add the following 2.1 Definitions: 2.2 Global variables: 2.3 Interrupt handler: 2.4 Initialization function: 2.5 Read ADC Function: 3.  Create header file with the two functions that will be used to enable the ADC, make sure to include the "fsl_lpadc"drivers. 4.  Add the ADC pin with pin configuration tool.  4.1 In this example I use PIO0_23 for the ADC0 Channel 0, 5. Add ADC_Init function to the main. 6. Now let's go ahead and modify "remote_control.c". Here we need to build the JSON text that we want updating our Thing's shadow with the ADC value, add the read function, add the variable in the initial shadow document and the keyword for our DeltaJSON. 6.1 First create global variables for the actual state of the ADC interaction and the parsed state. 6.2 Add external function which will read the ADC value. 6.3 Shadows use   JSON shadow documents   to store and retrieve data. A shadow’s document contains a state property that describes these aspects of the device’s state: desired: Apps specify the desired states of device properties by updating the desired object. reported: Devices report their current state in the reported object. delta: AWS IoT reports differences between the desired and the reported state in the delta object. 6.4 I've added the initial ADC state with a hard-coded 0, so that I can verify my Thing's shadow is initialized with the new information. 6.5 In the "void processShadowDeltaJSON(char *json, uint32_t jsonLength)" function, we need to add the condition for the change in state of the ADC. This will helps us identify when the action to read the ADC is requested. 6.6 Finally in the "prvShadowMainTask" function, we will create the action based on the above request. We can add some PRINTFs so that we know that the action is requested and processed properly through the serial console. As you may see I only want to update the ADC value when it is requested. Meaning the value of the ADC's state or parsed state is important. We will clear it to zero after we read the ADC and only update the value when it is 1. As opposed to the LEDState and parsedLEDState, where the value is important since it points to which color LED will be on/off. That's it you can build and run the project! Now we can add the Alexa Skill and the functionality in the AWS Lambda. MODIFYING AWS LAMBDA Since the lambda will be the connection between our LPCXpresso board and the Alexa Skill, we need to add the handler for  our new ADC requests. 1.  In this example we add the third request type which is the ADC event and the name of the callback function we will use.  2. The callback function "manage_ADC_request" will contain the attributes for reading and updating the shadow, this will consequently cause the change in delta shadow so our LPC55S69 will read the ADC pin. In addition, the utterances sent to the Alexa skill as well as how we want Alexa to respond will also be defined here.  As you may observe our function builds the JSON payload to update the shadow with a "1" when it is called and ignores the led and accelerometer values. We delay for 2.5 seconds to allow the LPC to read and write the ADC value in the necessary field and send the updated shadow. Then the Lambda will read the shadow and create the return message.  With this we construct the answer for Alexa. MODIFYING ALEXA SKILLS 1.  First create a custom 'intent'. Here is the general definition of what the utterances will be to request an action from the AWS Thing.    1.1 The name needs to match the name used for the event in the Lambda. In this example it is ADC_INTENT 2. Before we create the utterances, let's create the slot types. This is the list of all the words possible that may come to mind that a user might say to request a reading from the ADC.  2.1 The name of the slot type is not crucial, however please note it as we will need it later.  2.2 Add slot values. You can add as many as you think are necessary. For recommendations on custom slot values please check, best practices for sample utterances. 2.3 Go back to the general view of the ADC_INTENT, scroll down and we will add how the slot will be included in the utterances. In this example I use adc_name, however the name here is also not crucial. Select the slot type list we created earlier. 2.4 Now scroll back up and lets begin adding the sample utterances. This can be any command that you believe a user can say to invoke this action. You do not need to include the wake word here. In brackets add the name of your intent slot, in this case it is {adc_name}. That's it! You can save and rebuild the model. You are now ready to test it. You can do so through the 'Test' tab on the developer's console. In addition if you have an Alexa device or the SLN-ALEXA-IOT, you can test it by speaking with Alexa directly. In your LPCXpresso55S69 you can connect the 3.3V or the 0V to the ADC pin so you can see how the value is returned every request. 
View full article
This article is about how to use MCUXpresso Config Tool to create a USB project from start. The method is the same to all MCUXpresso Config Tool supported MCUs Demo: Creating USB composite HID mouse + keyboard project. Prequisities: LPCXpresso55S69-EVK MCUXPresso IDE 11.1.1 SDK package for LPCXpresso55S69 ,SDK_2.7.1_LPCXpresso55S69. The SDK has to be imported into MCUXPresso IDE (in Installed SDKs). Step by step guide is attached. Enjoy it :-).
View full article
I updated the design for the Mini-Monkey and used PCB:NG for fabrication.
View full article