MCUXpresso SDK Knowledge Base

cancel
Showing results for 
Search instead for 
Did you mean: 

MCUXpresso SDK Knowledge Base

Labels

Discussions

Introduction   Azure RTOS is a comprehensive suite of multithreading facilities, middleware and Windows tools for developing embedded IoT applications. It features Azure RTOS ThreadX, a small, fast, reliable real-time operating system that is already powering more than 6.2 billion devices worldwide. Most of the volume are components in smart phones, cellular modems, WiFi, Bluetooth, GPS, etc. Now Azure RTOS is integrated into MCUXpresso SDK2.8.5 and is available from our SDK builder site ( https://mcuxpresso.nxp.com) and also directly from MCUXpresso IDE. Support is currently available for i.MX RT1050, i.MX RT1060 and i.MX RT1064 MCUs. Please select Azure RTOS before you download it.     Code Structure   Below picture is the code structure of evkmimxrt1064_threadx_demo. Azure RTOS kernel is provided as a library, libthreadx.a.  You can import the evkmimxrt1064_threadx_lib to generate this library.      Tx_initialize_low_level.S : an assembly file that contains the low level initialization for ThreadX. The primary function of this file is to set up the System Tick handler, which controls the internal timing of ThreadX.   Tx_user.h   configuration options. Options defined in tx_user.h are applied only if the application and ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. Thread_demo.c The Thread_demo.c file contains the application entry point main(). This function is responsible for the following: Entering the ThreadX kernel Initializing the board Start the main application thread   Create a ThreadX application   There are four steps required to build a ThreadX application Include the tx_api.h file in all application files that uses ThreadX services or data structures. Create the standard C main function. This function must eventually call  tx_kernel_enter to start ThreadX. Tx_kernel_enter: The entry function coordinates initialization of various ThreadX data structures and then call the application’s definition function tx_application_define. Create the tx_application_define function. It executes after the basic ThreadX initialization is complete. It is responsible for setting up all of the initial system resources, including threads, queues, semaphores, mutexes, event flags, and memory pools. After tx_application_define completes, control is transferred to the thread scheduler and from there to each individual thread.   The small Example system is as below picture shows.   #include "tx_api.h" unsigned long my_thread_counter = 0; TX_THREAD my_thread; main( ) { /* Enter the ThreadX kernel. */ tx_kernel_enter( ); } void tx_application_define(void *first_unused_memory) { /* Create my_thread! */ tx_thread_create(&my_thread, "My Thread", my_thread_entry, 0x1234, first_unused_memory, 1024, 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); } void my_thread_entry(ULONG thread_input) { /* Enter into a forever loop. */ while(1) { /* Increment thread counter. */ my_thread_counter++; /* Sleep for 1 tick. */ tx_thread_sleep(1); } }   4  Compile evkmimxrt1064_threadx_demo and debug   Console output:   THREADX example ... start thread 0 ... start thread 5 ... start thread 3 ... start thread 4 ... start thread 6 ... start thread 7 ... start thread 1 ... start thread 2 ...    
View full article
  FreeRTOS supports multiple heap allocation schemes. Scheme 5 allows the heap to span multiple non adjacent (non-contiguous) memory regions. Heap_5 is useful when RAM provided by the system on which FreeRTOS is running does not appear as a single contiguous block in the system’s memory map. With heap_5, developers can combine multiple memory blocks for a virtual combined memory heap. In this article, I will take FrdmK82f hello_world_freertos as an example to illustrate how to use FreeRTOS heap 5 memory scheme with MCUXpresso SDK. Like some other Kinetis MCUs, Frdmk82f has two memory controllers, one for the SRAM_UPPER (192k byters) and one or SRAM_Lower as below (64K byters).   With FreeRTOS heap_4, application developers cannot have memory objects crossing that memory boundary 0x2000,000, they can only use SRAM_UPPER or SRAM_LOWER as FreeRTOS heap, with heap_5, they can combine SRAM_UPPER and SRAM_LOWER as a huge virtual FreeRTOS memory map. 1    Define multiple memory blocks Each separate memory areas is described by a structure of type HeapRegion_t. A description of all the available memory areas is passed into vPortDefineHeapRegions( ) as an array of HeapRegion_t structures. /* Used by heap_5.c to define the start address and size of each memory region that together comprise the total FreeRTOS heap space. */ typedef struct HeapRegion {     uint8_t *pucStartAddress;     size_t xSizeInBytes; } HeapRegion_t;   We can create an array of these structures to define our different memory blocks that can be assigned to the heap. For FrdmK82f, we can define two memory blocks, SRAM_UPPER and SRAM_LOWER. But SRAM_UPPER is the main RAM, it is not possible to allocate all the RAM to heap, leaving no RAM free for use by other variables. It is good to declare an array called ucHeap, it becomes part of the data allocated to RAM by linker. /*define the start address and size of SRAM_LOWER region not used by the the linker*/ #define SRAM_LOWER_START_ADDRESS  ( (uint8_t*) 0x1fff0000 ) #define SRAM_LOWER_SIZE           ( 0X10000)   /*Declare an array that will be part of the heap used by heap_5.  The array will be placed in SRAM_UPPER by the linker*/ #define SRAM_UPPOER_HEAP_SIZE (80 * 1024) static __attribute__ ((used,section(".noinit_RAM2"))) uint8_t ucHeap[SRAM_UPPOER_HEAP_SIZE]; /* placed in in no_init section inside SRAM_UPPER */   /*Create an array of HeapRegion_t definitions. this array will be passed to vPortDefineHeapRegions( ) */   const HeapRegion_t xHeapRegions[] = {         {SRAM_LOWER_START_ADDRESS, SRAM_LOWER_SIZE },         {ucHeap, SRAM_UPPOER_HEAP_SIZE },         {NULL, 0} };   Please note that the array should be terminated with a NULL zero sized region definition and the memory regions defined in the array must appear in address order from low address to high address.   2     FreeRTOS heap_5 Initialization   Heap_5 memory allocation scheme must be explicitly initialized before pvPortMalloc( ) can be used.  Heap_5 is initialized using the vPortDefineheapRegions( ) API function. It is used to specify the start address and size of each separate memory area that together makes up the total memory used by heap_5. When heap_5 is used, vPortDefineHeapRegions( ) must be called before any kernel objects (tasks, queues, semaphores, etc) can be created.  Usually this API is called in main function.       vPortDefineHeapRegions(xHeapRegions);   /*pass the array into vPortDefineHeapRegions(), must be called first*/   3    Configure FreeRTOS memory scheme To use Scheme, make sure heap_5.c is used in the application as below picture shows. ConfigFRTOS_MEMORY_SCHEME should be configured to ‘5’ in FreeRTOSConfig.h.         4     Using multiple FreeRTOS memory regions and Debugging Next I will allocate 100K memory with pvPortMalloc API in the hello_task.   int i;     unsigned char *handle;     for (i=0; i<10; i++)     {         handle =  pvPortMalloc(10*1024);         if (NULL == handle)         {             PRINTF("Malloc failed \r\n");         }         else         {             PRINTF("allocated buffer[%d], size 10K, address is 0x%x\r\n", i, handle);         }     } The console output is as below picture.  From the allocated address, we can see that 60K is allocated from SRAM_LOWER and 40K is from SRAM_UPPER.   SEGGER J-Link GDB Server V6.86e - Terminal output channel heapsize is 147432!. allocated buffer[0], size 10K, address is 0x1fff09c8 allocated buffer[1], size 10K, address is 0x1fff31d0 allocated buffer[2], size 10K, address is 0x1fff59d8 allocated buffer[3], size 10K, address is 0x1fff81e0 allocated buffer[4], size 10K, address is 0x1fffa9e8 allocated buffer[5], size 10K, address is 0x1fffd1f0 allocated buffer[6], size 10K, address is 0x20000298 allocated buffer[7], size 10K, address is 0x20002aa0 allocated buffer[8], size 10K, address is 0x200052a8 allocated buffer[9], size 10K, address is 0x20007ab0   From the heap and usage view, we can see the detailed memory info.            
View full article
LwIP can be used in two basic modes: Mainloop mode (“NO_SYS”)(no OS/RTOS running on target system) or OS mode (TCPIP thread) (there is an OS running on the target system). In mainloop mode, only raw API can be used. In OS mode, raw API and sequential APIs can be used. The raw API is an event-driven and non thread-safe API designed to be used without an operation system.  A particular application may register to be notified via a callback function for events such as incoming data available, outgoing data sent, error notifications, poll timer expiration, connection closed, etc. The callback functions will be called from the LwIP core layer when the corresponding event occurs. This post is focused on how to use raw API with MCUXpresso SDK. For sequential-style and socket API, please refer to below thread. https://community.nxp.com/docs/DOC-344955 Starting a network interface To create a new network interface, the user allocates space for a new struct net_if  and calls netif_add ,  LwIP needs an IP address. LwIP can use either DHCP or a static IP address. IP4_ADDR(&fsl_netif0_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3); IP4_ADDR(&fsl_netif0_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3); IP4_ADDR(&fsl_netif0_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3);     netif_add(& fsl_netif0 , &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, &fsl_enet_config0, ethernetif0_init,              ethernet_input); netif_set_default(& fsl_netif0 ); netif_set_up(& fsl_netif0 );   Pass ethernet_input API to netif_add API as input callback function that is called to pass ingress packets up in the protocol layer stack. LwIP Initialization Call lwip_init to init lwIP stack and all of its subsystems.   void lwip_init(void) { #ifndef LWIP_SKIP_CONST_CHECK   int a = 0; #ifdef LWIP_NOASSERT /* Caused compiler warning. */   LWIP_UNUSED_ARG(a); #endif   LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void *, &a) == &a); #endif #ifndef LWIP_SKIP_PACKING_CHECK   LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE); #endif     /* Modules initialization */   stats_init(); #if !NO_SYS   sys_init(); #endif /* !NO_SYS */   mem_init();   memp_init();   pbuf_init();   netif_init(); #if LWIP_IPV4   ip_init(); #if LWIP_ARP   etharp_init(); #endif /* LWIP_ARP */ #endif /* LWIP_IPV4 */ #if LWIP_RAW   raw_init(); #endif /* LWIP_RAW */ #if LWIP_UDP   udp_init(); #endif /* LWIP_UDP */ #if LWIP_TCP   tcp_init(); #endif /* LWIP_TCP */ #if LWIP_IGMP   igmp_init(); #endif /* LWIP_IGMP */ #if LWIP_DNS   dns_init(); #endif /* LWIP_DNS */ #if PPP_SUPPORT   ppp_init(); #endif   #if LWIP_TIMERS   sys_timeouts_init(); #endif /* LWIP_TIMERS */ } LwIP Raw—Main loop   In the while 1 loop,  we need to Poll the driver to get packets.  When a packet is ready, call function ethernetif_linkinput()  to handle the actual reception of the bytes from the network interface. Then the type of the received packet is determined and the appropriate input function is called. Handle all system timeouts for all core protocols.   Please refer to tcpecho server demo in MCUXpresso SDK. evkbimxrt1050_lwip_tcpecho_bm\source\lwip_tcpecho_bm.c /*!  * @brief Main function.  */ int main( void ) {     struct netif fsl_netif0; …       time_init ();   …     lwip_init();   …       tcpecho_raw_init();   …     while (1)     {         /* Poll the driver, get any outstanding frames */         ethernetif_input(&fsl_netif0);           sys_check_timeouts(); /* Handle all system timeouts for all core protocols */     } }   When using the netconn and socket API, the timers are handled in the background and the user typically does not need to manually implement them.  In the raw mode, the user must manually implement any required timers. Evkbimxrt1050_lwip_tcpecho_bm/lwip/port/sys_arch.c void time_init( void ) { #ifdef __CA7_REV     /* special for i.mx6ul */     SystemSetupSystick(1000U, ( void *)time_isr, 0U);     SystemClearSystickFlag(); #else     /* Set SysTick period to 1 ms and enable its interrupts */     SysTick_Config(USEC_TO_COUNT(1000U, sourceClock)); #endif }     Using Raw API The LwIP raw API is designed around a series of callbacks, your application registers callback functions to process specific events. Most callbacks are centered around a “protocol control block”, or PCB. evkbimxrt1050_lwip_tcpecho_bm\lwip\contrib\apps\tcpecho_raw\tcpecho_raw.c tcpecho_raq_init is called for initializing the TCP echo server application.   void tcpecho_raw_init ( void ) {   tcpecho_raw_pcb = tcp_new_ip_type( IPADDR_TYPE_ANY );   if (tcpecho_raw_pcb != NULL) {     err_t err;       err = tcp_bind(tcpecho_raw_pcb, IP_ANY_TYPE, 7);     if (err == ERR_OK ) {       tcpecho_raw_pcb = tcp_listen(tcpecho_raw_pcb);       tcp_accept(tcpecho_raw_pcb, tcpecho_raw_accept);     } else {       /* abort? output diagnostic? */     }   } else {     /* abort? output diagnostic? */   } }     Tcpecho_raw_init calls tcp_new_ip_type for creating a new TCP protocol control block (PCB) tcpecho_raw_pcb. Tcp_bind is used to bound the new created tcpecho_raw_pcb to a local IP address and port. Next, function tcp_listen is called in order to start TCP listening process on the TCP PCB. Finally a callback function tcpecho_raw_accept is assigned for handling incoming TCP connections on the TCP PCB (tcpecho_raw_pcb). This is done by using  function tcp_accept. After that, the TCP echo server is ready to accept any incoming connection from remote clients. The following example shows how incoming TCP connections are handled by the user callback function tcpecho_raw_accept. static err_t tcpecho_raw_accept ( void *arg, struct tcp_pcb *newpcb, err_t err) {   err_t ret_err;   struct tcpecho_raw_state *es;     LWIP_UNUSED_ARG(arg);   if ((err != ERR_OK ) || (newpcb == NULL)) {     return ERR_VAL ;   }     /* Unless this pcb should have NORMAL priority, set its priority now.      When running out of pcbs , low priority pcbs can be aborted to create      new pcbs of higher priority. */   tcp_setprio(newpcb, TCP_PRIO_MIN);     es = ( struct tcpecho_raw_state *)mem_malloc( sizeof ( struct tcpecho_raw_state ));   if (es != NULL) {     es-> state = ES_ACCEPTED ;     es-> pcb = newpcb;     es-> retries = 0;     es-> p = NULL;     /* pass newly allocated es to our callbacks */     tcp_arg(newpcb, es);     tcp_recv(newpcb, tcpecho_raw_recv);     tcp_err(newpcb, tcpecho_raw_error);     tcp_poll(newpcb, tcpecho_raw_poll, 0);     tcp_sent(newpcb, tcpecho_raw_sent);     ret_err = ERR_OK ;   } else {     ret_err = ERR_MEM ;   }   return ret_err; }   The new TCP connection is passed to callback function tcpecho_raw_accept through the parameter ‘newpcb’ Structure ‘es’ maintains application status. Tcp_arg specifies the program state shat should be passed to all other callback functions.  ‘es’ is passed as an argument to the connection TCP PCB ‘newpcb’. Tcp_recv sets the callback function that will be called when new data arrives. ‘ tcpecho_raw_recv ’ is assigned to handle all the data traffic. tcp_err specifies the function (tcpecho_raw_error) that should be called when a fatal error has occurred on the connection. tcp_poll specifies the polling interval and the callback function (tcpecho_raw_poll) that should be called to poll the application. tcp_sent specifies the callback function (tcpecho_raw_sent) that should be called when data has successfully received (i.e ackknowledged) by the remote host. Finally tcpecho_raw_sent will call tcp_write Configuration LwIP lwipopts.h is a user file that you can use to fully configure lwIP and all of its modules. You do not need to define every option that lwIP provides; if you do not define an option, a default value will be used. Therefore, your lwipopts.h provides a way to override much of the behavior of lwIP. Use Mainloop mode, we do not run an OS. We need to #define NO_SYS to 1. Please refer to lwipopts.h in MCUXpresso SDK. evkbimxrt1050_lwip_tcpecho_bm\source\lwipopts.h … /**  * NO_SYS==1: Bare metal lwIP  */ #define NO_SYS 1 /**  * LWIP_NETCONN==0: Disable Netconn API (require to use api_lib.c)  */ #define LWIP_NETCONN 0 /**  * LWIP_SOCKET==0: Disable Socket API (require to use sockets.c)  */ #define LWIP_SOCKET 0   /**  * LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT=1: we need to free PBUF_RAM pbufs  * from ISR context on LPC.  */ #if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0) #ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT #define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 #endif #endif …            
View full article
LwIP can be used in two basic modes: Mainloop mode (“NO_SYS”)(no OS/RTOS running on target system) or OS mode (TCPIP thread) (there is an OS running on the target system). In mainloop mode, only raw API can be used. In OS mode, raw API and sequential APIs can be used. In OS mode, the lwip stack and the application run in separate tasks. The application communicates with the LwIP stack through sequential API calls that sue the RTOS mailbox mechaniam for inter-process communicatioin. This post is focusing on how to design a LwIP applicatioin in OS mode with sequential API in MCUXpresso SDK. It is for LwIP beginners. The code snipperts is from MCUXpresso SDK2.6. For how to design a LwIP applicaton in mainloop mode (bare metal mode) with raw API, please refer to below link: Developing LwIP Applications with Raw API       Generally, a LwIP application inlcudes network interface setting up, LwIP stack initialization , using LwIP API, and configuration.   1. Starting a network interface To create a new network interface, the user allocates space for a new struct netif (but does not initialize any part of it) and calls netifapi_netif_add :     IP4_ADDR(&fsl_netif0_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3);     IP4_ADDR(&fsl_netif0_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3); IP4_ADDR(&fsl_netif0_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3);       netifapi_netif_add (&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, &fsl_enet_config0,                        ethernetif0_init, tcpip_input); Pass tcpip_input API to netif_add API as input callback function that is called to pass ingress packets up in the protocol layer stack   next we need to bring the interface up An interface that is “up” is available to your application for input and output, and “down” is the opposite state. Therefore, before you can use the interface, you must bring it up. This can be accomplished depending on how the interface gets its IP address.  We can use static IP address  or DHCP. Set the network interface as the default network interface netifapi_netif_set_default(&fsl_netif0);   Bring the interface up, available for processing     netifapi_netif_set_up(&fsl_netif0); 2. Initializing LwIP stack   Call tcpip_init to create tcpip_thread, this thread has exclusive access to LwIP core functions. Other threads communicate with this thread using message boxes. It also starts all the timers to make sure they are running in the right thread context.   tcpip_init(NULL, NULL);   void   tcpip_init(tcpip_init_done_fn initfunc, void *arg) {   lwip_init();     tcpip_init_done = initfunc;   tcpip_init_done_arg = arg;   if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) {     LWIP_ASSERT("failed to create tcpip_thread mbox", 0);   } #if LWIP_TCPIP_CORE_LOCKING   if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {     LWIP_ASSERT("failed to create lock_tcpip_core", 0);   } #endif /* LWIP_TCPIP_CORE_LOCKING */     sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); } Priority of user task should not exceed the priority of tcpip_thread   - In lwipopts.h, the priority of tcpip_thread     #define TCPIP_THREAD_PRIO              2   3. Using sequential API   As shown in the below figure, the steps for establishing a TCP connection on the client side are the following: Create a connection using the netconn_new() function; Connect to the address of the server using the netconn_connect() function; Send and receive data by means of the netconn_recv() and netconn_write() functions. Close the connection by means of the netconn_close() function. The steps involved in establishing a TCP connection on the server side are as follows: Create a TCP connection with the netconn_new() function; Bind the server to an address using the netconn_bind() function; Listen for connections with the netconn_listen() function; Accept a connection with the netconn_accept() function. This call typically blocks until a client connects with the server. Send and receive data by means of netconn_write() and netconn_recv(). Close the connection by means of the netconn_close() function.   Middleware/lwip/contrib/appa/tcpecho/tcpecho.c static void tcpecho_thread ( void *arg) {   struct netconn *conn, *newconn;   err_t err;   LWIP_UNUSED_ARG(arg);     /* Create a new connection identifier. */   /* Bind connection to well known port number 7. */ #if LWIP_IPV6   conn = netconn_new(NETCONN_TCP_IPV6);   netconn_bind(conn, IP6_ADDR_ANY, 7); #else /* LWIP_IPV6 */   conn = netconn_new( NETCONN_TCP );   netconn_bind(conn, IP_ADDR_ANY, 7); #endif /* LWIP_IPV6 */   LWIP_ERROR( " tcpecho : invalid conn " , (conn != NULL), return ;);     /* Tell connection to go into listening mode. */   netconn_listen(conn);     while (1) {       /* Grab new connection. */     err = netconn_accept(conn, &newconn);     /* printf ("accepted new connection %p\n", newconn );*/     /* Process the new connection. */     if (err == ERR_OK ) {       struct netbuf *buf;       void *data;       u16_t len;             while ((err = netconn_recv(newconn, &buf)) == ERR_OK ) {         /* printf (" Recved \n");*/         do {              netbuf_data(buf, &data, &len);              err = netconn_write(newconn, data, len, NETCONN_COPY); #if 0             if (err != ERR_OK) {               printf( " tcpecho : netconn_write: error \"%s\"\n" , lwip_strerr(err));             } #endif         } while (netbuf_next(buf) >= 0);         netbuf_delete(buf);       }       /* printf ("Got EOF, looping\n");*/       /* Close connection and discard connection identifier. */       netconn_close(newconn);       netconn_delete(newconn);     }   } }   From the tcpecho thread, we can see First, one new TCP connection was called with parameter NETCONN_TCP  by API netconn_new. #define netconn_new(t)                  netconn_new_with_proto_and_callback(t, 0, NULL) struct netconn * netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) {   struct netconn *conn;   API_MSG_VAR_DECLARE(msg);   API_MSG_VAR_ALLOC_RETURN_NULL(msg);     conn = netconn_alloc(t, callback);   if (conn != NULL) {     err_t err;       API_MSG_VAR_REF(msg).msg.n.proto = proto;     API_MSG_VAR_REF(msg).conn = conn;     err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg));     if (err != ERR_OK) {       LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);       LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); #if LWIP_TCP       LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); #endif /* LWIP_TCP */ #if !LWIP_NETCONN_SEM_PER_THREAD       LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));       sys_sem_free(&conn->op_completed); #endif /* !LWIP_NETCONN_SEM_PER_THREAD */       sys_mbox_free(&conn->recvmbox);       memp_free(MEMP_NETCONN, conn);       API_MSG_VAR_FREE(msg);       return NULL;     }   }   API_MSG_VAR_FREE(msg);   return conn; }   Then, the newly created connection is then bound to port 7 (echo protocol) by calling the API function netconn_bind.   Next, the application starts the listening process on the connection by calling the API function netconn_listen. In the infinite while(1) loop, the application waits for a new connection by calling the API function netconn_accept. This API will block the application task when there is no incoming connection. When there is an incoming connection, the application can start receiving data by calling the API function netconn_recv. Incoming data are received in a netbuf.       Application can get the received data by calling the netbuf API function netbuf_data. err_t netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) {   LWIP_ERROR("netbuf_data: invalid buf", (buf != NULL), return ERR_ARG;);   LWIP_ERROR("netbuf_data: invalid dataptr", (dataptr != NULL), return ERR_ARG;);   LWIP_ERROR("netbuf_data: invalid len", (len != NULL), return ERR_ARG;);     if (buf->ptr == NULL) {     return ERR_BUF;   }   *dataptr = buf->ptr->payload;   *len = buf->ptr->len;   return ERR_OK; }   The received data is sent back (echoed) to the remote TCP client by calling the API function netconn_write. Netconn_close and netconn_delete are used to respectively close and delete the netconn connection     4. Configuration LwIP lwipopts.h is a user file that you can use to fully configure lwIP and all of its modules. You do not need to define every option that lwIP provides; if you do not define an option, a default value will be used. Therefore, your lwipopts.h provides a way to override much of the behavior of lwIP. In multi theads mode, . We need to #define NO_SYS to 0. Please refer to evkbimxrt1050_lwip_tcpecho_freertos\source\lwipopts.h … #if USE_RTOS   /**  * SYS_LIGHTWEIGHT_PROT==1: if you want inter -task protection for certain  * critical regions during buffer allocation, deallocation and memory  * allocation and deallocation.  */ #define SYS_LIGHTWEIGHT_PROT 1   /**  * NO_SYS==0: Use RTOS  */ #define NO_SYS 0 /**  * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)  */ #define LWIP_NETCONN 1 /**  * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)  */ #define LWIP_SOCKET 1   /**  * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/ netconns and  * SO_RCVTIMEO processing.  */ #define LWIP_SO_RCVTIMEO 1 …          
View full article
This article describes how to configure a peripheral timer in a FreeRTOS project with MCUXpresso config tools. Software and Tools In this article, I’m using the following: MCUXpresso IDE 10.2.1   www.nxp.com/mcuxpresso MCUXpresso SDK 2.4.1 for  Frdm-k66f  board.  With Amazon FreeRTOS v10 . You can get it from https://mcuxpresso.nxp.com FRDM-K66 board  www.nxp.com/frdm-k66f First make sure you have a working FreeRTOS project. Please refer to below link for creating a new FreeRTOS project.  https://community.nxp.com/docs/DOC-341972 To open the tool, simply right click on the project in Project Explorer and select the appropriate Open command: With the peripheral Tool, we can use it to configure initialization of selected peripherals and generate code for them. we are picking the FTM0 timer ,of course we could use any other timer too. Click OK, then configure the timer to 10KHz. We will use the timer interrupt to increase a counter, so don’t forget to turn on the interrupt To update the generated code in the related tool chain project, click the Update Project button. Click OK, new code will be generated. Please check peripheral.c & peripheral.h Timer ISR Next we add the timer interrupt code to the application. #include "fsl_ftm.h"   /*******************************************************************************  * Variables  ******************************************************************************/ volatile bool ftmIsrFlag = false; volatile uint32_t milisecondCounts = 0U;       void FTM_1_IRQHANDLER ( void ) {     /* Clear interrupt flag.*/     FTM_ClearStatusFlags(FTM0, kFTM_TimeOverflowFlag );     ftmIsrFlag = true; } Adding Timer Drivers The project won’t compile yet, because the necessary drivers are not part of the project yet. To add them, use the ‘Manage SDK components’ button: Then check the ftm driver and press OK and get the extra driver sources added to the project. We can see that fsl_ftm.c & fsl_ftm.h added into this project. Adding timer to FreeRTOS application: In this task, the FTM interrupt will trigger a message printed to the terminal /*!  * @brief Task responsible for printing message with FTM0.  */ static void my_task( void *pvParameters) {       uint32_t cnt;     uint32_t loop = 2U;     uint32_t secondLoop = 1000U;     const char *signals = "-|" ;       cnt = 0;       while (true)     {          if (ftmIsrFlag)         {             milisecondCounts++;             ftmIsrFlag = false;             if (milisecondCounts >= secondLoop)             {                 PRINTF( "%c" , signals[cnt & 1]);                 cnt++;                 if (cnt >= loop)                 {                     cnt = 0;                 }                 milisecondCounts = 0U;             }         }         __WFI();     } } Run the demo console output: For information about how to use MCUXpresso pins tool in a FreeRTOS project, please see the following document. https://community.nxp.com/docs/DOC-341987 For information about how to create an FreeRTOS project with MCUXpresso IDE, please see the following document https://community.nxp.com/docs/DOC-341972 
View full article
This tutorial is introducing the eRPC (embedded remote procedure call) open-source project. The eRPC (Embedded Remote Procedure Call) is a Remote Procedure Call (RPC) system created by NXP. An RPC is a mechanism used to invoke a software routine on a remote system using a simple local function call. The remote system may be any CPU connected by an arbitrary communications channel: a server across a network, another CPU core in a multicore system, and so on. To the client, it is just like calling a function in a library built into the application. The only difference is any latency or unreliability introduced by the communications channel. Important links:  Everything related to the eRPC development is placed GitHub - eRPC base. The eRPC development is placed GitHub - eRPC development.  The eRPC releases are placed GitHub - eRPC Releases. The eRPC documentation is placed Github - eRPC wiki  The eRPC as Python Package on pypi  The eRPC is supporting multicore and multiprocessor types of applications.  Where to find eRPC: Multicores examples LPCXpresso54114 -  MCUXpresso download page i.mx6sx, i.mx7d - GitHub - eRPC i.MX demos  Multiprocessor examples frdmk22f, frdmk28f, frdmk64f, frdmk66f, frdmk82f, frdmkl25z, frdmkl27z,  frdmkl43z - MCUXpresso  download page
View full article
This documents describes who to use this tool in order to generate the routing and muxing for pins. Pins Tool Overview The Pins Tool is an easy-to-use way to configure the pins of the device. The Pins Tool software enables you to create, inspect, change, and modify any aspect of the pin configuration and muxing of the device. This document introduces you to the Pins Tool. It describes the basic components of the tool and lists the steps to configure and use the tool to configure the pins. This tool is provided as an online WEB application. You need to generate a downloadable MCUXpresso SDK v.2 package. The below link shows the steps for do that. Generating a downloadable MCUXpresso SDK v.2 package  Selecting Pins Tool SDK v.2 package. The below link sh
View full article
Generating a downloadable MCUXpresso SDK v.2 package   Follow these steps to get your MCUXpresso SDK v.2 package for your Kinetis or LPC-based MCU solution.   1) Go to the MCUXpresso Config Tools page:   Welcome | MCUXpresso SDK Builder    2) Click on the Select Development board option:     3) If you are not logged in you will be redirected to the Sign in page:   4) After signing in you will be directed to select a development board, to do this you need to select the corresponding processor, board or kit to be used and click on Build MCUXpresso SDK:     5) By default the package will be built for Windows and for the MCUXpresso IDE, this can be changed by clicking on drop-down menus:     6) You can also specify the included middleware, RTOS and development preferences for your MCUXpresso SDK package.        7) After specifying the required settings make sure the configuration information shown on the right hand side is correct click on Download SDK:     Note: You may be asked to fill your User basic information on the Preferences page before downloading the package.   😎 Agree to the Software Terms and Conditions:     9) The download of your MCUXpresso SDK package should start automatically:         Related links: Introducing MCUXpresso SDK v.2 for LPC54xxx Series  How to start with SDK v.2.0 for LPC5411x using LPCXpresso IDE  Using the MCUXpresso Pins Tool   MCUXpresso Config Tools is now available!  
View full article