diff --git a/source/.gitignore b/source/.gitignore new file mode 100644 index 0000000..e10e727 --- /dev/null +++ b/source/.gitignore @@ -0,0 +1 @@ +/.metadata/ diff --git a/source/.mcuxpressoide_packages_support/crt_directory.xml b/source/.mcuxpressoide_packages_support/crt_directory.xml new file mode 100644 index 0000000..3102557 --- /dev/null +++ b/source/.mcuxpressoide_packages_support/crt_directory.xml @@ -0,0 +1,4 @@ + + + + diff --git a/source/.mcuxpressoide_packages_support/info.properties b/source/.mcuxpressoide_packages_support/info.properties new file mode 100644 index 0000000..0ae3399 --- /dev/null +++ b/source/.mcuxpressoide_packages_support/info.properties @@ -0,0 +1,5 @@ +#MCUXpresso IDE +#Thu Mar 23 11:41:26 EET 2023 +product.name=MCUXpresso IDE v11.5.1 [Build 7266] [2022-04-13] +product.version=11.5.1 +product.build=7266 diff --git a/source/.mcuxpressoide_packages_support/readme.txt b/source/.mcuxpressoide_packages_support/readme.txt new file mode 100644 index 0000000..00460b7 --- /dev/null +++ b/source/.mcuxpressoide_packages_support/readme.txt @@ -0,0 +1,2 @@ +This folder is automatically created and contains the SDK part support for the IDE +*** DO NOT REMOVE OR MODIFY, YOUR CHANGES WILL BE OVERWRITTEN ON SDK REFRESH *** \ No newline at end of file diff --git a/source/freertos_blinky/.cproject b/source/freertos_blinky/.cproject new file mode 100644 index 0000000..1b5f34b --- /dev/null +++ b/source/freertos_blinky/.cproject @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <?xml version="1.0" encoding="UTF-8"?> +<TargetConfig> +<Properties property_0="" property_3="NXP" property_4="LPC11U68" property_count="5" version="60100"/> +<infoList vendor="NXP"> +<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen"> +<chip> +<name>LPC11U68</name> +<family>LPC11U6x</family> +<vendor>NXP (formerly Philips)</vendor> +<reset board="None" core="Real" sys="Real"/> +<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/> +<memory can_program="true" id="Flash" is_ro="true" type="Flash"/> +<memory id="RAM" type="RAM"/> +<memory id="Periph" is_volatile="true" type="Peripheral"/> +<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/> +<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/> +<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/> +<peripheralInstance derived_from="V6M_NVIC" determined="infoFile" id="NVIC" location="0xe000e000"/> +<peripheralInstance derived_from="V6M_DCR" determined="infoFile" id="DCR" location="0xe000edf0"/> +<peripheralInstance derived_from="I2C0" determined="infoFile" id="I2C0" location="0x40000000"/> +<peripheralInstance derived_from="WWDT" determined="infoFile" id="WWDT" location="0x40004000"/> +<peripheralInstance derived_from="USART0" determined="infoFile" id="USART0" location="0x40008000"/> +<peripheralInstance derived_from="CT16B0" determined="infoFile" id="CT16B0" location="0x4000c000"/> +<peripheralInstance derived_from="CT16B1" determined="infoFile" id="CT16B1" location="0x40010000"/> +<peripheralInstance derived_from="CT32B0" determined="infoFile" id="CT32B0" location="0x40014000"/> +<peripheralInstance derived_from="CT32B1" determined="infoFile" id="CT32B1" location="0x40018000"/> +<peripheralInstance derived_from="ADC" determined="infoFile" id="ADC" location="0x4001c000"/> +<peripheralInstance derived_from="I2C1" determined="infoFile" id="I2C1" location="0x40020000"/> +<peripheralInstance derived_from="RTC" determined="infoFile" id="RTC" location="0x40024000"/> +<peripheralInstance derived_from="DMATRIGMUX" determined="infoFile" id="DMATRIGMUX" location="0x40028000"/> +<peripheralInstance derived_from="PMU" determined="infoFile" id="PMU" location="0x40038000"/> +<peripheralInstance derived_from="FLASHCTRL" determined="infoFile" id="FLASHCTRL" location="0x4003c000"/> +<peripheralInstance derived_from="SSP0" determined="infoFile" id="SSP0" location="0x40040000"/> +<peripheralInstance derived_from="IOCON" determined="infoFile" id="IOCON" location="0x40044000"/> +<peripheralInstance derived_from="SYSCON" determined="infoFile" id="SYSCON" location="0x40048000"/> +<peripheralInstance derived_from="USART4" determined="infoFile" id="USART4" location="0x4004c000"/> +<peripheralInstance derived_from="SSP1" determined="infoFile" id="SSP1" location="0x40058000"/> +<peripheralInstance derived_from="GINT0" determined="infoFile" id="GINT0" location="0x4005c000"/> +<peripheralInstance derived_from="GINT1" determined="infoFile" id="GINT1" location="0x40060000"/> +<peripheralInstance derived_from="USART1" determined="infoFile" id="USART1" location="0x4006c000"/> +<peripheralInstance derived_from="USART2" determined="infoFile" id="USART2" location="0x40070000"/> +<peripheralInstance derived_from="USART3" determined="infoFile" id="USART3" location="0x40074000"/> +<peripheralInstance derived_from="USB" determined="infoFile" id="USB" location="0x40080000"/> +<peripheralInstance derived_from="CRC" determined="infoFile" id="CRC" location="0x50000000"/> +<peripheralInstance derived_from="DMA" determined="infoFile" id="DMA" location="0x50004000"/> +<peripheralInstance derived_from="SCT0" determined="infoFile" id="SCT0" location="0x5000c000"/> +<peripheralInstance derived_from="SCT1" determined="infoFile" id="SCT1" location="0x5000e000"/> +<peripheralInstance derived_from="GPIO-PORT" determined="infoFile" id="GPIO-PORT" location="0xa0000000"/> +<peripheralInstance derived_from="PINT" determined="infoFile" id="PINT" location="0xa0004000"/> +</chip> +<processor> +<name gcc_name="cortex-m0">Cortex-M0</name> +<family>Cortex-M</family> +</processor> +<link href="LPC11U6x_peripheral.xme" show="embed" type="simple"/> +</info> +</infoList> +</TargetConfig> + + diff --git a/source/freertos_blinky/.project b/source/freertos_blinky/.project new file mode 100644 index 0000000..5ea2517 --- /dev/null +++ b/source/freertos_blinky/.project @@ -0,0 +1,28 @@ + + + freertos_blinky + + + lpc_chip_11u6x + lpc_board_nxp_lpcxpresso_11u68 + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/source/freertos_blinky/.settings/language.settings.xml b/source/freertos_blinky/.settings/language.settings.xml new file mode 100644 index 0000000..bc044e3 --- /dev/null +++ b/source/freertos_blinky/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/freertos_blinky/example/inc/FreeRTOSConfig.h b/source/freertos_blinky/example/inc/FreeRTOSConfig.h new file mode 100644 index 0000000..21f882b --- /dev/null +++ b/source/freertos_blinky/example/inc/FreeRTOSConfig.h @@ -0,0 +1,158 @@ +/* + FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd. + + + *************************************************************************** + * * + * FreeRTOS tutorial books are available in pdf and paperback. * + * Complete, revised, and edited pdf reference manuals are also * + * available. * + * * + * Purchasing FreeRTOS documentation will not only help you, by * + * ensuring you get running as quickly as possible and with an * + * in-depth knowledge of how to use FreeRTOS, it will also help * + * the FreeRTOS project to continue with its mission of providing * + * professional grade, cross platform, de facto standard solutions * + * for microcontrollers - completely free of charge! * + * * + * >>> See http://www.FreeRTOS.org/Documentation for details. <<< * + * * + * Thank you for using FreeRTOS, and thank you for your support! * + * * + *************************************************************************** + + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + >>>NOTE<<< The modification to the GPL is included to allow you to + distribute a combined work that includes FreeRTOS without being obliged to + provide the source code for proprietary components outside of the FreeRTOS + kernel. FreeRTOS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#ifndef __IASMARM__ +/* For SystemCoreClock */ +#include "board.h" +#endif + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 8 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 64 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 1024 + 512) ) +#define configMAX_TASK_NAME_LEN ( 10 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TICKLESS_IDLE 1 + + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* Software timer definitions. This example uses I2C to write to the LEDs. As +this takes a finite time, and because a timer callback writes to an LED, the +priority of the timer task is kept to a minimum to ensure it does not disrupt +test tasks that check their own execution times. */ +#define configUSE_TIMERS 0 +#define configTIMER_TASK_PRIORITY ( 0 ) +#define configTIMER_QUEUE_LENGTH 5 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 1 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS + /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 5 /* 32 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x1f + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } + +#define configUSE_CUSTOM_TICK 0 + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS +standard names - or at least those used in the unmodified vector table. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ + diff --git a/source/freertos_blinky/example/src/aeabi_romdiv_patch.s b/source/freertos_blinky/example/src/aeabi_romdiv_patch.s new file mode 100644 index 0000000..bbbf1e9 --- /dev/null +++ b/source/freertos_blinky/example/src/aeabi_romdiv_patch.s @@ -0,0 +1,93 @@ +//***************************************************************************** +// aeabi_romdiv_patch.s +// - Provides "patch" versions of the aeabi integer divide functions to +// replace the standard ones pulled in from the C library, which vector +// integer divides onto the rom division functions contained in +// specific NXP MCUs such as LPC11Uxx and LPC12xx. +// - Note that this patching will only occur if "__USE_ROMDIVIDE" is +// defined for the project build for both the compiler and assembler. +//***************************************************************************** +// +// Copyright(C) NXP Semiconductors, 2013 +// All rights reserved. +// +// Software that is described herein is for illustrative purposes only +// which provides customers with programming information regarding the +// LPC products. This software is supplied "AS IS" without any warranties of +// any kind, and NXP Semiconductors and its licensor disclaim any and +// all warranties, express or implied, including all implied warranties of +// merchantability, fitness for a particular purpose and non-infringement of +// intellectual property rights. NXP Semiconductors assumes no responsibility +// or liability for the use of the software, conveys no license or rights under any +// patent, copyright, mask work right, or any other intellectual property rights in +// or to any products. NXP Semiconductors reserves the right to make changes +// in the software without notification. NXP Semiconductors also makes no +// representation or warranty that such application will be suitable for the +// specified use without further testing or modification. +// +// Permission to use, copy, modify, and distribute this software and its +// documentation is hereby granted, under NXP Semiconductors' and its +// licensor's relevant copyrights in the software, without fee, provided that it +// is used in conjunction with NXP Semiconductors microcontrollers. This +// copyright, permission, and disclaimer notice must appear in all copies of +// this code. +//***************************************************************************** +#if defined(__USE_ROMDIVIDE) + +// Note that the romdivide "divmod" functions are not actually called from +// the below code, as these functions are actually just wrappers to the +// main romdivide "div" functions which push the quotient and remainder onto +// the stack, so as to be compatible with the way that C returns structures. +// +// This is not needed for the aeabi "divmod" functions, as the compiler +// automatically generates code that handles the return values being passed +// back in registers when it generates inline calls to __aeabi_idivmod and +// __aeabi_uidivmod routines. + + .syntax unified + .text + +// ========= __aeabi_idiv & __aeabi_idivmod ========= + .align 2 + .section .text.__aeabi_idiv + + .global __aeabi_idiv + .set __aeabi_idivmod, __aeabi_idiv // make __aeabi_uidivmod an alias + .global __aeabi_idivmod + .global pDivRom_idiv // pointer to the romdivide 'idiv' functione + .func + .thumb_func + .type __aeabi_idiv, %function + +__aeabi_idiv: + push {r4, lr} + ldr r3, =pDivRom_idiv + ldr r3, [r3, #0] // Load address of function + blx r3 // Call divide function + pop {r4, pc} + + .endfunc + +// ======== __aeabi_uidiv & __aeabi_uidivmod ======== + .align 2 + + .section .text.__aeabi_uidiv + + .global __aeabi_uidiv + .set __aeabi_uidivmod, __aeabi_uidiv // make __aeabi_uidivmod an alias + .global __aeabi_uidivmod + .global pDivRom_uidiv // pointer to the romdivide 'uidiv' function + .func + .thumb_func + .type __aeabi_uidiv, %function + +__aeabi_uidiv: + push {r4, lr} + ldr r3, =pDivRom_uidiv + ldr r3, [r3, #0] // Load address of function + blx r3 // Call divide function + pop {r4, pc} + + .endfunc + +#endif // (__USE_ROMDIVIDE) diff --git a/source/freertos_blinky/example/src/cr_startup_lpc11u6x.c b/source/freertos_blinky/example/src/cr_startup_lpc11u6x.c new file mode 100644 index 0000000..a9a3fd4 --- /dev/null +++ b/source/freertos_blinky/example/src/cr_startup_lpc11u6x.c @@ -0,0 +1,352 @@ +//***************************************************************************** +// LPC11U6x Microcontroller Startup code for use with LPCXpresso IDE +// +// Version : 140113 +//***************************************************************************** +// +// Copyright(C) NXP Semiconductors, 2014 +// All rights reserved. +// +// Software that is described herein is for illustrative purposes only +// which provides customers with programming information regarding the +// LPC products. This software is supplied "AS IS" without any warranties of +// any kind, and NXP Semiconductors and its licensor disclaim any and +// all warranties, express or implied, including all implied warranties of +// merchantability, fitness for a particular purpose and non-infringement of +// intellectual property rights. NXP Semiconductors assumes no responsibility +// or liability for the use of the software, conveys no license or rights under any +// patent, copyright, mask work right, or any other intellectual property rights in +// or to any products. NXP Semiconductors reserves the right to make changes +// in the software without notification. NXP Semiconductors also makes no +// representation or warranty that such application will be suitable for the +// specified use without further testing or modification. +// +// Permission to use, copy, modify, and distribute this software and its +// documentation is hereby granted, under NXP Semiconductors' and its +// licensor's relevant copyrights in the software, without fee, provided that it +// is used in conjunction with NXP Semiconductors microcontrollers. This +// copyright, permission, and disclaimer notice must appear in all copies of +// this code. +//***************************************************************************** + +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#else +//***************************************************************************** +// +// The entry point for the C++ library startup +// +//***************************************************************************** +extern "C" { + extern void __libc_init_array(void); +} +#endif +#endif + +#define WEAK __attribute__ ((weak)) +#define ALIAS(f) __attribute__ ((weak, alias (#f))) + +//***************************************************************************** +#if defined (__cplusplus) +extern "C" { +#endif + +//***************************************************************************** +#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN) +// Declaration of external SystemInit function +extern void SystemInit(void); +#endif + +// Patch the AEABI integer divide functions to use MCU's romdivide library +#ifdef __USE_ROMDIVIDE +// Location in memory that holds the address of the ROM Driver table +#define PTR_ROM_DRIVER_TABLE ((unsigned int *)(0x1FFF1FF8)) +// Variables to store addresses of idiv and udiv functions within MCU ROM +unsigned int *pDivRom_idiv; +unsigned int *pDivRom_uidiv; +#endif + +//***************************************************************************** +// +// Forward declaration of the default handlers. These are aliased. +// When the application defines a handler (with the same name), this will +// automatically take precedence over these weak definitions +// +//***************************************************************************** + void ResetISR(void); +WEAK void NMI_Handler(void); +WEAK void HardFault_Handler(void); +WEAK void SVC_Handler(void); +WEAK void PendSV_Handler(void); +WEAK void SysTick_Handler(void); +WEAK void IntDefaultHandler(void); +//***************************************************************************** +// +// Forward declaration of the specific IRQ handlers. These are aliased +// to the IntDefaultHandler, which is a 'forever' loop. When the application +// defines a handler (with the same name), this will automatically take +// precedence over these weak definitions +// +//***************************************************************************** +void PIN_INT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT2_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT3_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT4_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT5_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT6_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT7_IRQHandler (void) ALIAS(IntDefaultHandler); +void GINT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void GINT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void I2C1_IRQHandler (void) ALIAS(IntDefaultHandler); +void USART1_4_IRQHandler (void) ALIAS(IntDefaultHandler); +void USART2_3_IRQHandler (void) ALIAS(IntDefaultHandler); +void SCT0_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP1_IRQHandler (void) ALIAS(IntDefaultHandler); +void I2C0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP0_IRQHandler (void) ALIAS(IntDefaultHandler); +void USART0_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_FIQHandler (void) ALIAS(IntDefaultHandler); +void ADCA_IRQHandler (void) ALIAS(IntDefaultHandler); +void RTC_IRQHandler (void) ALIAS(IntDefaultHandler); +void BOD_WDT_IRQHandler (void) ALIAS(IntDefaultHandler); +void FMC_IRQHandler (void) ALIAS(IntDefaultHandler); +void DMA_IRQHandler (void) ALIAS(IntDefaultHandler); +void ADCB_IRQHandler (void) ALIAS(IntDefaultHandler); +void USBWakeup_IRQHandler (void) ALIAS(IntDefaultHandler); + +//***************************************************************************** +// The entry point for the application. +// __main() is the entry point for redlib based applications +// main() is the entry point for newlib based applications +//***************************************************************************** +#if defined (__REDLIB__) +extern void __main(void); +#endif +extern int main(void); +//***************************************************************************** +// +// External declaration for the pointer to the stack top from the Linker Script +// +//***************************************************************************** +extern void _vStackTop(void); + +//***************************************************************************** +#if defined (__cplusplus) +} // extern "C" +#endif +//***************************************************************************** +// +// The vector table. Note that the proper constructs must be placed on this to +// ensure that it ends up at physical address 0x0000.0000. +// +//***************************************************************************** +extern void (* const g_pfnVectors[])(void); +__attribute__ ((section(".isr_vector"))) +void (* const g_pfnVectors[])(void) = { + &_vStackTop, // The initial stack pointer + ResetISR, // The reset handler + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler + 0, // Reserved + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler + + // LPC11U6x specific handlers + PIN_INT0_IRQHandler, // 0 - GPIO pin interrupt 0 + PIN_INT1_IRQHandler, // 1 - GPIO pin interrupt 1 + PIN_INT2_IRQHandler, // 2 - GPIO pin interrupt 2 + PIN_INT3_IRQHandler, // 3 - GPIO pin interrupt 3 + PIN_INT4_IRQHandler, // 4 - GPIO pin interrupt 4 + PIN_INT5_IRQHandler, // 5 - GPIO pin interrupt 5 + PIN_INT6_IRQHandler, // 6 - GPIO pin interrupt 6 + PIN_INT7_IRQHandler, // 7 - GPIO pin interrupt 7 + GINT0_IRQHandler, // 8 - GPIO GROUP0 interrupt + GINT1_IRQHandler, // 9 - GPIO GROUP1 interrupt + I2C1_IRQHandler, // 10 - I2C1 + USART1_4_IRQHandler, // 11 - combined USART1 & 4 interrupt + USART2_3_IRQHandler, // 12 - combined USART2 & 3 interrupt + SCT0_1_IRQHandler, // 13 - combined SCT0 and 1 interrupt + SSP1_IRQHandler, // 14 - SPI/SSP1 Interrupt + I2C0_IRQHandler, // 15 - I2C0 + TIMER16_0_IRQHandler, // 16 - CT16B0 (16-bit Timer 0) + TIMER16_1_IRQHandler, // 17 - CT16B1 (16-bit Timer 1) + TIMER32_0_IRQHandler, // 18 - CT32B0 (32-bit Timer 0) + TIMER32_1_IRQHandler, // 19 - CT32B1 (32-bit Timer 1) + SSP0_IRQHandler, // 20 - SPI/SSP0 Interrupt + USART0_IRQHandler, // 21 - USART0 + USB_IRQHandler, // 22 - USB IRQ + USB_FIQHandler, // 23 - USB FIQ + ADCA_IRQHandler, // 24 - ADC A(A/D Converter) + RTC_IRQHandler, // 25 - Real Time CLock interrpt + BOD_WDT_IRQHandler, // 25 - Combined Brownout/Watchdog interrupt + FMC_IRQHandler, // 27 - IP2111 Flash Memory Controller + DMA_IRQHandler, // 28 - DMA interrupt + ADCB_IRQHandler, // 24 - ADC B (A/D Converter) + USBWakeup_IRQHandler, // 30 - USB wake-up interrupt + 0, // 31 - Reserved +}; + +//***************************************************************************** +// Functions to carry out the initialization of RW and BSS data sections. These +// are written as separate functions rather than being inlined within the +// ResetISR() function in order to cope with MCUs with multiple banks of +// memory. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void data_init(unsigned int romstart, unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int *pulSrc = (unsigned int*) romstart; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = *pulSrc++; +} + +__attribute__ ((section(".after_vectors"))) +void bss_init(unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = 0; +} + +//***************************************************************************** +// The following symbols are constructs generated by the linker, indicating +// the location of various points in the "Global Section Table". This table is +// created by the linker via the Code Red managed linker script mechanism. It +// contains the load address, execution address and length of each RW data +// section and the execution and length of each BSS (zero initialized) section. +//***************************************************************************** +extern unsigned int __data_section_table; +extern unsigned int __data_section_table_end; +extern unsigned int __bss_section_table; +extern unsigned int __bss_section_table_end; + +//***************************************************************************** +// Reset entry point for your code. +// Sets up a simple runtime environment and initializes the C/C++ +// library. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void +ResetISR(void) { + + // Optionally enable RAM banks that may be off by default at reset +#if !defined (DONT_ENABLE_DISABLED_RAMBANKS) + volatile unsigned int *SYSCON_SYSAHBCLKCTRL = (unsigned int *) 0x40048080; + // Ensure that RAM1(26) and USBSRAM(27) bits in SYSAHBCLKCTRL are set + *SYSCON_SYSAHBCLKCTRL |= (1 << 26) | (1 <<27); +#endif + + // + // Copy the data sections from flash to SRAM. + // + unsigned int LoadAddr, ExeAddr, SectionLen; + unsigned int *SectionTableAddr; + + // Load base address of Global Section Table + SectionTableAddr = &__data_section_table; + + // Copy the data sections from flash to SRAM. + while (SectionTableAddr < &__data_section_table_end) { + LoadAddr = *SectionTableAddr++; + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + data_init(LoadAddr, ExeAddr, SectionLen); + } + // At this point, SectionTableAddr = &__bss_section_table; + // Zero fill the bss segment + while (SectionTableAddr < &__bss_section_table_end) { + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + bss_init(ExeAddr, SectionLen); + } + + // Patch the AEABI integer divide functions to use MCU's romdivide library +#ifdef __USE_ROMDIVIDE + // Get address of Integer division routines function table in ROM + unsigned int *div_ptr = (unsigned int *)((unsigned int *)*(PTR_ROM_DRIVER_TABLE))[4]; + // Get addresses of integer divide routines in ROM + // These address are then used by the code in aeabi_romdiv_patch.s + pDivRom_idiv = (unsigned int *)div_ptr[0]; + pDivRom_uidiv = (unsigned int *)div_ptr[1]; +#endif + +#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN) + SystemInit(); +#endif + +#if defined (__cplusplus) + // + // Call C++ library initialisation + // + __libc_init_array(); +#endif + +#if defined (__REDLIB__) + // Call the Redlib library, which in turn calls main() + __main() ; +#else + main(); +#endif + // + // main() shouldn't return, but if it does, we'll just enter an infinite loop + // + while (1) { + ; + } +} + +//***************************************************************************** +// Default exception handlers. Override the ones here by defining your own +// handler routines in your application code. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void NMI_Handler(void) +{ while(1) { } +} +__attribute__ ((section(".after_vectors"))) +void HardFault_Handler(void) +{ while(1) { } +} + +__attribute__ ((section(".after_vectors"))) +void SVC_Handler(void) +{ while(1) { } +} + +__attribute__ ((section(".after_vectors"))) +void PendSV_Handler(void) +{ while(1) { } +} + +__attribute__ ((section(".after_vectors"))) +void SysTick_Handler(void) +{ while(1) { } +} + +//***************************************************************************** +// +// Processor ends up here if an unexpected interrupt occurs or a specific +// handler is not present in the application code. +// +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void IntDefaultHandler(void) +{ while(1) { } +} diff --git a/source/freertos_blinky/example/src/crp.c b/source/freertos_blinky/example/src/crp.c new file mode 100644 index 0000000..5bbb587 --- /dev/null +++ b/source/freertos_blinky/example/src/crp.c @@ -0,0 +1,14 @@ +/* + * crp.c + * Source file to create CRP word expected by Code Red linker + */ + +#ifdef __CODE_RED +#include + +// Variable to store CRP value in. Will be placed automatically +// by the linker when "Enable Code Read Protect" selected. +// See crp.h header for more information +__CRP const unsigned int CRP_WORD = CRP_NO_CRP ; + +#endif diff --git a/source/freertos_blinky/example/src/freertos_blinky.c b/source/freertos_blinky/example/src/freertos_blinky.c new file mode 100644 index 0000000..05d31d5 --- /dev/null +++ b/source/freertos_blinky/example/src/freertos_blinky.c @@ -0,0 +1,120 @@ +/* + * @brief FreeRTOS Blinky example + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "board.h" +#include "FreeRTOS.h" +#include "task.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Sets up system hardware */ +static void prvSetupHardware(void) +{ + SystemCoreClockUpdate(); + Board_Init(); +} + +/* LED0 toggle thread */ +static void vLEDTask0(void *pvParameters) { + bool LedState = false; + while (1) { + Board_LED_Set(0, LedState); + LedState = (bool) !LedState; + + vTaskDelay(configTICK_RATE_HZ / 2); + } +} + +/* LED1 toggle thread */ +static void vLEDTask1(void *pvParameters) { + bool LedState = false; + while (1) { + Board_LED_Set(1, LedState); + LedState = (bool) !LedState; + + vTaskDelay(configTICK_RATE_HZ * 2); + } +} + +/* LED2 toggle thread */ +static void vLEDTask2(void *pvParameters) { + bool LedState = false; + while (1) { + Board_LED_Set(2, LedState); + LedState = (bool) !LedState; + + vTaskDelay(configTICK_RATE_HZ); + } +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/** + * @brief main routine for FreeRTOS blinky example + * @return Nothing, function should not exit + */ +int main(void) +{ + prvSetupHardware(); + + /* LED1 toggle thread */ + xTaskCreate(vLEDTask1, (signed char *) "vTaskLed1", + configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL), + (xTaskHandle *) NULL); + + /* LED2 toggle thread */ + xTaskCreate(vLEDTask2, (signed char *) "vTaskLed2", + configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL), + (xTaskHandle *) NULL); + + /* LED0 toggle thread */ + xTaskCreate(vLEDTask0, (signed char *) "vTaskLed0", + configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 1UL), + (xTaskHandle *) NULL); + + /* Start the scheduler */ + vTaskStartScheduler(); + + /* Should never arrive here */ + return 1; +} diff --git a/source/freertos_blinky/example/src/mtb.c b/source/freertos_blinky/example/src/mtb.c new file mode 100644 index 0000000..4a65389 --- /dev/null +++ b/source/freertos_blinky/example/src/mtb.c @@ -0,0 +1,86 @@ +//***************************************************************************** +// +--+ +// | ++----+ +// +-++ | +// | | +// +-+--+ | +// | +--+--+ +// +----+ Copyright (c) 2013 Code Red Technologies Ltd. +// +// mtb.c +// +// Optionally defines an array to be used as a buffer for Micro Trace +// Buffer (MTB) instruction trace on Cortex-M0+ parts +// +// Version : 130502 +// +// Software License Agreement +// +// The software is owned by Code Red Technologies and/or its suppliers, and is +// protected under applicable copyright laws. All rights are reserved. Any +// use in violation of the foregoing restrictions may subject the user to criminal +// sanctions under applicable laws, as well as to civil liability for the breach +// of the terms and conditions of this license. +// +// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT +// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH +// CODE RED TECHNOLOGIES LTD. +// +//***************************************************************************** + +/******************************************************************* + * Symbols controlling behavior of this code... + * + * __MTB_DISABLE + * If this symbol is defined, then the buffer array for the MTB + * will not be created. + * + * __MTB_BUFFER_SIZE + * Symbol specifying the sizer of the buffer array for the MTB. + * This must be a power of 2 in size, and fit into the available + * RAM. The MTB buffer will also be aligned to its 'size' + * boundary and be placed at the start of a RAM bank (which + * should ensure minimal or zero padding due to alignment). + * + * __MTB_RAM_BANK + * Allows MTB Buffer to be placed into specific RAM bank. When + * this is not defined, the "default" (first if there are + * several) RAM bank is used. + *******************************************************************/ + +// Ignore with none Code Red tools +#if defined (__CODE_RED) + +// Allow MTB to be removed by setting a define (via command line) +#if !defined (__MTB_DISABLE) + + // Allow for MTB buffer size being set by define set via command line + // Otherwise provide small default buffer + #if !defined (__MTB_BUFFER_SIZE) + #define __MTB_BUFFER_SIZE 128 + #endif + + // Check that buffer size requested is >0 bytes in size + #if (__MTB_BUFFER_SIZE > 0) + // Pull in MTB related macros + #include + + // Check if MYTB buffer is to be placed in specific RAM bank + #if defined(__MTB_RAM_BANK) + // Place MTB buffer into explicit bank of RAM + __CR_MTB_BUFFER_EXT(__MTB_BUFFER_SIZE,__MTB_RAM_BANK); + #else + // Place MTB buffer into 'default' bank of RAM + __CR_MTB_BUFFER(__MTB_BUFFER_SIZE); + + #endif // defined(__MTB_RAM_BANK) + + #endif // (__MTB_BUFFER_SIZE > 0) + +#endif // !defined (__MTB_DISABLE) + +#endif // defined (__CODE_RED) + diff --git a/source/freertos_blinky/example/src/sysinit.c b/source/freertos_blinky/example/src/sysinit.c new file mode 100644 index 0000000..65dcf24 --- /dev/null +++ b/source/freertos_blinky/example/src/sysinit.c @@ -0,0 +1,60 @@ +/* + * @brief Common SystemInit function for LPC11u6x chips + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + + #include "board.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Set up and initialize hardware prior to call to main */ +void SystemInit(void) +{ +#if defined(NO_BOARD_LIB) + /* Chip specific SystemInit */ + Chip_SystemInit(); +#else + /* Setup system clocking and muxing */ + Board_SystemInit(); +#endif +} diff --git a/source/freertos_blinky/freertos/inc/FreeRTOS.h b/source/freertos_blinky/freertos/inc/FreeRTOS.h new file mode 100644 index 0000000..d2e6904 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/FreeRTOS.h @@ -0,0 +1,621 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* configUSE_PORT_OPTIMISED_TASK_SELECTION must be defined before portable.h +is included as it is used by the port layer. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +/* Definitions specific to the port being used. */ +#include "portable.h" + + +/* Defines the prototype to which the application task hook function must +conform. */ +typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); + + + + + +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_CO_ROUTINES + #error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelete + #error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskSuspend + #error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelay + #error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS + #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle + #define INCLUDE_xTaskGetIdleTaskHandle 0 +#endif + +#ifndef INCLUDE_xTimerGetTimerDaemonTaskHandle + #define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#endif + +#ifndef INCLUDE_xQueueGetMutexHolder + #define INCLUDE_xQueueGetMutexHolder 0 +#endif + +#ifndef INCLUDE_xSemaphoreGetMutexHolder + #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder +#endif + +#ifndef INCLUDE_pcTaskGetTaskName + #define INCLUDE_pcTaskGetTaskName 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef INCLUDE_eTaskGetState + #define INCLUDE_eTaskGetState 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS + #define configUSE_TIMERS 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef configASSERT + #define configASSERT( x ) + #define configASSERT_DEFINED 0 +#else + #define configASSERT_DEFINED 1 +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + + #ifndef configTIMER_TASK_PRIORITY + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. + #endif /* configTIMER_TASK_PRIORITY */ + + #ifndef configTIMER_QUEUE_LENGTH + #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. + #endif /* configTIMER_QUEUE_LENGTH */ + + #ifndef configTIMER_TASK_STACK_DEPTH + #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. + #endif /* configTIMER_TASK_STACK_DEPTH */ + +#endif /* configUSE_TIMERS */ + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#endif + +#ifndef portCLEAN_UP_TCB + #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef portSETUP_TCB + #define portSETUP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) +#endif + +#ifndef portPOINTER_SIZE_TYPE + #define portPOINTER_SIZE_TYPE unsigned long +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART + /* Used to perform any necessary initialisation - for example, open a file + into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + /* Use to close a trace, for example close a file into which trace has been + written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + /* Called after a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceINCREASE_TICK_COUNT + /* Called before stepping the tick count after waking from tickless idle + sleep. */ + #define traceINCREASE_TICK_COUNT( x ) +#endif + +#ifndef traceLOW_POWER_IDLE_BEGIN + /* Called immediately before entering tickless idle. */ + #define traceLOW_POWER_IDLE_BEGIN() +#endif + +#ifndef traceLOW_POWER_IDLE_END + /* Called when returning to the Idle task after a tickless idle. */ + #define traceLOW_POWER_IDLE_END() +#endif + +#ifndef traceTASK_SWITCHED_OUT + /* Called before a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceTASK_PRIORITY_INHERIT + /* Called when a task attempts to take a mutex that is already held by a + lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task + that holds the mutex. uxInheritedPriority is the priority the mutex holder + will inherit (the priority of the task that is attempting to obtain the + muted. */ + #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) +#endif + +#ifndef traceTASK_PRIORITY_DISINHERIT + /* Called when a task releases a mutex, the holding of which had resulted in + the task inheriting the priority of a higher priority task. + pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the + mutex. uxOriginalPriority is the task's configured (base) priority. */ + #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + /* Task is about to block because it cannot read from a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the read was attempted. pxCurrentTCB points to the TCB of the + task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + /* Task is about to block because it cannot write to a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the write was attempted. pxCurrentTCB points to the TCB of the + task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceMOVED_TASK_TO_READY_STATE + #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED( ucQueueType ) +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED + #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR + #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED + #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL() +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE + #define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED + #define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND + #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED + #define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED + #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef traceMALLOC + #define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE + #define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. + #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT + #define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API + #define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef pvPortMallocAligned + #define pvPortMallocAligned( x, puxStackBuffer ) ( ( ( puxStackBuffer ) == NULL ) ? ( pvPortMalloc( ( x ) ) ) : ( puxStackBuffer ) ) +#endif + +#ifndef vPortFreeAligned + #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree ) +#endif + +#ifndef portSUPPRESS_TICKS_AND_SLEEP + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) +#endif + +#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP + #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 +#endif + +#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 + #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 +#endif + +#ifndef configUSE_TICKLESS_IDLE + #define configUSE_TICKLESS_IDLE 0 +#endif + +#ifndef configPRE_SLEEP_PROCESSING + #define configPRE_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPOST_SLEEP_PROCESSING + #define configPOST_SLEEP_PROCESSING( x ) +#endif + +#ifndef configUSE_QUEUE_SETS + #define configUSE_QUEUE_SETS 0 +#endif + +#ifndef portTASK_USES_FLOATING_POINT + #define portTASK_USES_FLOATING_POINT() +#endif + +#ifndef configUSE_TIME_SLICING + #define configUSE_TIME_SLICING 1 +#endif + +#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS + #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 +#endif + +#ifndef configUSE_NEWLIB_REENTRANT + #define configUSE_NEWLIB_REENTRANT 0 +#endif + +#ifndef configUSE_STATS_FORMATTING_FUNCTIONS + #define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#endif + +#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() +#endif + +/* For backward compatability. */ +#define eTaskStateGet eTaskGetState + +#endif /* INC_FREERTOS_H */ + diff --git a/source/freertos_blinky/freertos/inc/StackMacros.h b/source/freertos_blinky/freertos/inc/StackMacros.h new file mode 100644 index 0000000..9c51c70 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/StackMacros.h @@ -0,0 +1,180 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef STACK_MACROS_H +#define STACK_MACROS_H + +/* + * Call the stack overflow hook function if the stack of the task being swapped + * out is currently overflowed, or looks like it might have overflowed in the + * past. + * + * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check + * the current stack state only - comparing the current top of stack value to + * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 + * will also cause the last few stack bytes to be checked to ensure the value + * to which the bytes were set when the task was created have not been + * overwritten. Note this second test does not guarantee that an overflowed + * stack will always be recognised. + */ + +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) + + /* FreeRTOSConfig.h is not set to check for stack overflows. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) + + /* FreeRTOSConfig.h is only set to use the first method of + overflow checking. */ + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack; \ + static const unsigned char ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#endif /* STACK_MACROS_H */ + diff --git a/source/freertos_blinky/freertos/inc/croutine.h b/source/freertos_blinky/freertos/inc/croutine.h new file mode 100644 index 0000000..85d7bf3 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/croutine.h @@ -0,0 +1,758 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef CO_ROUTINE_H +#define CO_ROUTINE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include croutine.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to hide the implementation of the co-routine control block. The +control block structure however has to be included in the header due to +the macro implementation of the co-routine functionality. */ +typedef void * xCoRoutineHandle; + +/* Defines the prototype to which co-routine functions must conform. */ +typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); + +typedef struct corCoRoutineControlBlock +{ + crCOROUTINE_CODE pxCoRoutineFunction; + xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ + unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + unsigned short uxState; /*< Used internally by the co-routine implementation. */ +} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ + +/** + * croutine. h + *
+ portBASE_TYPE xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 unsigned portBASE_TYPE uxPriority,
+                                 unsigned portBASE_TYPE uxIndex
+                               );
+ * + * Create a new co-routine and add it to the list of co-routines that are + * ready to run. + * + * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine + * functions require special syntax - see the co-routine section of the WEB + * documentation for more information. + * + * @param uxPriority The priority with respect to other co-routines at which + * the co-routine will run. + * + * @param uxIndex Used to distinguish between different co-routines that + * execute the same function. See the example below and the co-routine section + * of the WEB documentation for further information. + * + * @return pdPASS if the co-routine was successfully created and added to a ready + * list, otherwise an error code defined with ProjDefs.h. + * + * Example usage: +
+ // Co-routine to be created.
+ void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how long to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+		
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   
+ * \defgroup xCoRoutineCreate xCoRoutineCreate + * \ingroup Tasks + */ +signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); + + +/** + * croutine. h + *
+ void vCoRoutineSchedule( void );
+ * + * Run a co-routine. + * + * vCoRoutineSchedule() executes the highest priority co-routine that is able + * to run. The co-routine will execute until it either blocks, yields or is + * preempted by a task. Co-routines execute cooperatively so one + * co-routine cannot be preempted by another, but can be preempted by a task. + * + * If an application comprises of both tasks and co-routines then + * vCoRoutineSchedule should be called from the idle task (in an idle task + * hook). + * + * Example usage: +
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ 
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * \ingroup Tasks + */ +void vCoRoutineSchedule( void ); + +/** + * croutine. h + *
+ crSTART( xCoRoutineHandle xHandle );
+ * + * This macro MUST always be called at the start of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static long ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crSTART( pxCRCB ) switch( ( ( corCRCB * )( pxCRCB ) )->uxState ) { case 0: + +/** + * croutine. h + *
+ crEND();
+ * + * This macro MUST always be called at the end of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static long ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crEND() } + +/* + * These macros are intended for internal use by the co-routine implementation + * only. The macros should not be used directly by application writers. + */ +#define crSET_STATE0( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): +#define crSET_STATE1( xHandle ) ( ( corCRCB * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): + +/** + * croutine. h + *
+ crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );
+ * + * Delay a co-routine for a fixed period of time. + * + * crDELAY can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * @param xHandle The handle of the co-routine to delay. This is the xHandle + * parameter of the co-routine function. + * + * @param xTickToDelay The number of ticks that the co-routine should delay + * for. The actual amount of time this equates to is defined by + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS + * can be used to convert ticks to milliseconds. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crDELAY crDELAY + * \ingroup Tasks + */ +#define crDELAY( xHandle, xTicksToDelay ) \ + if( ( xTicksToDelay ) > 0 ) \ + { \ + vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \ + } \ + crSET_STATE0( ( xHandle ) ); + +/** + *
+ crQUEUE_SEND(
+                  xCoRoutineHandle xHandle,
+                  xQueueHandle pxQueue,
+                  void *pvItemToQueue,
+                  portTickType xTicksToWait,
+                  portBASE_TYPE *pxResult
+             )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_SEND can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue on which the data will be posted. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvItemToQueue A pointer to the data being posted onto the queue. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied from pvItemToQueue into the queue + * itself. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for space to become available on the queue, should space not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example + * below). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully posted onto the queue, otherwise it will be set to an + * error defined within ProjDefs.h. + * + * Example usage: +
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xNumberToPost = 0;
+ static portBASE_TYPE xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }
+ * \defgroup crQUEUE_SEND crQUEUE_SEND + * \ingroup Tasks + */ +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_RECEIVE(
+                     xCoRoutineHandle xHandle,
+                     xQueueHandle pxQueue,
+                     void *pvBuffer,
+                     portTickType xTicksToWait,
+                     portBASE_TYPE *pxResult
+                 )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_RECEIVE can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue from which the data will be received. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvBuffer The buffer into which the received item is to be copied. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied into pvBuffer. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for data to become available from the queue, should data not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the + * crQUEUE_SEND example). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully retrieved from the queue, otherwise it will be set to + * an error code as defined within ProjDefs.h. + * + * Example usage: +
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xResult;
+ static unsigned portBASE_TYPE uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ +{ \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \ + if( *( pxResult ) == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( ( xHandle ) ); \ + *( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \ + } \ + if( *( pxResult ) == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( ( xHandle ) ); \ + *( pxResult ) = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            xQueueHandle pxQueue,
+                            void *pvItemToQueue,
+                            portBASE_TYPE xCoRoutinePreviouslyWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue + * that is being used from within a co-routine. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto + * the same queue multiple times from a single interrupt. The first call + * should always pass in pdFALSE. Subsequent calls should pass in + * the value returned from the previous call. + * + * @return pdTRUE if a co-routine was woken by posting onto the queue. This is + * used by the ISR to determine if a context switch may be required following + * the ISR. + * + * Example usage: +
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ char cRxedChar;
+ portBASE_TYPE xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ char cRxedChar;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) ) + + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            xQueueHandle pxQueue,
+                            void *pvBuffer,
+                            portBASE_TYPE * pxCoRoutineWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data + * from a queue that is being used from within a co-routine (a co-routine + * posted to the queue). + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvBuffer A pointer to a buffer into which the received item will be + * placed. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from the queue into + * pvBuffer. + * + * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become + * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a + * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise + * *pxCoRoutineWoken will remain unchanged. + * + * @return pdTRUE an item was successfully received from the queue, otherwise + * pdFALSE. + * + * Example usage: +
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static char cCharToTx = 'a';
+ portBASE_TYPE xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ char cCharToTx;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) ) + +/* + * This function is intended for internal use by the co-routine macros only. + * The macro nature of the co-routine implementation requires that the + * prototype appears here. The function should not be used by application + * writers. + * + * Removes the current co-routine from its ready list and places it in the + * appropriate delayed list. + */ +void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ); + +/* + * This function is intended for internal use by the queue implementation only. + * The function should not be used by application writers. + * + * Removes the highest priority co-routine from the event list and places it in + * the pending ready list. + */ +signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); + +#ifdef __cplusplus +} +#endif + +#endif /* CO_ROUTINE_H */ diff --git a/source/freertos_blinky/freertos/inc/list.h b/source/freertos_blinky/freertos/inc/list.h new file mode 100644 index 0000000..34e6809 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/list.h @@ -0,0 +1,379 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * xLists can only store pointers to xListItems. Each xListItem contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + + +#ifndef LIST_H +#define LIST_H + +/* + * The list structure members are modified from within interrupts, and therefore + * by rights should be declared volatile. However, they are only modified in a + * functionally atomic way (within critical sections of with the scheduler + * suspended) and are either passed by reference into a function or indexed via + * a volatile variable. Therefore, in all use cases tested so far, the volatile + * qualifier can be omitted in order to provide a moderate performance + * improvement without adversely affecting functional behaviour. The assembly + * instructions generated by the IAR, ARM and GCC compilers when the respective + * compiler's options were set for maximum optimisation has been inspected and + * deemed to be as intended. That said, as compiler technology advances, and + * especially if aggressive cross module optimisation is used (a use case that + * has not been exercised to any great extend) then it is feasible that the + * volatile qualifier will be needed for correct optimisation. It is expected + * that a compiler removing essential code because, without the volatile + * qualifier on the list structure members and with aggressive cross module + * optimisation, the compiler deemed the code unnecessary will result in + * complete and obvious failure of the scheduler. If this is ever experienced + * then the volatile qualifier can be inserted in the relevant places within the + * list structures by simply defining configLIST_VOLATILE to volatile in + * FreeRTOSConfig.h (as per the example at the bottom of this comment block). + * If configLIST_VOLATILE is not defined then the preprocessor directives below + * will simply #define configLIST_VOLATILE away completely. + * + * To use volatile list structure members then add the following line to + * FreeRTOSConfig.h (without the quotes): + * "#define configLIST_VOLATILE volatile" + */ +#ifndef configLIST_VOLATILE + #define configLIST_VOLATILE +#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM +{ + configLIST_VOLATILE portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next xListItem in the list. */ + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;/*< Pointer to the previous xListItem in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ +}; +typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM +{ + configLIST_VOLATILE portTickType xItemValue; + struct xLIST_ITEM * configLIST_VOLATILE pxNext; + struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; +}; +typedef struct xMINI_LIST_ITEM xMiniListItem; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST +{ + configLIST_VOLATILE unsigned portBASE_TYPE uxNumberOfItems; + xListItem * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ + xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ +} xList; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) + +/* + * Access macro to get the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( pxListItem )->pvOwner + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) + +/* + * Access macro to retrieve the value of the list item. The value can + * represent anything - for example a the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro the retrieve the value of the list item at the head of a given + * list. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->xItemValue ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( portBASE_TYPE ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entries pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +xList * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE is the list item is in the list, otherwise pdFALSE. + * pointer against + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( portBASE_TYPE ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) + +/* + * Return the list a list item is contained within (referenced from). + * + * @param pxListItem The list item being queried. + * @return A pointer to the xList object that references the pxListItem + */ +#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) + +/* + * This provides a crude means of knowing if a list has been initialised, as + * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() + * function. + */ +#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise( xList * const pxList ); + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem( xListItem * const pxItem ); + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item to that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert( xList * const pxList, xListItem * const pxNewListItem ); + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pvIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pvIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pvIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ); + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param uxListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * @return The number of items that remain in the list after the list item has + * been removed. + * + * \page uxListRemove uxListRemove + * \ingroup LinkedList + */ +unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/freertos_blinky/freertos/inc/mpu_wrappers.h b/source/freertos_blinky/freertos/inc/mpu_wrappers.h new file mode 100644 index 0000000..149ca0a --- /dev/null +++ b/source/freertos_blinky/freertos/inc/mpu_wrappers.h @@ -0,0 +1,153 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef MPU_WRAPPERS_H +#define MPU_WRAPPERS_H + +/* This file redefines API functions to be called through a wrapper macro, but +only for ports that are using the MPU. */ +#ifdef portUSING_MPU_WRAPPERS + + /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is + included from queue.c or task.c to prevent it from having an effect within + those files. */ + #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + + #define xTaskGenericCreate MPU_xTaskGenericCreate + #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions + #define vTaskDelete MPU_vTaskDelete + #define vTaskDelayUntil MPU_vTaskDelayUntil + #define vTaskDelay MPU_vTaskDelay + #define uxTaskPriorityGet MPU_uxTaskPriorityGet + #define vTaskPrioritySet MPU_vTaskPrioritySet + #define eTaskGetState MPU_eTaskGetState + #define vTaskSuspend MPU_vTaskSuspend + #define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended + #define vTaskResume MPU_vTaskResume + #define vTaskSuspendAll MPU_vTaskSuspendAll + #define xTaskResumeAll MPU_xTaskResumeAll + #define xTaskGetTickCount MPU_xTaskGetTickCount + #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks + #define vTaskList MPU_vTaskList + #define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats + #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag + #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag + #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook + #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark + #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle + #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle + #define uxTaskGetSystemState MPU_uxTaskGetSystemState + + #define xQueueGenericCreate MPU_xQueueGenericCreate + #define xQueueCreateMutex MPU_xQueueCreateMutex + #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive + #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive + #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore + #define xQueueGenericSend MPU_xQueueGenericSend + #define xQueueAltGenericSend MPU_xQueueAltGenericSend + #define xQueueAltGenericReceive MPU_xQueueAltGenericReceive + #define xQueueGenericReceive MPU_xQueueGenericReceive + #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting + #define vQueueDelete MPU_vQueueDelete + #define xQueueGenericReset MPU_xQueueGenericReset + #define xQueueCreateSet MPU_xQueueCreateSet + #define xQueueSelectFromSet MPU_xQueueSelectFromSet + #define xQueueAddToSet MPU_xQueueAddToSet + #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet + #define xQueuePeekFromISR MPU_xQueuePeekFromISR + + #define pvPortMalloc MPU_pvPortMalloc + #define vPortFree MPU_vPortFree + #define xPortGetFreeHeapSize MPU_xPortGetFreeHeapSize + #define vPortInitialiseBlocks MPU_vPortInitialiseBlocks + + #if configQUEUE_REGISTRY_SIZE > 0 + #define vQueueAddToRegistry MPU_vQueueAddToRegistry + #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue + #endif + + /* Remove the privileged function macro. */ + #define PRIVILEGED_FUNCTION + + #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + + /* Ensure API functions go in the privileged execution section. */ + #define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) + + #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +#else /* portUSING_MPU_WRAPPERS */ + + #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA + #define portUSING_MPU_WRAPPERS 0 + +#endif /* portUSING_MPU_WRAPPERS */ + + +#endif /* MPU_WRAPPERS_H */ + diff --git a/source/freertos_blinky/freertos/inc/portable.h b/source/freertos_blinky/freertos/inc/portable.h new file mode 100644 index 0000000..8df01d1 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/portable.h @@ -0,0 +1,402 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Include the macro file relevant to the port being used. */ + +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef GCC_MEGA_AVR + #include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR + #include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT + #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT + #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT + #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT + #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" +#endif + +#ifdef _FEDPICC + #include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +#ifdef GCC_ARM7 + #include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +#endif + +#ifdef GCC_ARM7_ECLIPSE + #include "portmacro.h" +#endif + +#ifdef ROWLEY_LPC23xx + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" +#endif + +#ifdef IAR_MSP430 + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S + #include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 + #include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 + #include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef __GNUC__ + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif +#endif + +#ifdef __ICCAVR32__ + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif +#endif + +#ifdef __91467D + #include "portmacro.h" +#endif + +#ifdef __96340 + #include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +/* Catch all to ensure portmacro.h is included in the build. Newer demos +have the path as part of the project options, rather than as relative from +the project location. If portENTER_CRITICAL() has not been defined then +portmacro.h has not yet been included - as every portmacro.h provides a +portENTER_CRITICAL() definition. Check the demo application for your demo +to find the path to the correct portmacro.h file. */ +#ifndef portENTER_CRITICAL + #include "portmacro.h" +#endif + +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#ifndef portNUM_CONFIGURABLE_REGIONS + #define portNUM_CONFIGURABLE_REGIONS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpu_wrappers.h" + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged ) PRIVILEGED_FUNCTION; +#else + portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) PRIVILEGED_FUNCTION; +#endif + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION; +void vPortFree( void *pv ) PRIVILEGED_FUNCTION; +void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; +size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +portBASE_TYPE xPortStartScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; + +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if( portUSING_MPU_WRAPPERS == 1 ) + struct xMEMORY_REGION; + void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + diff --git a/source/freertos_blinky/freertos/inc/portmacro.h b/source/freertos_blinky/freertos/inc/portmacro.h new file mode 100644 index 0000000..5e4fc64 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/portmacro.h @@ -0,0 +1,145 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE unsigned portLONG +#define portBASE_TYPE long + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ +extern void vPortYield( void ); +#define portNVIC_INT_CTRL_REG ( * ( ( volatile unsigned long * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portYIELD() vPortYield() +#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + + +/* Critical section management. */ +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); +extern unsigned long ulSetInterruptMaskFromISR( void ) __attribute__((naked)); +extern void vClearInterruptMaskFromISR( unsigned long ulMask ) __attribute__((naked)); + +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#define portNOP() + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/source/freertos_blinky/freertos/inc/projdefs.h b/source/freertos_blinky/freertos/inc/projdefs.h new file mode 100644 index 0000000..86ca641 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/projdefs.h @@ -0,0 +1,89 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* Defines the prototype to which task functions must conform. */ +typedef void (*pdTASK_CODE)( void * ); + +#define pdFALSE ( ( portBASE_TYPE ) 0 ) +#define pdTRUE ( ( portBASE_TYPE ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( portBASE_TYPE ) 0 ) +#define errQUEUE_FULL ( ( portBASE_TYPE ) 0 ) + +/* Error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errNO_TASK_TO_RUN ( -2 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +#endif /* PROJDEFS_H */ + + + diff --git a/source/freertos_blinky/freertos/inc/queue.h b/source/freertos_blinky/freertos/inc/queue.h new file mode 100644 index 0000000..6618330 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/queue.h @@ -0,0 +1,1685 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include queue.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Type by which queues are referenced. For example, a call to xQueueCreate() + * returns an xQueueHandle variable that can then be used as a parameter to + * xQueueSend(), xQueueReceive(), etc. + */ +typedef void * xQueueHandle; + +/** + * Type by which queue sets are referenced. For example, a call to + * xQueueCreateSet() returns an xQueueSet variable that can then be used as a + * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. + */ +typedef void * xQueueSetHandle; + +/** + * Queue sets can contain both queues and semaphores, so the + * xQueueSetMemberHandle is defined as a type to be used where a parameter or + * return value can be either an xQueueHandle or an xSemaphoreHandle. + */ +typedef void * xQueueSetMemberHandle; + +/* For internal use only. */ +#define queueSEND_TO_BACK ( ( portBASE_TYPE ) 0 ) +#define queueSEND_TO_FRONT ( ( portBASE_TYPE ) 1 ) +#define queueOVERWRITE ( ( portBASE_TYPE ) 2 ) + +/* For internal use only. These definitions *must* match those in queue.c. */ +#define queueQUEUE_TYPE_BASE ( ( unsigned char ) 0U ) +#define queueQUEUE_TYPE_SET ( ( unsigned char ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( unsigned char ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( unsigned char ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( unsigned char ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( unsigned char ) 4U ) + +/** + * queue. h + *
+ xQueueHandle xQueueCreate(
+							  unsigned portBASE_TYPE uxQueueLength,
+							  unsigned portBASE_TYPE uxItemSize
+						  );
+ * 
+ * + * Creates a new queue instance. This allocates the storage required by the + * new queue and returns a handle for the queue. + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+	if( xQueue1 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue2 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ +#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToToFront(
+								   xQueueHandle	xQueue,
+								   const void	*	pvItemToQueue,
+								   portTickType	xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToBack(
+								   xQueueHandle	xQueue,
+								   const	void	*	pvItemToQueue,
+								   portTickType	xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSend(
+							  xQueueHandle xQueue,
+							  const void * pvItemToQueue,
+							  portTickType xTicksToWait
+						 );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueOverwrite(
+							  xQueueHandle xQueue,
+							  const void * pvItemToQueue
+						 );
+ * 
+ * + * Only for use with queues that have a length of one - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * This function must not be called from an interrupt service routine. + * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle of the queue to which the data is being sent. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and + * therefore has the same return values as xQueueSendToFront(). However, pdPASS + * is the only value that can be returned because xQueueOverwrite() will write + * to the queue even when the queue is already full. + * + * Example usage: +
+
+ void vFunction( void *pvParameters )
+ {
+ xQueueHandle xQueue;
+ unsigned long ulVarToSend, ulValReceived;
+
+	// Create a queue to hold one unsigned long value.  It is strongly
+	// recommended *not* to use xQueueOverwrite() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
+
+	// Write the value 10 to the queue using xQueueOverwrite().
+	ulVarToSend = 10;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// Peeking the queue should now return 10, but leave the value 10 in
+	// the queue.  A block time of zero is used as it is known that the
+	// queue holds a value.
+	ulValReceived = 0;
+	xQueuePeek( xQueue, &ulValReceived, 0 );
+
+	if( ulValReceived != 10 )
+	{
+		// Error unless the item was removed by a different task.
+	}
+
+	// The queue is still full.  Use xQueueOverwrite() to overwrite the
+	// value held in the queue with 100.
+	ulVarToSend = 100;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// This time read from the queue, leaving the queue empty once more.
+	// A block time of 0 is used again.
+	xQueueReceive( xQueue, &ulValReceived, 0 );
+
+	// The value read should be the last value written, even though the
+	// queue was already full when the value was written.
+	if( ulValReceived != 100 )
+	{
+		// Error!
+	}
+
+	// ...
+}
+ 
+ * \defgroup xQueueOverwrite xQueueOverwrite + * \ingroup QueueManagement + */ +#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericSend(
+									xQueueHandle xQueue,
+									const void * pvItemToQueue,
+									portTickType xTicksToWait
+									portBASE_TYPE xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ unsigned long ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 unsigned long values.
+	xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an unsigned long.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ portBASE_TYPE xQueuePeek(
+							 xQueueHandle xQueue,
+							 void *pvBuffer,
+							 portTickType xTicksToWait
+						 );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. See + * xQueuePeekFromISR() for an alternative that can be called from an interrupt + * service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Peek a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask, but the item still remains on the queue.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/** + * queue. h + *
+ portBASE_TYPE xQueuePeekFromISR(
+									xQueueHandle xQueue,
+									void *pvBuffer,
+								);
+ * + * A version of xQueuePeek() that can be called from an interrupt service + * routine (ISR). + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ portBASE_TYPE xQueueReceive(
+								 xQueueHandle xQueue,
+								 void *pvBuffer,
+								 portTickType xTicksToWait
+							);
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_RATE_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericReceive(
+									   xQueueHandle	xQueue,
+									   void	*pvBuffer,
+									   portTickType	xTicksToWait
+									   portBASE_TYPE	xJustPeek
+									);
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue );
+ * + * Return the number of free spaces available in a queue. This is equal to the + * number of items that can be sent to the queue before the queue becomes full + * if no items are removed. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of spaces available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
void vQueueDelete( xQueueHandle xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \defgroup vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToFrontFromISR(
+										 xQueueHandle xQueue,
+										 const void *pvItemToQueue,
+										 portBASE_TYPE *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPrioritTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToBackFromISR(
+										 xQueueHandle xQueue,
+										 const void *pvItemToQueue,
+										 portBASE_TYPE *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueOverwriteFromISR(
+							  xQueueHandle xQueue,
+							  const void * pvItemToQueue,
+							  portBASE_TYPE *pxHigherPriorityTaskWoken
+						 );
+ * 
+ * + * A version of xQueueOverwrite() that can be used in an interrupt service + * routine (ISR). + * + * Only for use with queues that can hold a single item - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return xQueueOverwriteFromISR() is a macro that calls + * xQueueGenericSendFromISR(), and therefore has the same return values as + * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be + * returned because xQueueOverwriteFromISR() will write to the queue even when + * the queue is already full. + * + * Example usage: +
+
+ xQueueHandle xQueue;
+ 
+ void vFunction( void *pvParameters )
+ {
+ 	// Create a queue to hold one unsigned long value.  It is strongly
+	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( unsigned long ) );
+}
+
+void vAnInterruptHandler( void )
+{
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+unsigned long ulVarToSend, ulValReceived;
+
+	// Write the value 10 to the queue using xQueueOverwriteFromISR().
+	ulVarToSend = 10;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// The queue is full, but calling xQueueOverwriteFromISR() again will still
+	// pass because the value held in the queue will be overwritten with the
+	// new value.
+	ulVarToSend = 100;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// Reading from the queue will now return 100.
+
+	// ...
+	
+	if( xHigherPrioritytaskWoken == pdTRUE )
+	{
+		// Writing to the queue caused a task to unblock and the unblocked task
+		// has a priority higher than or equal to the priority of the currently
+		// executing task (the task this interrupt interrupted).  Perform a context
+		// switch so this interrupt returns directly to the unblocked task.
+		portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+	}
+}
+ 
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR + * \ingroup QueueManagement + */ +#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendFromISR(
+									 xQueueHandle xQueue,
+									 const void *pvItemToQueue,
+									 portBASE_TYPE *pxHigherPriorityTaskWoken
+								);
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		// Actual macro used here is port specific.
+		taskYIELD_FROM_ISR ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericSendFromISR(
+										   xQueueHandle		xQueue,
+										   const	void	*pvItemToQueue,
+										   portBASE_TYPE	*pxHigherPriorityTaskWoken,
+										   portBASE_TYPE	xCopyPosition
+									   );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ portBASE_TYPE xHigherPriorityTaskWokenByPost;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWokenByPost = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post each byte.
+		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.  Note that the
+	// name of the yield function required is port specific.
+	if( xHigherPriorityTaskWokenByPost )
+	{
+		taskYIELD_YIELD_FROM_ISR();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ portBASE_TYPE xQueueReceiveFromISR(
+									   xQueueHandle	xQueue,
+									   void	*pvBuffer,
+									   portBASE_TYPE *pxTaskWoken
+								   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ xQueueHandle xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const portTickType xBlockTime = ( portTickType )0xff;
+
+	// Create a queue capable of containing 10 characters.
+	xQueue = xQueueCreate( 10, sizeof( char ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Post some characters that will be used within an ISR.  If the queue
+	// is full then this task will block for xBlockTime ticks.
+	cValueToPost = 'a';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+	cValueToPost = 'b';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+
+	// ... keep posting characters ... this task may block when the queue
+	// becomes full.
+
+	cValueToPost = 'c';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ portBASE_TYPE xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+	{
+		// A character was received.  Output the character now.
+		vOutputCharacter( cRxedChar );
+
+		// If removing the character from the queue woke the task that was
+		// posting onto the queue cTaskWokenByReceive will have been set to
+		// pdTRUE.  No matter how many times this loop iterates only one
+		// task will be woken.
+	}
+
+	if( cTaskWokenByPost != ( char ) pdFALSE;
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; + +/* + * Utilities to query queues that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) PRIVILEGED_FUNCTION; + + +/* + * xQueueAltGenericSend() is an alternative version of xQueueGenericSend(). + * Likewise xQueueAltGenericReceive() is an alternative version of + * xQueueGenericReceive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); +signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); +#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) +#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) +#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) +#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); +signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ); +signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ); +signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait ); + +/* + * For internal use only. Use xSemaphoreCreateMutex(), + * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling + * these functions directly. + */ +xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION; +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION; +void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION; +portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) PRIVILEGED_FUNCTION; + +/* + * Reset a queue back to its original empty state. pdPASS is returned if the + * queue is successfully reset. pdFAIL is returned if the queue could not be + * reset because there are tasks blocked on the queue waiting to either + * receive from the queue or send to the queue. + */ +#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcName ) PRIVILEGED_FUNCTION; +#endif + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to + * remove the queue, semaphore or mutex from the register. If you are not using + * a kernel aware debugger then this function can be ignored. + * + * @param xQueue The handle of the queue being removed from the registry. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +#endif + +/* + * Generic version of the queue creation function, which is in turn called by + * any queue, semaphore or mutex creation function or macro. + */ +xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION; + +/* + * Queue sets provide a mechanism to allow a task to block (pend) on a read + * operation from multiple queues or semaphores simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * A queue set must be explicitly created using a call to xQueueCreateSet() + * before it can be used. Once created, standard FreeRTOS queues and semaphores + * can be added to the set using calls to xQueueAddToSet(). + * xQueueSelectFromSet() is then used to determine which, if any, of the queues + * or semaphores contained in the set is in a state where a queue read or + * semaphore take operation would be successful. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: An additional 4 bytes of RAM is required for each space in a every + * queue added to a queue set. Therefore counting semaphores that have a high + * maximum count value should not be added to a queue set. + * + * Note 4: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param uxEventQueueLength Queue sets store events that occur on + * the queues and semaphores contained in the set. uxEventQueueLength specifies + * the maximum number of events that can be queued at once. To be absolutely + * certain that events are not lost uxEventQueueLength should be set to the + * total sum of the length of the queues added to the set, where binary + * semaphores and mutexes have a length of 1, and counting semaphores have a + * length set by their maximum count value. Examples: + * + If a queue set is to hold a queue of length 5, another queue of length 12, + * and a binary semaphore, then uxEventQueueLength should be set to + * (5 + 12 + 1), or 18. + * + If a queue set is to hold three binary semaphores then uxEventQueueLength + * should be set to (1 + 1 + 1 ), or 3. + * + If a queue set is to hold a counting semaphore that has a maximum count of + * 5, and a counting semaphore that has a maximum count of 3, then + * uxEventQueueLength should be set to (5 + 3), or 8. + * + * @return If the queue set is created successfully then a handle to the created + * queue set is returned. Otherwise NULL is returned. + */ +xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) PRIVILEGED_FUNCTION; + +/* + * Adds a queue or semaphore to a queue set that was previously created by a + * call to xQueueCreateSet(). + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being added to + * the queue set (cast to an xQueueSetMemberHandle type). + * + * @param xQueueSet The handle of the queue set to which the queue or semaphore + * is being added. + * + * @return If the queue or semaphore was successfully added to the queue set + * then pdPASS is returned. If the queue could not be successfully added to the + * queue set because it is already a member of a different queue set then pdFAIL + * is returned. + */ +portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * Removes a queue or semaphore from a queue set. A queue or semaphore can only + * be removed from a set if the queue or semaphore is empty. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being removed + * from the queue set (cast to an xQueueSetMemberHandle type). + * + * @param xQueueSet The handle of the queue set in which the queue or semaphore + * is included. + * + * @return If the queue or semaphore was successfully removed from the queue set + * then pdPASS is returned. If the queue was not in the queue set, or the + * queue (or semaphore) was not empty, then pdFAIL is returned. + */ +portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION; + +/* + * xQueueSelectFromSet() selects from the members of a queue set a queue or + * semaphore that either contains data (in the case of a queue) or is available + * to take (in the case of a semaphore). xQueueSelectFromSet() effectively + * allows a task to block (pend) on a read operation on all the queues and + * semaphores in a queue set simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueSet The queue set on which the task will (potentially) block. + * + * @param xBlockTimeTicks The maximum time, in ticks, that the calling task will + * remain in the Blocked state (with other tasks executing) to wait for a member + * of the queue set to be ready for a successful queue read or semaphore take + * operation. + * + * @return xQueueSelectFromSet() will return the handle of a queue (cast to + * a xQueueSetMemberHandle type) contained in the queue set that contains data, + * or the handle of a semaphore (cast to a xQueueSetMemberHandle type) contained + * in the queue set that is available, or NULL if no such queue or semaphore + * exists before before the specified block time expires. + */ +xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) PRIVILEGED_FUNCTION; + +/* + * A version of xQueueSelectFromSet() that can be used from an ISR. + */ +xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) PRIVILEGED_FUNCTION; + +/* Not public API functions. */ +void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; +portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION; +void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) PRIVILEGED_FUNCTION; +unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; +unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) PRIVILEGED_FUNCTION; + + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + diff --git a/source/freertos_blinky/freertos/inc/semphr.h b/source/freertos_blinky/freertos/inc/semphr.h new file mode 100644 index 0000000..863b873 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/semphr.h @@ -0,0 +1,786 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h" must appear in source files before "include semphr.h" +#endif + +#include "queue.h" + +typedef xQueueHandle xSemaphoreHandle; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0U ) +#define semGIVE_BLOCK_TIME ( ( portTickType ) 0U ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
+ * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } + +/** + * semphr. h + *
xSemaphoreTake( 
+ *                   xSemaphoreHandle xSemaphore, 
+ *                   portTickType xBlockTime 
+ *               )
+ * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_RATE_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the 
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * xSemaphoreHandle xMutex, + * portTickType xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_RATE_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to 
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be 
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) + + +/* + * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + *
xSemaphoreGive( xSemaphoreHandle xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to 
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be 
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) + +/* + * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR( 
+                          xSemaphoreHandle xSemaphore, 
+                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore 
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute 
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static unsigned char ucLocalTickCount = 0;
+ static signed portBASE_TYPE xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreTakeFromISR( 
+                          xSemaphoreHandle xSemaphore, 
+                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to take a semaphore from an ISR. The semaphore must have + * previously been created with a call to vSemaphoreCreateBinary() or + * xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR, however taking a semaphore from an ISR + * is not a common operation. It is likely to only be useful when taking a + * counting semaphore when an interrupt is obtaining an object from a resource + * pool (when the semaphore count indicates the number of resources available). + * + * @param xSemaphore A handle to the semaphore being taken. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully taken, otherwise + * pdFALSE + */ +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateMutex( void )
+ * + * Macro that implements a mutex semaphore by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros should not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) + + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )
+ * + * Macro that implements a recursive mutex by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
+ * + * Macro that creates a counting semaphore by using the existing + * queue mechanism. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ xSemaphoreHandle xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) + +/** + * semphr. h + *
void vSemaphoreDelete( xSemaphoreHandle xSemaphore );
+ * + * Delete a semaphore. This function must be used with care. For example, + * do not delete a mutex type semaphore if the mutex is held by a task. + * + * @param xSemaphore A handle to the semaphore to be deleted. + * + * \defgroup vSemaphoreDelete vSemaphoreDelete + * \ingroup Semaphores + */ +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) ( xSemaphore ) ) + +/** + * semphr.h + *
xTaskHandle xSemaphoreGetMutexHolder( xSemaphoreHandle xMutex );
+ * + * If xMutex is indeed a mutex type semaphore, return the current mutex holder. + * If xMutex is not a mutex type semaphore, or the mutex is available (not held + * by a task), return NULL. + * + * Note: This Is is a good way of determining if the calling task is the mutex + * holder, but not a good way of determining the identity of the mutex holder as + * the holder may change between the function exiting and the returned value + * being tested. + */ +#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) + +#endif /* SEMAPHORE_H */ + + diff --git a/source/freertos_blinky/freertos/inc/task.h b/source/freertos_blinky/freertos/inc/task.h new file mode 100644 index 0000000..0a98d4e --- /dev/null +++ b/source/freertos_blinky/freertos/inc/task.h @@ -0,0 +1,1520 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef INC_TASK_H +#define INC_TASK_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include task.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V7.5.3" + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an xTaskHandle variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \defgroup xTaskHandle xTaskHandle + * \ingroup Tasks + */ +typedef void * xTaskHandle; + +/* Task states returned by eTaskGetState. */ +typedef enum +{ + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a read or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted /* The task being queried has been deleted, but its TCB has not yet been freed. */ +} eTaskState; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT +{ + portBASE_TYPE xOverflowCount; + portTickType xTimeOnEntering; +} xTimeOutType; + +/* + * Defines the memory ranges allocated to the task when an MPU is used. + */ +typedef struct xMEMORY_REGION +{ + void *pvBaseAddress; + unsigned long ulLengthInBytes; + unsigned long ulParameters; +} xMemoryRegion; + +/* + * Parameters required to create an MPU protected task. + */ +typedef struct xTASK_PARAMTERS +{ + pdTASK_CODE pvTaskCode; + const signed char * const pcName; + unsigned short usStackDepth; + void *pvParameters; + unsigned portBASE_TYPE uxPriority; + portSTACK_TYPE *puxStackBuffer; + xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} xTaskParameters; + +/* Used with the uxTaskGetSystemState() function to return the state of each task +in the system. */ +typedef struct xTASK_STATUS +{ + xTaskHandle xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const signed char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ + unsigned portBASE_TYPE xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + unsigned portBASE_TYPE uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + unsigned portBASE_TYPE uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + unsigned long ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + unsigned short usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ +} xTaskStatusType; + +/* Possible return values for eTaskConfirmSleepModeStatus(). */ +typedef enum +{ + eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ + eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ +} eSleepModeStatus; + + +/* + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0U ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \defgroup taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL() portENTER_CRITICAL() + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() + +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). */ +#define taskSCHEDULER_NOT_STARTED ( ( portBASE_TYPE ) 0 ) +#define taskSCHEDULER_RUNNING ( ( portBASE_TYPE ) 1 ) +#define taskSCHEDULER_SUSPENDED ( ( portBASE_TYPE ) 2 ) + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ portBASE_TYPE xTaskCreate(
+							  pdTASK_CODE pvTaskCode,
+							  const char * const pcName,
+							  unsigned short usStackDepth,
+							  void *pvParameters,
+							  unsigned portBASE_TYPE uxPriority,
+							  xTaskHandle *pvCreatedTask
+						  );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * xTaskCreate() can only be used to create a task that has unrestricted + * access to the entire microcontroller memory map. Systems that include MPU + * support can alternatively create an MPU constrained task using + * xTaskCreateRestricted(). + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. Systems that + * include MPU support can optionally create tasks in a privileged (system) + * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For + * example, to create a privileged task at priority 2 the uxPriority parameter + * should be set to ( 2 | portPRIVILEGE_BIT ). + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file errors. h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+	 }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+
+	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+	 // the new task attempts to access it.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) ) + +/** + * task. h + *
+ portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );
+ * + * xTaskCreateRestricted() should only be used in systems that include an MPU + * implementation. + * + * Create a new task and add it to the list of tasks that are ready to run. + * The function parameters define the memory regions and associated access + * permissions allocated to the task. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file errors. h + * + * Example usage: +
+// Create an xTaskParameters structure that defines the task to be created.
+static const xTaskParameters xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+};
+
+int main( void )
+{
+xTaskHandle xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) ) + +/** + * task. h + *
+ void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );
+ * + * Memory regions are assigned to a restricted task when the task is created by + * a call to xTaskCreateRestricted(). These regions can be redefined using + * vTaskAllocateMPURegions(). + * + * @param xTask The handle of the task being updated. + * + * @param xRegions A pointer to an xMemoryRegion structure that contains the + * new memory region definitions. + * + * Example usage: +
+// Define an array of xMemoryRegion structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array.  The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{
+	// Base address		Length		Parameters
+	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+	{ 0,				0,			0 },
+	{ 0,				0,			0 }
+};
+
+void vATask( void *pvParameters )
+{
+	// This task was created such that it has access to certain regions of
+	// memory as defined by the MPU configuration.  At some point it is
+	// desired that these MPU regions are replaced with that defined in the
+	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+	// for this purpose.  NULL is used as the task handle to indicate that this
+	// function should modify the MPU regions of the calling task.
+	vTaskAllocateMPURegions( NULL, xAltRegions );
+
+	// Now the task can continue its function, but from this point on can only
+	// access its stack and the ucOneKByte array (unless any other statically
+	// defined or shared regions have been declared elsewhere).
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelete( xTaskHandle xTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernels management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param xTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create the task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete( xTaskHandle xTaskToDelete ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( portTickType xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_RATE_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a cyclical task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const portTickType xDelay = 500 / portTICK_RATE_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay( portTickType xTicksToDelay ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by cyclical + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_RATE_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ portTickType xLastWakeTime;
+ const portTickType xFrequency = 10;
+
+	 // Initialise the xLastWakeTime variable with the current time.
+	 xLastWakeTime = xTaskGetTickCount ();
+	 for( ;; )
+	 {
+		 // Wait for the next cycle.
+		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+		 // Perform action here.
+	 }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask );
+ * + * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param xTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of xTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to obtain the priority of the created task.
+	 // It was created with tskIDLE_PRIORITY, but may have changed
+	 // it itself.
+	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+	 {
+		 // The task has changed it's priority.
+	 }
+
+	 // ...
+
+	 // Is our priority higher than the created task?
+	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+	 {
+		 // Our priority (obtained using NULL handle) is higher.
+	 }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
eTaskState eTaskGetState( xTaskHandle xTask );
+ * + * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the state of any task. States are encoded by the eTaskState + * enumerated type. + * + * @param xTask Handle of the task to be queried. + * + * @return The state of xTask at the time the function was called. Note the + * state of the task might change between the function being called, and the + * functions return value being tested by the calling task. + */ +eTaskState eTaskGetState( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param xTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to raise the priority of the created task.
+	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+	 // ...
+
+	 // Use a NULL handle to raise our priority to the same value.
+	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspend( xTaskHandle xTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Suspend ourselves.
+	 vTaskSuspend( NULL );
+
+	 // We cannot get here unless another task calls vTaskResume
+	 // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend( xTaskHandle xTaskToSuspend ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskResume( xTaskHandle xTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one of more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param xTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Resume the suspended task ourselves.
+	 vTaskResume( xHandle );
+
+	 // The created task will once again get microcontroller processing
+	 // time in accordance with it priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void xTaskResumeFromISR( xTaskHandle xTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one of more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * @param xTaskToResume Handle to the task being readied. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. This function + * does not return until an executing task calls vTaskEndScheduler (). + * + * At least one task should be created via a call to xTaskCreate () + * before calling vTaskStartScheduler (). The idle task is created + * automatically when the first application task is created. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // At some point we want to end the real time kernel processing
+		 // so call ...
+		 vTaskEndScheduler ();
+	 }
+ }
+
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will only get here when the vTaskCode () task has called
+	 // vTaskEndScheduler ().  When we get here we are back to single task
+	 // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends all real time kernel activity while keeping interrupts (including the + * kernel tick) enabled. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the kernel
+		 // tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.
+		 xTaskResumeAll ();
+	 }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
char xTaskResumeAll( void );
+ * + * Resumes real time kernel activity following a call to vTaskSuspendAll (). + * After a call to vTaskSuspendAll () the kernel will take control of which + * task is executing at any time. + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the real
+		 // time kernel tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.  We want to force
+		 // a context switch - but there is no point if resuming the scheduler
+		 // caused a context switch already.
+		 if( !xTaskResumeAll () )
+		 {
+			  taskYIELD ();
+		 }
+	 }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +signed portBASE_TYPE xTaskResumeAll( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
signed portBASE_TYPE xTaskIsTaskSuspended( const xTaskHandle xTask );
+ * + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. + * + */ +signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
portTickType xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \defgroup xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
portTickType xTaskGetTickCountFromISR( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * This is a version of xTaskGetTickCount() that is safe to be called from an + * ISR - provided that portTickType is the natural word size of the + * microcontroller being used or interrupt nesting is either not supported or + * not being used. + * + * \defgroup xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +portTickType xTaskGetTickCountFromISR( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
unsigned short uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery );
+ * + * @return The text (human readable) name of the task referenced by the handle + * xTaskToQueury. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. INCLUDE_pcTaskGetTaskName must be + * set to 1 in FreeRTOSConfig.h for pcTaskGetTaskName() to be available. + * + * \defgroup pcTaskGetTaskName pcTaskGetTaskName + * \ingroup TaskUtils + */ +signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ); + +/** + * task.h + *
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in words, so on a 32 bit machine + * a value of 1 means 4 bytes) since the task started. The smaller the returned + * number the closer the task has come to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in bytes) + * since the task referenced by xTask was created. + */ +unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + +/* When using trace macros it is sometimes necessary to include tasks.h before +FreeRTOS.h. When this is done pdTASK_HOOK_CODE will not yet have been defined, +so the following two prototypes will cause a compilation error. This can be +fixed by simply guarding against the inclusion of these two prototypes unless +they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration +constant. */ +#ifdef configUSE_APPLICATION_TASK_TAG + #if configUSE_APPLICATION_TASK_TAG == 1 + /** + * task.h + *
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ + void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) PRIVILEGED_FUNCTION; + + /** + * task.h + *
void xTaskGetApplicationTaskTag( xTaskHandle xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ + pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) PRIVILEGED_FUNCTION; + #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ + +/** + * task.h + *
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. + */ +portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) PRIVILEGED_FUNCTION; + +/** + * xTaskGetIdleTaskHandle() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the idle task. It is not valid to call + * xTaskGetIdleTaskHandle() before the scheduler has been started. + */ +xTaskHandle xTaskGetIdleTaskHandle( void ); + +/** + * configUSE_TRACE_FACILITY must bet defined as 1 in FreeRTOSConfig.h for + * uxTaskGetSystemState() to be available. + * + * uxTaskGetSystemState() populates an xTaskStatusType structure for each task in + * the system. xTaskStatusType structures contain, among other things, members + * for the task handle, task name, task priority, task state, and total amount + * of run time consumed by the task. See the xTaskStatusType structure + * definition in this file for the full member list. + * + * NOTE: This function is intended for debugging use only as its use results in + * the scheduler remaining suspended for an extended period. + * + * @param pxTaskStatusArray A pointer to an array of xTaskStatusType structures. + * The array must contain at least one xTaskStatusType structure for each task + * that is under the control of the RTOS. The number of tasks under the control + * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. + * + * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray + * parameter. The size is specified as the number of indexes in the array, or + * the number of xTaskStatusType structures contained in the array, not by the + * number of bytes in the array. + * + * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in + * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the + * total run time (as defined by the run time stats clock, see + * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. + * pulTotalRunTime can be set to NULL to omit the total run time information. + * + * @return The number of xTaskStatusType structures that were populated by + * uxTaskGetSystemState(). This should equal the number returned by the + * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed + * in the uxArraySize parameter was too small. + * + * Example usage: +
+    // This example demonstrates how a human readable table of run time stats
+	// information is generated from raw data provided by uxTaskGetSystemState().
+	// The human readable table is written to pcWriteBuffer
+	void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
+	{
+	xTaskStatusType *pxTaskStatusArray;
+	volatile unsigned portBASE_TYPE uxArraySize, x;
+	unsigned long ulTotalRunTime, ulStatsAsPercentage;
+
+		// Make sure the write buffer does not contain a string.
+		*pcWriteBuffer = 0x00;
+
+		// Take a snapshot of the number of tasks in case it changes while this
+		// function is executing.
+		uxArraySize = uxCurrentNumberOfTasks();
+
+		// Allocate a xTaskStatusType structure for each task.  An array could be
+		// allocated statically at compile time.
+		pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
+
+		if( pxTaskStatusArray != NULL )
+		{
+			// Generate raw status information about each task.
+			uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+
+			// For percentage calculations.
+			ulTotalRunTime /= 100UL;
+
+			// Avoid divide by zero errors.
+			if( ulTotalRunTime > 0 )
+			{
+				// For each populated position in the pxTaskStatusArray array,
+				// format the raw data as human readable ASCII data
+				for( x = 0; x < uxArraySize; x++ )
+				{
+					// What percentage of the total run time has the task used?
+					// This will always be rounded down to the nearest integer.
+					// ulTotalRunTimeDiv100 has already been divided by 100.
+					ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+
+					if( ulStatsAsPercentage > 0UL )
+					{
+						sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+					}
+					else
+					{
+						// If the percentage is zero here then the task has
+						// consumed less than 1% of the total run time.
+						sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+					}
+
+					pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+				}
+			}
+
+			// The array is no longer needed, free the memory it consumes.
+			vPortFree( pxTaskStatusArray );
+		}
+	}
+	
+ */ +unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime ); + +/** + * task. h + *
void vTaskList( char *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must + * both be defined as 1 for this function to be available. See the + * configuration section of the FreeRTOS.org website for more information. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays task + * names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that might + * bloat the code size, use a lot of stack, and provide different results on + * different platforms. An alternative, tiny, third party, and limited + * functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly through a + * call to vTaskList(). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ascii form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \defgroup vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS + * must both be defined as 1 for this function to be available. The application + * must also then provide definitions for + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE + * to configure a peripheral timer/counter and return the timers current count + * value respectively. The counter should be at least 10 times the frequency of + * the tick count. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * NOTE 2: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays the + * amount of time each task has spent in the Running state in both absolute and + * percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function + * that might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, and + * limited functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() directly + * to get access to raw stats data, rather than indirectly through a call to + * vTaskGetRunTimeStats(). + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ascii form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. If a non-zero value is returned then a context switch is + * required because either: + * + A task was removed from a blocked list because its timeout had expired, + * or + * + Time slicing is in use and there is a task of equal priority to the + * currently running task. + */ +portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_RATE_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * This function performs nearly the same function as vTaskPlaceOnEventList(). + * The difference being that this function does not permit tasks to block + * indefinitely, whereas vTaskPlaceOnEventList() does. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList () will be called if either an event occurs to + * unblock a task, or the block timeout period expires. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +void vTaskSwitchContext( void ) PRIVILEGED_FUNCTION; + +/* + * Return the handle of the calling task. + */ +xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION; + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) PRIVILEGED_FUNCTION; + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) PRIVILEGED_FUNCTION; + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield( void ) PRIVILEGED_FUNCTION; + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +portBASE_TYPE xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION; + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) PRIVILEGED_FUNCTION; + +/* + * Generic version of the task creation function which is in turn called by the + * xTaskCreate() and xTaskCreateRestricted() macros. + */ +signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) PRIVILEGED_FUNCTION; + +/* + * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. + */ +unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ); + +/* + * Set the uxTCBNumber of the task referenced by the xTask parameter to + * ucHandle. + */ +void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ); + +/* + * If tickless mode is being used, or a low power mode is implemented, then + * the tick interrupt will not execute during idle periods. When this is the + * case, the tick count value maintained by the scheduler needs to be kept up + * to date with the actual execution time by being skipped forward by the by + * a time equal to the idle period. + */ +void vTaskStepTick( portTickType xTicksToJump ); + +/* + * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port + * specific sleep function to determine if it is ok to proceed with the sleep, + * and if it is ok to proceed, if it is ok to sleep indefinitely. + * + * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only + * called with the scheduler suspended, not from within a critical section. It + * is therefore possible for an interrupt to request a context switch between + * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being + * entered. eTaskConfirmSleepModeStatus() should be called from a short + * critical section between the timer being stopped and the sleep mode being + * entered to ensure it is ok to proceed into the sleep mode. + */ +eSleepModeStatus eTaskConfirmSleepModeStatus( void ); + +#ifdef __cplusplus +} +#endif +#endif /* INC_TASK_H */ + + + diff --git a/source/freertos_blinky/freertos/inc/timers.h b/source/freertos_blinky/freertos/inc/timers.h new file mode 100644 index 0000000..60758d9 --- /dev/null +++ b/source/freertos_blinky/freertos/inc/timers.h @@ -0,0 +1,960 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef TIMERS_H +#define TIMERS_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include timers.h" +#endif + +/*lint -e537 This headers are only multiply included if the application code +happens to also be including task.h. */ +#include "task.h" +/*lint +e956 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* IDs for commands that can be sent/received on the timer queue. These are to +be used solely through the macros that make up the public software timer API, +as defined below. */ +#define tmrCOMMAND_START ( ( portBASE_TYPE ) 0 ) +#define tmrCOMMAND_STOP ( ( portBASE_TYPE ) 1 ) +#define tmrCOMMAND_CHANGE_PERIOD ( ( portBASE_TYPE ) 2 ) +#define tmrCOMMAND_DELETE ( ( portBASE_TYPE ) 3 ) + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + + /** + * Type by which software timers are referenced. For example, a call to + * xTimerCreate() returns an xTimerHandle variable that can then be used to + * reference the subject timer in calls to other software timer API functions + * (for example, xTimerStart(), xTimerReset(), etc.). + */ +typedef void * xTimerHandle; + +/* Define the prototype to which timer callback functions must conform. */ +typedef void (*tmrTIMER_CALLBACK)( xTimerHandle xTimer ); + +/** + * xTimerHandle xTimerCreate( const signed char *pcTimerName, + * portTickType xTimerPeriodInTicks, + * unsigned portBASE_TYPE uxAutoReload, + * void * pvTimerID, + * tmrTIMER_CALLBACK pxCallbackFunction ); + * + * Creates a new software timer instance. This allocates the storage required + * by the new timer, initialises the new timers internal state, and returns a + * handle by which the new timer can be referenced. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param pcTimerName A text name that is assigned to the timer. This is done + * purely to assist debugging. The kernel itself only ever references a timer by + * its handle, and never by its name. + * + * @param xTimerPeriodInTicks The timer period. The time is defined in tick periods so + * the constant portTICK_RATE_MS can be used to convert a time that has been + * specified in milliseconds. For example, if the timer must expire after 100 + * ticks, then xTimerPeriodInTicks should be set to 100. Alternatively, if the timer + * must expire after 500ms, then xPeriod can be set to ( 500 / portTICK_RATE_MS ) + * provided configTICK_RATE_HZ is less than or equal to 1000. + * + * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will + * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. If + * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and + * enter the dormant state after it expires. + * + * @param pvTimerID An identifier that is assigned to the timer being created. + * Typically this would be used in the timer callback function to identify which + * timer expired when the same callback function is assigned to more than one + * timer. + * + * @param pxCallbackFunction The function to call when the timer expires. + * Callback functions must have the prototype defined by tmrTIMER_CALLBACK, + * which is "void vCallbackFunction( xTimerHandle xTimer );". + * + * @return If the timer is successfully create then a handle to the newly + * created timer is returned. If the timer cannot be created (because either + * there is insufficient FreeRTOS heap remaining to allocate the timer + * structures, or the timer period was set to 0) then 0 is returned. + * + * Example usage: + * @verbatim + * #define NUM_TIMERS 5 + * + * // An array to hold handles to the created timers. + * xTimerHandle xTimers[ NUM_TIMERS ]; + * + * // An array to hold a count of the number of times each timer expires. + * long lExpireCounters[ NUM_TIMERS ] = { 0 }; + * + * // Define a callback function that will be used by multiple timer instances. + * // The callback function does nothing but count the number of times the + * // associated timer expires, and stop the timer once the timer has expired + * // 10 times. + * void vTimerCallback( xTimerHandle pxTimer ) + * { + * long lArrayIndex; + * const long xMaxExpiryCountBeforeStopping = 10; + * + * // Optionally do something if the pxTimer parameter is NULL. + * configASSERT( pxTimer ); + * + * // Which timer expired? + * lArrayIndex = ( long ) pvTimerGetTimerID( pxTimer ); + * + * // Increment the number of times that pxTimer has expired. + * lExpireCounters[ lArrayIndex ] += 1; + * + * // If the timer has expired 10 times then stop it from running. + * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) + * { + * // Do not use a block time if calling a timer API function from a + * // timer callback function, as doing so could cause a deadlock! + * xTimerStop( pxTimer, 0 ); + * } + * } + * + * void main( void ) + * { + * long x; + * + * // Create then start some timers. Starting the timers before the scheduler + * // has been started means the timers will start running immediately that + * // the scheduler starts. + * for( x = 0; x < NUM_TIMERS; x++ ) + * { + * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. + * ( 100 * x ), // The timer period in ticks. + * pdTRUE, // The timers will auto-reload themselves when they expire. + * ( void * ) x, // Assign each timer a unique id equal to its array index. + * vTimerCallback // Each timer calls the same callback when it expires. + * ); + * + * if( xTimers[ x ] == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timers running as they have already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +xTimerHandle xTimerCreate( const signed char * const pcTimerName, portTickType xTimerPeriodInTicks, unsigned portBASE_TYPE uxAutoReload, void * pvTimerID, tmrTIMER_CALLBACK pxCallbackFunction ) PRIVILEGED_FUNCTION; + +/** + * void *pvTimerGetTimerID( xTimerHandle xTimer ); + * + * Returns the ID assigned to the timer. + * + * IDs are assigned to timers using the pvTimerID parameter of the call to + * xTimerCreated() that was used to create the timer. + * + * If the same callback function is assigned to multiple timers then the timer + * ID can be used within the callback function to identify which timer actually + * expired. + * + * @param xTimer The timer being queried. + * + * @return The ID assigned to the timer being queried. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + */ +void *pvTimerGetTimerID( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; + +/** + * portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ); + * + * Queries a timer to see if it is active or dormant. + * + * A timer will be dormant if: + * 1) It has been created but not started, or + * 2) It is an expired on-shot timer that has not been restarted. + * + * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), + * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and + * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the + * active state. + * + * @param xTimer The timer being queried. + * + * @return pdFALSE will be returned if the timer is dormant. A value other than + * pdFALSE will be returned if the timer is active. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. + * void vAFunction( xTimerHandle xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is active, do something. + * } + * else + * { + * // xTimer is not active, do something else. + * } + * } + * @endverbatim + */ +portBASE_TYPE xTimerIsTimerActive( xTimerHandle xTimer ) PRIVILEGED_FUNCTION; + +/** + * xTimerGetTimerDaemonTaskHandle() is only available if + * INCLUDE_xTimerGetTimerDaemonTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the timer service/daemon task. It it not valid + * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. + */ +xTaskHandle xTimerGetTimerDaemonTaskHandle( void ); + +/** + * portBASE_TYPE xTimerStart( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStart() starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerStart() has equivalent functionality + * to the xTimerReset() API function. + * + * Starting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerStart() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerStart() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerStart() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() + * to be available. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the start command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStart() was called. xBlockTime is ignored if xTimerStart() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStart( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerStop( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerStop() stops a timer that was previously started using either of the + * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), + * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. + * + * Stopping a timer ensures the timer is not in the active state. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() + * to be available. + * + * @param xTimer The handle of the timer being stopped. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the stop command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerStop() was called. xBlockTime is ignored if xTimerStop() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerCreate() API function example usage scenario. + * + */ +#define xTimerStop( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerChangePeriod( xTimerHandle xTimer, + * portTickType xNewPeriod, + * portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerChangePeriod() changes the period of a timer that was previously + * created using the xTimerCreate() API function. + * + * xTimerChangePeriod() can be called to change the period of an active or + * dormant state timer. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerChangePeriod() to be available. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_RATE_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the change period command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerChangePeriod() was called. xBlockTime is ignored if + * xTimerChangePeriod() is called before the scheduler is started. + * + * @return pdFAIL will be returned if the change period command could not be + * sent to the timer command queue even after xBlockTime ticks had passed. + * pdPASS will be returned if the command was successfully sent to the timer + * command queue. When the command is actually processed will depend on the + * priority of the timer service/daemon task relative to other tasks in the + * system. The timer service/daemon task priority is set by the + * configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This function assumes xTimer has already been created. If the timer + * // referenced by xTimer is already active when it is called, then the timer + * // is deleted. If the timer referenced by xTimer is not active when it is + * // called, then the period of the timer is set to 500ms and the timer is + * // started. + * void vAFunction( xTimerHandle xTimer ) + * { + * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" + * { + * // xTimer is already active - delete it. + * xTimerDelete( xTimer ); + * } + * else + * { + * // xTimer is not active, change its period to 500ms. This will also + * // cause the timer to start. Block for a maximum of 100 ticks if the + * // change period command cannot immediately be sent to the timer + * // command queue. + * if( xTimerChangePeriod( xTimer, 500 / portTICK_RATE_MS, 100 ) == pdPASS ) + * { + * // The command was successfully sent. + * } + * else + * { + * // The command could not be sent, even after waiting for 100 ticks + * // to pass. Take appropriate action here. + * } + * } + * } + * @endverbatim + */ + #define xTimerChangePeriod( xTimer, xNewPeriod, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerDelete( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerDelete() deletes a timer that was previously created using the + * xTimerCreate() API function. + * + * The configUSE_TIMERS configuration constant must be set to 1 for + * xTimerDelete() to be available. + * + * @param xTimer The handle of the timer being deleted. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the delete command to be + * successfully sent to the timer command queue, should the queue already be + * full when xTimerDelete() was called. xBlockTime is ignored if xTimerDelete() + * is called before the scheduler is started. + * + * @return pdFAIL will be returned if the delete command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system. The timer + * service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * + * See the xTimerChangePeriod() API function example usage scenario. + */ +#define xTimerDelete( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerReset( xTimerHandle xTimer, portTickType xBlockTime ); + * + * Timer functionality is provided by a timer service/daemon task. Many of the + * public FreeRTOS timer API functions send commands to the timer service task + * though a queue called the timer command queue. The timer command queue is + * private to the kernel itself and is not directly accessible to application + * code. The length of the timer command queue is set by the + * configTIMER_QUEUE_LENGTH configuration constant. + * + * xTimerReset() re-starts a timer that was previously created using the + * xTimerCreate() API function. If the timer had already been started and was + * already in the active state, then xTimerReset() will cause the timer to + * re-evaluate its expiry time so that it is relative to when xTimerReset() was + * called. If the timer was in the dormant state then xTimerReset() has + * equivalent functionality to the xTimerStart() API function. + * + * Resetting a timer ensures the timer is in the active state. If the timer + * is not stopped, deleted, or reset in the mean time, the callback function + * associated with the timer will get called 'n' ticks after xTimerReset() was + * called, where 'n' is the timers defined period. + * + * It is valid to call xTimerReset() before the scheduler has been started, but + * when this is done the timer will not actually start until the scheduler is + * started, and the timers expiry time will be relative to when the scheduler is + * started, not relative to when xTimerReset() was called. + * + * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() + * to be available. + * + * @param xTimer The handle of the timer being reset/started/restarted. + * + * @param xBlockTime Specifies the time, in ticks, that the calling task should + * be held in the Blocked state to wait for the reset command to be successfully + * sent to the timer command queue, should the queue already be full when + * xTimerReset() was called. xBlockTime is ignored if xTimerReset() is called + * before the scheduler is started. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue even after xBlockTime ticks had passed. pdPASS will + * be returned if the command was successfully sent to the timer command queue. + * When the command is actually processed will depend on the priority of the + * timer service/daemon task relative to other tasks in the system, although the + * timers expiry time is relative to when xTimerStart() is actually called. The + * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY + * configuration constant. + * + * Example usage: + * @verbatim + * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer. + * + * xTimerHandle xBacklightTimer = NULL; + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press event handler. + * void vKeyPressEventHandler( char cKey ) + * { + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. Wait 10 ticks for the command to be successfully sent + * // if it cannot be sent immediately. + * vSetBacklightState( BACKLIGHT_ON ); + * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * } + * + * void main( void ) + * { + * long x; + * + * // Create then start the one-shot timer that is responsible for turning + * // the back-light off if no keys are pressed within a 5 second period. + * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. + * ( 5000 / portTICK_RATE_MS), // The timer period in ticks. + * pdFALSE, // The timer is a one-shot timer. + * 0, // The id is not used by the callback so can take any value. + * vBacklightTimerCallback // The callback function that switches the LCD back-light off. + * ); + * + * if( xBacklightTimer == NULL ) + * { + * // The timer was not created. + * } + * else + * { + * // Start the timer. No block time is specified, and even if one was + * // it would be ignored because the scheduler has not yet been + * // started. + * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) + * { + * // The timer could not be set into the Active state. + * } + * } + * + * // ... + * // Create tasks here. + * // ... + * + * // Starting the scheduler will start the timer running as it has already + * // been set into the active state. + * xTaskStartScheduler(); + * + * // Should not reach here. + * for( ;; ); + * } + * @endverbatim + */ +#define xTimerReset( xTimer, xBlockTime ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xBlockTime ) ) + +/** + * portBASE_TYPE xTimerStartFromISR( xTimerHandle xTimer, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStart() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being started/restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStartFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStartFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStartFromISR() function. If + * xTimerStartFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the start command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerStartFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then restart the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The start command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + * @endverbatim + */ +#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * portBASE_TYPE xTimerStopFromISR( xTimerHandle xTimer, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerStop() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer being stopped. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerStopFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerStopFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerStopFromISR() function. If + * xTimerStopFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the stop command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the timer should be simply stopped. + * + * // The interrupt service routine that stops the timer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - simply stop the timer. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The stop command was not executed successfully. Take appropriate + * // action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + * @endverbatim + */ +#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0, ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * portBASE_TYPE xTimerChangePeriodFromISR( xTimerHandle xTimer, + * portTickType xNewPeriod, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerChangePeriod() that can be called from an interrupt + * service routine. + * + * @param xTimer The handle of the timer that is having its period changed. + * + * @param xNewPeriod The new period for xTimer. Timer periods are specified in + * tick periods, so the constant portTICK_RATE_MS can be used to convert a time + * that has been specified in milliseconds. For example, if the timer must + * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, + * if the timer must expire after 500ms, then xNewPeriod can be set to + * ( 500 / portTICK_RATE_MS ) provided configTICK_RATE_HZ is less than + * or equal to 1000. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerChangePeriodFromISR() writes a message to the + * timer command queue, so has the potential to transition the timer service/ + * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() + * causes the timer service/daemon task to leave the Blocked state, and the + * timer service/daemon task has a priority equal to or greater than the + * currently executing task (the task that was interrupted), then + * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the + * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets + * this value to pdTRUE then a context switch should be performed before the + * interrupt exits. + * + * @return pdFAIL will be returned if the command to change the timers period + * could not be sent to the timer command queue. pdPASS will be returned if the + * command was successfully sent to the timer command queue. When the command + * is actually processed will depend on the priority of the timer service/daemon + * task relative to other tasks in the system. The timer service/daemon task + * priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xTimer has already been created and started. When + * // an interrupt occurs, the period of xTimer should be changed to 500ms. + * + * // The interrupt service routine that changes the period of xTimer. + * void vAnExampleInterruptServiceRoutine( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // The interrupt has occurred - change the period of xTimer to 500ms. + * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined + * // (within this function). As this is an interrupt service routine, only + * // FreeRTOS API functions that end in "FromISR" can be used. + * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The command to change the timers period was not executed + * // successfully. Take appropriate action here. + * } + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + * @endverbatim + */ +#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) + +/** + * portBASE_TYPE xTimerResetFromISR( xTimerHandle xTimer, + * portBASE_TYPE *pxHigherPriorityTaskWoken ); + * + * A version of xTimerReset() that can be called from an interrupt service + * routine. + * + * @param xTimer The handle of the timer that is to be started, reset, or + * restarted. + * + * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most + * of its time in the Blocked state, waiting for messages to arrive on the timer + * command queue. Calling xTimerResetFromISR() writes a message to the timer + * command queue, so has the potential to transition the timer service/daemon + * task out of the Blocked state. If calling xTimerResetFromISR() causes the + * timer service/daemon task to leave the Blocked state, and the timer service/ + * daemon task has a priority equal to or greater than the currently executing + * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will + * get set to pdTRUE internally within the xTimerResetFromISR() function. If + * xTimerResetFromISR() sets this value to pdTRUE then a context switch should + * be performed before the interrupt exits. + * + * @return pdFAIL will be returned if the reset command could not be sent to + * the timer command queue. pdPASS will be returned if the command was + * successfully sent to the timer command queue. When the command is actually + * processed will depend on the priority of the timer service/daemon task + * relative to other tasks in the system, although the timers expiry time is + * relative to when xTimerResetFromISR() is actually called. The timer service/daemon + * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. + * + * Example usage: + * @verbatim + * // This scenario assumes xBacklightTimer has already been created. When a + * // key is pressed, an LCD back-light is switched on. If 5 seconds pass + * // without a key being pressed, then the LCD back-light is switched off. In + * // this case, the timer is a one-shot timer, and unlike the example given for + * // the xTimerReset() function, the key press event handler is an interrupt + * // service routine. + * + * // The callback function assigned to the one-shot timer. In this case the + * // parameter is not used. + * void vBacklightTimerCallback( xTimerHandle pxTimer ) + * { + * // The timer expired, therefore 5 seconds must have passed since a key + * // was pressed. Switch off the LCD back-light. + * vSetBacklightState( BACKLIGHT_OFF ); + * } + * + * // The key press interrupt service routine. + * void vKeyPressEventInterruptHandler( void ) + * { + * portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + * + * // Ensure the LCD back-light is on, then reset the timer that is + * // responsible for turning the back-light off after 5 seconds of + * // key inactivity. This is an interrupt service routine so can only + * // call FreeRTOS API functions that end in "FromISR". + * vSetBacklightState( BACKLIGHT_ON ); + * + * // xTimerStartFromISR() or xTimerResetFromISR() could be called here + * // as both cause the timer to re-calculate its expiry time. + * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was + * // declared (in this function). + * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) + * { + * // The reset command was not executed successfully. Take appropriate + * // action here. + * } + * + * // Perform the rest of the key processing here. + * + * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch + * // should be performed. The syntax required to perform a context switch + * // from inside an ISR varies from port to port, and from compiler to + * // compiler. Inspect the demos for the port you are using to find the + * // actual syntax required. + * if( xHigherPriorityTaskWoken != pdFALSE ) + * { + * // Call the interrupt safe yield function here (actual function + * // depends on the FreeRTOS port being used. + * } + * } + * @endverbatim + */ +#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) + +/* + * Functions beyond this part are not part of the public API and are intended + * for use by the kernel only. + */ +portBASE_TYPE xTimerCreateTimerTask( void ) PRIVILEGED_FUNCTION; +portBASE_TYPE xTimerGenericCommand( xTimerHandle xTimer, portBASE_TYPE xCommandID, portTickType xOptionalValue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portTickType xBlockTime ) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif +#endif /* TIMERS_H */ + + + diff --git a/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.c b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.c new file mode 100644 index 0000000..9b0a3c6 --- /dev/null +++ b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.c @@ -0,0 +1,94 @@ +/* + * @brief Common FreeRTOS functions shared among platforms + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "FreeRTOS.h" +#include "task.h" +#include "FreeRTOSCommonHooks.h" + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Delay for the specified number of milliSeconds */ +void FreeRTOSDelay(uint32_t ms) +{ + portTickType xDelayTime; + + xDelayTime = xTaskGetTickCount(); + vTaskDelayUntil(&xDelayTime, ms); +} + +/* FreeRTOS malloc fail hook */ +void vApplicationMallocFailedHook(void) +{ + DEBUGSTR("DIE:ERROR:FreeRTOS: Malloc Failure!\r\n"); + taskDISABLE_INTERRUPTS(); + for (;; ) {} +} + +/* FreeRTOS application idle hook */ +void vApplicationIdleHook(void) +{ + /* Best to sleep here until next systick */ + __WFI(); +} + +/* FreeRTOS stack overflow hook */ +void vApplicationStackOverflowHook(xTaskHandle pxTask, signed char *pcTaskName) +{ + (void) pxTask; + (void) pcTaskName; + + DEBUGOUT("DIE:ERROR:FreeRTOS: Stack overflow in task %s\r\n", pcTaskName); + /* Run time stack overflow checking is performed if + configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook + function is called if a stack overflow is detected. */ + taskDISABLE_INTERRUPTS(); + for (;; ) {} +} + +/* FreeRTOS application tick hook */ +void vApplicationTickHook(void) +{} diff --git a/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.h b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.h new file mode 100644 index 0000000..3136682 --- /dev/null +++ b/source/freertos_blinky/freertos/src/FreeRTOSCommonHooks.h @@ -0,0 +1,81 @@ +/* + * @brief Common FreeRTOS functions shared among platforms + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __FREERTOSCOMMONHOOKS_H_ +#define __FREERTOSCOMMONHOOKS_H_ + +/** @ingroup FreeRTOS_COMMON + * @{ + */ + +/** + * @brief Delay for the specified number of milliSeconds + * @param ms : Delay in milliSeconds + * @return Nothing + * @note Delays the specified number of milliSeoconds using a task delay + */ +void FreeRTOSDelay(uint32_t ms); + +/** + * @brief FreeRTOS malloc fail hook + * @return Nothing + * @note This function is alled when a malloc fails to allocate data. + */ +void vApplicationMallocFailedHook(void); + +/** + * @brief FreeRTOS application idle hook + * @return Nothing + * @note Calls ARM Wait for Interrupt function to idle core + */ +void vApplicationIdleHook(void); + +/** + * @brief FreeRTOS stack overflow hook + * @param pxTask : Task handle that overflowed stack + * @param pcTaskName : Task name that overflowed stack + * @return Nothing + * @note This function is alled when a stack overflow occurs. + */ +void vApplicationStackOverflowHook(xTaskHandle pxTask, signed char *pcTaskName); + +/** + * @brief FreeRTOS application tick hook + * @return Nothing + * @note This just returns to the caller. + */ +void vApplicationTickHook(void); + +/** + * @} + */ + +#endif /* __FREERTOSCOMMONHOOKS_H_ */ diff --git a/source/freertos_blinky/freertos/src/heap_3.c b/source/freertos_blinky/freertos/src/heap_3.c new file mode 100644 index 0000000..f6d2537 --- /dev/null +++ b/source/freertos_blinky/freertos/src/heap_3.c @@ -0,0 +1,131 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +/* + * Implementation of pvPortMalloc() and vPortFree() that relies on the + * compilers own malloc() and free() implementations. + * + * This file can only be used if the linker is configured to to generate + * a heap memory area. + * + * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the + * memory management pages of http://www.FreeRTOS.org for more information. + */ + +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn; + + vTaskSuspendAll(); + { + pvReturn = malloc( xWantedSize ); + traceMALLOC( pvReturn, xWantedSize ); + } + xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + if( pv ) + { + vTaskSuspendAll(); + { + free( pv ); + traceFREE( pv, 0 ); + } + xTaskResumeAll(); + } +} + + + diff --git a/source/freertos_blinky/freertos/src/list.c b/source/freertos_blinky/freertos/src/list.c new file mode 100644 index 0000000..9c22dbc --- /dev/null +++ b/source/freertos_blinky/freertos/src/list.c @@ -0,0 +1,204 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#include +#include "FreeRTOS.h" +#include "list.h" + +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +void vListInitialise( xList * const pxList ) +{ + /* The list structure contains a list item which is used to mark the + end of the list. To initialise the list the list end is inserted + as the only list entry. */ + pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + /* The list end value is the highest possible value in the list to + ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; + + /* The list end next and previous pointers point to itself so we know + when the list is empty. */ + pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + + pxList->uxNumberOfItems = ( unsigned portBASE_TYPE ) 0U; +} +/*-----------------------------------------------------------*/ + +void vListInitialiseItem( xListItem * const pxItem ) +{ + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pvContainer = NULL; +} +/*-----------------------------------------------------------*/ + +void vListInsertEnd( xList * const pxList, xListItem * const pxNewListItem ) +{ +xListItem * pxIndex; + + /* Insert a new list item into pxList, but rather than sort the list, + makes the new list item the last item to be removed by a call to + pvListGetOwnerOfNextEntry. */ + pxIndex = pxList->pxIndex; + + pxNewListItem->pxNext = pxIndex; + pxNewListItem->pxPrevious = pxIndex->pxPrevious; + pxIndex->pxPrevious->pxNext = pxNewListItem; + pxIndex->pxPrevious = pxNewListItem; + + /* Remember which list the item is in. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListInsert( xList * const pxList, xListItem * const pxNewListItem ) +{ +xListItem *pxIterator; +portTickType xValueOfInsertion; + + /* Insert the new list item into the list, sorted in ulListItem order. */ + xValueOfInsertion = pxNewListItem->xItemValue; + + /* If the list already contains a list item with the same item value then + the new list item should be placed after it. This ensures that TCB's which + are stored in ready lists (all of which have the same ulListItem value) + get an equal share of the CPU. However, if the xItemValue is the same as + the back marker the iteration loop below will not end. This means we need + to guard against this by checking the value first and modifying the + algorithm slightly if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + If you find your application is crashing here then likely causes are: + 1) Stack overflow - + see http://www.freertos.org/Stacks-and-stack-overflow-checking.html + 2) Incorrect interrupt priority assignment, especially on Cortex-M3 + parts where numerically high priority values denote low actual + interrupt priories, which can seem counter intuitive. See + configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html + 3) Calling an API function from within a critical section or when + the scheduler is suspended, or calling an API function that does + not end in "FromISR" from an interrupt. + 4) Using a queue or semaphore before it has been initialised or + before the scheduler has been started (are interrupts firing + before vTaskStartScheduler() has been called?). + See http://www.freertos.org/FAQHelp.html for more tips. + **********************************************************************/ + + for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */ + { + /* There is nothing to do here, we are just iterating to the + wanted insertion position. */ + } + } + + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = pxNewListItem; + + /* Remember which list the item is in. This allows fast removal of the + item later. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxListRemove( xListItem * const pxItemToRemove ) +{ +xList * pxList; + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + + /* The list item knows which list it is in. Obtain the list from the list + item. */ + pxList = ( xList * ) pxItemToRemove->pvContainer; + + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + + pxItemToRemove->pvContainer = NULL; + ( pxList->uxNumberOfItems )--; + + return pxList->uxNumberOfItems; +} +/*-----------------------------------------------------------*/ + diff --git a/source/freertos_blinky/freertos/src/port.c b/source/freertos_blinky/freertos/src/port.c new file mode 100644 index 0000000..de10b9e --- /dev/null +++ b/source/freertos_blinky/freertos/src/port.c @@ -0,0 +1,366 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM0 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Constants required to manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) +#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) +#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) +#define portNVIC_SYSTICK_CLK 0x00000004 +#define portNVIC_SYSTICK_INT 0x00000002 +#define portNVIC_SYSTICK_ENABLE 0x00000001 +#define portNVIC_PENDSVSET 0x10000000 +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) +#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case is messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. + */ +static void prvSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__ (( naked )); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void vPortStartFirstTask( void ) __attribute__ (( naked )); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11..R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " add r0, r0, #16 \n" /* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ + " mov r8, r4 \n" + " mov r9, r5 \n" + " mov r10, r6 \n" + " mov r11, r7 \n" + " \n" + " msr psp, r0 \n" /* Remember the new top of stack for the task. */ + " \n" + " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ + " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ + " mov r1, r14 \n" /* OR R14 with 0x0d. */ + " movs r0, #0x0d \n" + " orr r1, r0 \n" + " bx r1 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +void vPortStartFirstTask( void ) +{ + /* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector + table offset register that can be used to locate the initial stack value. + Not all M0 parts have the application vector table at address 0. */ + __asm volatile( + " cpsie i \n" /* Globally enable interrupts. */ + " svc 0 \n" /* System call to start first task. */ + " nop \n" + ); +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + vPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM0 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + *( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __asm volatile( "dsb" ); + __asm volatile( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __asm volatile( "dsb" ); + __asm volatile( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +unsigned long ulSetInterruptMaskFromISR( void ) +{ + __asm volatile( + " mrs r0, PRIMASK \n" + " cpsid i \n" + " bx lr " + ); + + /* To avoid compiler warnings. This line will never be reached. */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vClearInterruptMaskFromISR( unsigned long ulMask ) +{ + __asm volatile( + " msr PRIMASK, r0 \n" + " bx lr " + ); + + /* Just to avoid compiler warning. */ + ( void ) ulMask; +} +/*-----------------------------------------------------------*/ + +void xPortPendSVHandler( void ) +{ + /* This is a naked function. */ + + __asm volatile + ( + " mrs r0, psp \n" + " \n" + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " sub r0, r0, #32 \n" /* Make space for the remaining low registers. */ + " str r0, [r2] \n" /* Save the new top of stack. */ + " stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ + " mov r4, r8 \n" /* Store the high registers. */ + " mov r5, r9 \n" + " mov r6, r10 \n" + " mov r7, r11 \n" + " stmia r0!, {r4-r7} \n" + " \n" + " push {r3, r14} \n" + " cpsid i \n" + " bl vTaskSwitchContext \n" + " cpsie i \n" + " pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */ + " \n" + " ldr r1, [r2] \n" + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " add r0, r0, #16 \n" /* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ + " mov r8, r4 \n" + " mov r9, r5 \n" + " mov r10, r6 \n" + " mov r11, r7 \n" + " \n" + " msr psp, r0 \n" /* Remember the new top of stack for the task. */ + " \n" + " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ + " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ + " \n" + " bx r3 \n" + " \n" + " .align 2 \n" + "pxCurrentTCBConst: .word pxCurrentTCB " + ); +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ +unsigned long ulPreviousMask; + + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +/*-----------------------------------------------------------*/ + diff --git a/source/freertos_blinky/freertos/src/queue.c b/source/freertos_blinky/freertos/src/queue.c new file mode 100644 index 0000000..75fc158 --- /dev/null +++ b/source/freertos_blinky/freertos/src/queue.c @@ -0,0 +1,2084 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#if ( configUSE_CO_ROUTINES == 1 ) + #include "croutine.h" +#endif + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + + +/* Constants used with the cRxLock and xTxLock structure members. */ +#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 ) + +/* When the xQUEUE structure is used to represent a base queue its pcHead and +pcTail members are used as pointers into the queue storage area. When the +xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are +not necessary, and the pcHead pointer is set to NULL to indicate that the +pcTail pointer actually points to the mutex holder (if any). Map alternative +names to the pcHead and pcTail structure members to ensure the readability of +the code is maintained despite this dual use of two structure members. An +alternative implementation would be to use a union, but use of a union is +against the coding standard (although an exception to the standard has been +permitted where the dual use also significantly changes the type of the +structure member). */ +#define pxMutexHolder pcTail +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL + +/* Semaphores do not actually store or copy data, so have an item size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U ) + + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. + */ +typedef struct QueueDefinition +{ + signed char *pcHead; /*< Points to the beginning of the queue storage area. */ + signed char *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + + signed char *pcWriteTo; /*< Points to the free next place in the storage area. */ + + union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */ + { + signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ + unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ + } u; + + xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ + unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ + + volatile signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + + #if ( configUSE_TRACE_FACILITY == 1 ) + unsigned char ucQueueNumber; + unsigned char ucQueueType; + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + struct QueueDefinition *pxQueueSetContainer; + #endif + +} xQUEUE; +/*-----------------------------------------------------------*/ + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + signed char *pcQueueName; + xQueueHandle xHandle; + } xQueueRegistryItem; + + /* The queue registry is simply an array of xQueueRegistryItem structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + +#endif /* configQUEUE_REGISTRY_SIZE */ + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION; + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION; + +#if ( configUSE_QUEUE_SETS == 1 ) + /* + * Checks to see if a queue is a member of a queue set, and if so, notifies + * the queue set that the queue contains data. + */ + static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION; +#endif + +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxQueue )->xRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->xTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL() +/*-----------------------------------------------------------*/ + +portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue ) +{ +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); + pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize ); + pxQueue->xRxLock = queueUNLOCKED; + pxQueue->xTxLock = queueUNLOCKED; + + if( xNewQueue == pdFALSE ) + { + /* If there are tasks blocked waiting to read from the queue, then + the tasks will remain blocked as after this function exits the queue + will still be empty. If there are tasks blocked waiting to write to + the queue, then one should be unblocked as after this function exits + it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + } + } + else + { + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); + } + } + taskEXIT_CRITICAL(); + + /* A value is returned for calling semantic consistency with previous + versions. */ + return pdPASS; +} +/*-----------------------------------------------------------*/ + +xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) +{ +xQUEUE *pxNewQueue; +size_t xQueueSizeInBytes; +xQueueHandle xReturn = NULL; + + /* Remove compiler warnings about unused parameters should + configUSE_TRACE_FACILITY not be set to 1. */ + ( void ) ucQueueType; + + /* Allocate the new queue structure. */ + if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) + { + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Create the list of pointers to queue items. The queue is one byte + longer than asked for to make wrap checking easier/faster. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes ); + if( pxNewQueue->pcHead != NULL ) + { + /* Initialise the queue members as described above where the + queue type is defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ + + #if( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ + + traceQUEUE_CREATE( pxNewQueue ); + xReturn = pxNewQueue; + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + vPortFree( pxNewQueue ); + } + } + } + + configASSERT( xReturn ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) + { + xQUEUE *pxNewQueue; + + /* Prevent compiler warnings about unused parameters if + configUSE_TRACE_FACILITY does not equal 1. */ + ( void ) ucQueueType; + + /* Allocate the new queue structure. */ + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Information required for priority inheritance. */ + pxNewQueue->pxMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* Queues used as a mutex no data is actually copied into or out + of the queue. */ + pxNewQueue->pcWriteTo = NULL; + pxNewQueue->u.pcReadFrom = NULL; + + /* Each mutex has a length of 1 (like a binary semaphore) and + an item size of 0 as nothing is actually copied into or out + of the mutex. */ + pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U; + pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U; + pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif + + /* Ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + traceCREATE_MUTEX( pxNewQueue ); + + /* Start with the semaphore in the expected state. */ + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + + configASSERT( pxNewQueue ); + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + + void* xQueueGetMutexHolder( xQueueHandle xSemaphore ) + { + void *pxReturn; + + /* This function is called by xSemaphoreGetMutexHolder(), and should not + be called directly. Note: This is is a good way of determining if the + calling task is the mutex holder, but not a good way of determining the + identity of the mutex holder, as the holder may change between the + following critical section exiting and the function returning. */ + taskENTER_CRITICAL(); + { + if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder; + } + else + { + pxReturn = NULL; + } + } + taskEXIT_CRITICAL(); + + return pxReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) + { + portBASE_TYPE xReturn; + xQUEUE * const pxMutex = ( xQUEUE * ) xMutex; + + configASSERT( pxMutex ); + + /* If this is the task that holds the mutex then pxMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */ + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->u.uxRecursiveCallCount )--; + + /* Have we unwound the call count? */ + if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + + xReturn = pdPASS; + } + else + { + /* We cannot give the mutex because we are not the holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) + { + portBASE_TYPE xReturn; + xQUEUE * const pxMutex = ( xQUEUE * ) xMutex; + + configASSERT( pxMutex ); + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */ + { + ( pxMutex->u.uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); + + /* pdPASS will only be returned if we successfully obtained the mutex, + we may have blocked to reach here. */ + if( xReturn == pdPASS ) + { + ( pxMutex->u.uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_COUNTING_SEMAPHORES == 1 ) + + xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) + { + xQueueHandle xHandle; + + xHandle = xQueueGenericCreate( uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + configASSERT( xHandle ); + return xHandle; + } + +#endif /* configUSE_COUNTING_SEMAPHORES */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) +{ +signed portBASE_TYPE xEntryTimeSet = pdFALSE; +xTimeOutType xTimeOut; +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? The running task must be + the highest priority task wanting to access the queue. If + the head item in the queue is to be overwritten then it does + not matter if the queue is full. */ + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + portYIELD_WITHIN_API(); + } + } + else + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to + do this from within the critical section - the + kernel takes care of that. */ + portYIELD_WITHIN_API(); + } + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + portYIELD_WITHIN_API(); + } + } + } + #endif /* configUSE_QUEUE_SETS */ + + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting the + function. */ + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting + the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + /* Return to the original privilege level before exiting the + function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_ALTERNATIVE_API == 1 ) + + signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) + { + signed portBASE_TYPE xEntryTimeSet = pdFALSE; + xTimeOutType xTimeOut; + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. */ + portYIELD_WITHIN_API(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + taskEXIT_CRITICAL(); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } + taskEXIT_CRITICAL(); + } + } + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_ALTERNATIVE_API == 1 ) + + signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) + { + signed portBASE_TYPE xEntryTimeSet = pdFALSE; + xTimeOutType xTimeOut; + signed char *pcOriginalReadPosition; + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + for( ;; ) + { + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Data is actually being removed (not just peeked). */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* We are not removing the data, so reset our read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + portYIELD_WITHIN_API(); + } + } + + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + portENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + portEXIT_CRITICAL(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + portYIELD_WITHIN_API(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } + taskEXIT_CRITICAL(); + } + } + + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are keep permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + /* Similar to xQueueGenericSend, except we don't block if there is no room + in the queue. Also we don't directly wake a task that was blocked on a + queue read, instead we return a flag to say whether a context switch is + required or not (i.e. has a task with a higher priority than us been woken + by this post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If the queue is locked we do not alter the event list. This will + be done when the queue is unlocked later. */ + if( pxQueue->xTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + ++( pxQueue->xTxLock ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) +{ +signed portBASE_TYPE xEntryTimeSet = pdFALSE; +xTimeOutType xTimeOut; +signed char *pcOriginalReadPosition; +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there data in the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Remember the read position in case the queue is only being + peeked. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Actually removing data, not just peeking. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */ + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* The data is not being removed, so reset the read + pointer. */ + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + portYIELD_WITHIN_API(); + } + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + portENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + portEXIT_CRITICAL(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are keep permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + --( pxQueue->uxMessagesWaiting ); + + /* If the queue is locked the event list will not be modified. + Instead update the lock count so the task that unlocks the queue + will know that an ISR has removed data while the queue was + locked. */ + if( pxQueue->xRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + ++( pxQueue->xRxLock ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; +signed char *pcOriginalReadPosition; +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are keep permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + traceQUEUE_PEEK_FROM_ISR( pxQueue ); + + /* Remember the read position so it can be reset as nothing is + actually being removed from the queue. */ + pcOriginalReadPosition = pxQueue->u.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->u.pcReadFrom = pcOriginalReadPosition; + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ) +{ +unsigned portBASE_TYPE uxReturn; + + configASSERT( xQueue ); + + taskENTER_CRITICAL(); + uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting; + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue ) +{ +unsigned portBASE_TYPE uxReturn; +xQUEUE *pxQueue; + + pxQueue = ( xQUEUE * ) xQueue; + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue ) +{ +unsigned portBASE_TYPE uxReturn; + + configASSERT( xQueue ); + + uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting; + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +void vQueueDelete( xQueueHandle xQueue ) +{ +xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + configASSERT( pxQueue ); + + traceQUEUE_DELETE( pxQueue ); + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueUnregisterQueue( pxQueue ); + } + #endif + vPortFree( pxQueue->pcHead ); + vPortFree( pxQueue ); +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue ) + { + return ( ( xQUEUE * ) xQueue )->ucQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber ) + { + ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + unsigned char ucQueueGetQueueType( xQueueHandle xQueue ) + { + return ( ( xQUEUE * ) xQueue )->ucQueueType; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) +{ + if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + pxQueue->pxMutexHolder = NULL; + } + } + #endif /* configUSE_MUTEXES */ + } + else if( xPosition == queueSEND_TO_BACK ) + { + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */ + pxQueue->pcWriteTo += pxQueue->uxItemSize; + if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + } + else + { + ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + pxQueue->u.pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); + } + + if( xPosition == queueOVERWRITE ) + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* An item is not being added but overwritten, so subtract + one from the recorded number of items in the queue so when + one is added again below the number of recorded items remains + correct. */ + --( pxQueue->uxMessagesWaiting ); + } + } + } + + ++( pxQueue->uxMessagesWaiting ); +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) +{ + if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) + { + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */ + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( xQUEUE *pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(); + { + /* See if data was added to the queue while it was locked. */ + while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE ) + { + /* The queue is a member of a queue set, and posting to + the queue set caused a higher priority task to unblock. + A context switch is required. */ + vTaskMissedYield(); + } + } + else + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + } + else + { + break; + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + } + else + { + break; + } + } + #endif /* configUSE_QUEUE_SETS */ + + --( pxQueue->xTxLock ); + } + + pxQueue->xTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + + --( pxQueue->xRxLock ); + } + else + { + break; + } + } + + pxQueue->xRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) +{ +signed portBASE_TYPE xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue ) +{ +signed portBASE_TYPE xReturn; + + configASSERT( xQueue ); + if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) +{ +signed portBASE_TYPE xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue ) +{ +signed portBASE_TYPE xReturn; + + configASSERT( xQueue ); + if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait ) + { + signed portBASE_TYPE xReturn; + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( portTickType ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait ) + { + signed portBASE_TYPE xReturn; + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( portTickType ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) + { + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + } + } + } + + return xCoRoutinePreviouslyWoken; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) + { + signed portBASE_TYPE xReturn; + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->u.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->u.pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + } + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) + { + unsigned portBASE_TYPE ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + break; + } + } + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueUnregisterQueue( xQueueHandle xQueue ) + { + unsigned portBASE_TYPE ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + break; + } + } + + } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TIMERS == 1 ) + + void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait ) + { + xQUEUE * const pxQueue = ( xQUEUE * ) xQueue; + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements. + It can result in vListInsert() being called on a list that can only + possibly ever have one item in it, so the list will be fast, but even + so it should be called with the scheduler locked and not from a critical + section. */ + + /* Only do anything if there are no messages in the queue. This function + will not actually cause the task to block, just place it on a blocked + list. It will not block until the scheduler is unlocked - at which + time a yield will be performed. If an item is added to the queue while + the queue is locked, and the calling task blocks on the queue, then the + calling task will be immediately unblocked when the queue is unlocked. */ + prvLockQueue( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + } + prvUnlockQueue( pxQueue ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength ) + { + xQueueSetHandle pxQueue; + + pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET ); + + return pxQueue; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) + { + portBASE_TYPE xReturn; + + if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + taskENTER_CRITICAL(); + { + ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + } + taskEXIT_CRITICAL(); + xReturn = pdPASS; + } + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet ) + { + portBASE_TYPE xReturn; + xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore; + + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) + { + /* The queue was not a member of the set. */ + xReturn = pdFAIL; + } + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 ) + { + /* It is dangerous to remove a queue from a set when the queue is + not empty because the queue set will still hold pending events for + the queue. */ + xReturn = pdFAIL; + } + else + { + taskENTER_CRITICAL(); + { + /* The queue is no longer contained in the set. */ + pxQueueOrSemaphore->pxQueueSetContainer = NULL; + } + taskEXIT_CRITICAL(); + xReturn = pdPASS; + } + + return xReturn; + } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks ) + { + xQueueSetMemberHandle xReturn = NULL; + + ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet ) + { + xQueueSetMemberHandle xReturn = NULL; + + ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) + { + xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer; + portBASE_TYPE xReturn = pdFALSE; + + configASSERT( pxQueueSetContainer ); + configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); + + if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) + { + traceQUEUE_SEND( pxQueueSetContainer ); + /* The data copies is the handle of the queue that contains data. */ + prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority */ + xReturn = pdTRUE; + } + } + } + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ + diff --git a/source/freertos_blinky/freertos/src/tasks.c b/source/freertos_blinky/freertos/src/tasks.c new file mode 100644 index 0000000..c47121d --- /dev/null +++ b/source/freertos_blinky/freertos/src/tasks.c @@ -0,0 +1,2957 @@ +/* + FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + >>! NOTE: The modification to the GPL is included to allow you to distribute + >>! a combined work that includes FreeRTOS without being obliged to provide + >>! the source code for proprietary components outside of the FreeRTOS + >>! kernel. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* Standard includes. */ +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "StackMacros.h" + +/* Lint e961 and e750 are suppressed as a MISRA exception justified because the +MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the +header files above, but not in this file, in order to generate the correct +privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */ + +#if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) + /* At the bottom of this file are two optional functions that can be used + to generate human readable text from the raw data generated by the + uxTaskGetSystemState() function. Note the formatting functions are provided + for convenience only, and are NOT considered part of the kernel. */ + #include +#endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */ + +/* Sanity check the configuration. */ +#if configUSE_TICKLESS_IDLE != 0 + #if INCLUDE_vTaskSuspend != 1 + #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 + #endif /* INCLUDE_vTaskSuspend */ +#endif /* configUSE_TICKLESS_IDLE */ + +/* + * Defines the size, in words, of the stack allocated to the idle task. + */ +#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE + +/* + * Task control block. A task control block (TCB) is allocated for each task, + * and stores task state information, including a pointer to the task's context + * (the task's run time environment, including register values) + */ +typedef struct tskTaskControlBlock +{ + volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */ + #endif + + xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */ + xListItem xEventListItem; /*< Used to reference a task from an event list. */ + unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */ + portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ + signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ + + #if ( portSTACK_GROWTH > 0 ) + portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */ + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + unsigned portBASE_TYPE uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */ + unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + pdTASK_HOOK_CODE pxTaskTag; + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ + #endif + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + /* Allocate a Newlib reent structure that is specific to this task. + Note Newlib support has been included by popular demand, but is not + used by the FreeRTOS maintainers themselves. FreeRTOS is not + responsible for resulting newlib operation. User must be familiar with + newlib and must provide system-wide implementations of the necessary + stubs. Be warned that (at the time of writing) the current newlib design + implements a system-wide malloc() that must be provided with locks. */ + struct _reent xNewLib_reent; + #endif + +} tskTCB; + + +/* + * Some kernel aware debuggers require the data the debugger needs access to to + * be global, rather than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + +/*lint -e956 A manual analysis and inspection has been used to determine which +static variables must be declared volatile. */ + +PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; + +/* Lists for ready and blocked tasks. --------------------*/ +PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ +PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ +PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +PRIVILEGED_DATA static xList * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ +PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */ + +#if ( INCLUDE_vTaskDelete == 1 ) + + PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ + PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U; + +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + + PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ + +#endif + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ + +#endif + +/* Other file private variables. --------------------------------*/ +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U; +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; +PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; +PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = pdFALSE; +PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; +PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U; +PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_DELAY; + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */ + +#endif + +/*lint +e956 */ + +/* Debugging and trace facilities private variables and macros. ------------*/ + +/* + * The value used to fill the stack of a task when the task is created. This + * is used purely for checking the high water mark for tasks. + */ +#define tskSTACK_FILL_BYTE ( 0xa5U ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) +#define tskREADY_CHAR ( ( signed char ) 'R' ) +#define tskDELETED_CHAR ( ( signed char ) 'D' ) +#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) + +/*-----------------------------------------------------------*/ + +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is + performed in a generic way that is not optimised to any particular + microcontroller architecture. */ + + /* uxTopReadyPriority holds the priority of the highest priority ready + state task. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) \ + { \ + if( ( uxPriority ) > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = ( uxPriority ); \ + } \ + } /* taskRECORD_READY_PRIORITY */ + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + /* Find the highest priority queue that contains ready tasks. */ \ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \ + { \ + configASSERT( uxTopReadyPriority ); \ + --uxTopReadyPriority; \ + } \ + \ + /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \ + the same priority get an equal share of the processor time. */ \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK */ + + /*-----------------------------------------------------------*/ + + /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as + they are only required when a port optimised method of task selection is + being used. */ + #define taskRESET_READY_PRIORITY( uxPriority ) + #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + +#else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + + /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is + performed in a way that is tailored to the particular microcontroller + architecture being used. */ + + /* A port optimised version is provided. Call the port defined macros. */ + #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority ) + + /*-----------------------------------------------------------*/ + + #define taskSELECT_HIGHEST_PRIORITY_TASK() \ + { \ + unsigned portBASE_TYPE uxTopPriority; \ + \ + /* Find the highest priority queue that contains ready tasks. */ \ + portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ + configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ + } /* taskSELECT_HIGHEST_PRIORITY_TASK() */ + + /*-----------------------------------------------------------*/ + + /* A port optimised version is provided, call it only if the TCB being reset + is being referenced from a ready list. If it is referenced from a delayed + or suspended list then it won't be in a ready list. */ + #define taskRESET_READY_PRIORITY( uxPriority ) \ + { \ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \ + { \ + portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ + } \ + } + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + +/* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick +count overflows. */ +#define taskSWITCH_DELAYED_LISTS() \ +{ \ + xList *pxTemp; \ + \ + /* The delayed tasks list should be empty when the lists are switched. */ \ + configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \ + \ + pxTemp = pxDelayedTaskList; \ + pxDelayedTaskList = pxOverflowDelayedTaskList; \ + pxOverflowDelayedTaskList = pxTemp; \ + xNumOfOverflows++; \ + \ + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \ + { \ + /* The new current delayed list is empty. Set \ + xNextTaskUnblockTime to the maximum possible value so it is \ + extremely unlikely that the \ + if( xTickCount >= xNextTaskUnblockTime ) test will pass until \ + there is an item in the delayed list. */ \ + xNextTaskUnblockTime = portMAX_DELAY; \ + } \ + else \ + { \ + /* The new current delayed list is not empty, get the value of \ + the item at the head of the delayed list. This is the time at \ + which the task at the head of the delayed list should be removed \ + from the Blocked state. */ \ + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \ + xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \ + } \ +} + +/*-----------------------------------------------------------*/ + +/* + * Place the task represented by pxTCB into the appropriate ready list for + * the task. It is inserted at the end of the list. + */ +#define prvAddTaskToReadyList( pxTCB ) \ + traceMOVED_TASK_TO_READY_STATE( pxTCB ) \ + taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \ + vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) ) +/*-----------------------------------------------------------*/ + +/* + * Several functions take an xTaskHandle parameter that can optionally be NULL, + * where NULL is used to indicate that the handle of the currently executing + * task should be used in place of the parameter. This macro simply checks to + * see if the parameter is NULL and returns a pointer to the appropriate TCB. + */ +#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) ) + +/* Callback function prototypes. --------------------------*/ +extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName ); +extern void vApplicationTickHook( void ); + +/* File private functions. --------------------------------*/ + +/* + * Utility to ready a TCB for a given task. Mainly just copies the parameters + * into the TCB structure. + */ +static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first task. + */ +static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; + +/* + * The idle task, which as all tasks is implemented as a never ending loop. + * The idle task is automatically created and added to the ready lists upon + * creation of the first user task. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); + +/* + * Utility to free all memory allocated by the scheduler to hold a TCB, + * including the stack pointed to by the TCB. + * + * This does not free memory allocated by the task itself (i.e. memory + * allocated by calls to pvPortMalloc from within the tasks application code). + */ +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Used only by the idle task. This checks to see if anything has been placed + * in the list of tasks waiting to be deleted. If so the task is cleaned up + * and its TCB deleted. + */ +static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; + +/* + * The currently executing task is entering the Blocked state. Add the task to + * either the current or the overflow delayed task list. + */ +static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION; + +/* + * Allocates memory from the heap for a TCB and associated stack. Checks the + * allocation was successful. + */ +static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; + +/* + * Fills an xTaskStatusType structure with information on each task that is + * referenced from the pxList list (which may be a ready list, a delayed list, + * a suspended list, etc.). + * + * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM + * NORMAL APPLICATION CODE. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) PRIVILEGED_FUNCTION; + +#endif + +/* + * When a task is created, the stack of the task is filled with a known value. + * This function determines the 'high water mark' of the task stack by + * determining how much of the stack remains at the original preset value. + */ +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; + +#endif + +/* + * Return the amount of time, in ticks, that will pass before the kernel will + * next move a task from the Blocked state to the Running state. + * + * This conditional compilation should use inequality to 0, not equality to 1. + * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user + * defined low power mode implementations require configUSE_TICKLESS_IDLE to be + * set to a value other than 1. + */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION; + +#endif + +signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) +{ +signed portBASE_TYPE xReturn; +tskTCB * pxNewTCB; + + configASSERT( pxTaskCode ); + configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) ); + + /* Allocate the memory required by the TCB and stack for the new task, + checking that the allocation was successful. */ + pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); + + if( pxNewTCB != NULL ) + { + portSTACK_TYPE *pxTopOfStack; + + #if( portUSING_MPU_WRAPPERS == 1 ) + /* Should the task be created in privileged mode? */ + portBASE_TYPE xRunPrivileged; + if( ( uxPriority & portPRIVILEGE_BIT ) != 0U ) + { + xRunPrivileged = pdTRUE; + } + else + { + xRunPrivileged = pdFALSE; + } + uxPriority &= ~portPRIVILEGE_BIT; + #endif /* portUSING_MPU_WRAPPERS == 1 */ + + /* Calculate the top of stack address. This depends on whether the + stack grows from high memory to low (as per the 80x86) or visa versa. + portSTACK_GROWTH is used to make the result positive or negative as + required by the port. */ + #if( portSTACK_GROWTH < 0 ) + { + pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 ); + pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */ + + /* Check the alignment of the calculated top of stack is correct. */ + configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + } + #else /* portSTACK_GROWTH */ + { + pxTopOfStack = pxNewTCB->pxStack; + + /* Check the alignment of the stack buffer is correct. */ + configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + + /* If we want to use stack checking on architectures that use + a positive stack growth direction then we also need to store the + other extreme of the stack space. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); + } + #endif /* portSTACK_GROWTH */ + + /* Setup the newly allocated TCB with the initial state of the task. */ + prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + #if( portUSING_MPU_WRAPPERS == 1 ) + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); + } + #endif /* portUSING_MPU_WRAPPERS */ + + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the TCB out - in an anonymous way. The calling function/ + task can use this as a handle to delete the task later if + required.*/ + *pxCreatedTask = ( xTaskHandle ) pxNewTCB; + } + + /* Ensure interrupts don't access the task lists while they are being + updated. */ + taskENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + if( pxCurrentTCB == NULL ) + { + /* There are no other tasks, or all the other tasks are in + the suspended state - make this the current task. */ + pxCurrentTCB = pxNewTCB; + + if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) + { + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + } + else + { + /* If the scheduler is not already running, make this task the + current task if it is the highest priority task to be created + so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB->uxPriority <= uxPriority ) + { + pxCurrentTCB = pxNewTCB; + } + } + } + + uxTaskNumber++; + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif /* configUSE_TRACE_FACILITY */ + traceTASK_CREATE( pxNewTCB ); + + prvAddTaskToReadyList( pxNewTCB ); + + xReturn = pdPASS; + portSETUP_TCB( pxNewTCB ); + } + taskEXIT_CRITICAL(); + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + traceTASK_CREATE_FAILED(); + } + + if( xReturn == pdPASS ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than the current task + then it should run now. */ + if( pxCurrentTCB->uxPriority < uxPriority ) + { + portYIELD_WITHIN_API(); + } + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + void vTaskDelete( xTaskHandle xTaskToDelete ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( xTaskToDelete ); + + /* Remove task from the ready list and place in the termination list. + This will stop the task from be scheduled. The idle task will check + the termination list and free up any memory allocated by the + scheduler for the TCB and stack. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxTasksDeleted; + + /* Increment the uxTaskNumberVariable also so kernel aware debuggers + can detect that the task lists need re-generating. */ + uxTaskNumber++; + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); + + /* Force a reschedule if we have just deleted the current task. */ + if( xSchedulerRunning != pdFALSE ) + { + if( pxTCB == pxCurrentTCB ) + { + portYIELD_WITHIN_API(); + } + } + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + + void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) + { + portTickType xTimeToWake; + portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; + + configASSERT( pxPreviousWakeTime ); + configASSERT( ( xTimeIncrement > 0U ) ); + + vTaskSuspendAll(); + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const portTickType xConstTickCount = xTickCount; + + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + + if( xConstTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + } + else + { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) ) + { + xShouldDelay = pdTRUE; + } + } + + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; + + if( xShouldDelay != pdFALSE ) + { + traceTASK_DELAY_UNTIL(); + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + } + xAlreadyYielded = xTaskResumeAll(); + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + +#endif /* INCLUDE_vTaskDelayUntil */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + + void vTaskDelay( portTickType xTicksToDelay ) + { + portTickType xTimeToWake; + signed portBASE_TYPE xAlreadyYielded = pdFALSE; + + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( portTickType ) 0U ) + { + vTaskSuspendAll(); + { + traceTASK_DELAY(); + + /* A task that is removed from the event list while the + scheduler is suspended will not get placed in the ready + list or removed from the blocked list until the scheduler + is resumed. + + This task cannot be in an event list as it is the currently + executing task. */ + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + /* The current task must be in a ready list, so there is + no need to check, and the port reset macro can be called + directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + xAlreadyYielded = xTaskResumeAll(); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( xAlreadyYielded == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + +#endif /* INCLUDE_vTaskDelay */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_eTaskGetState == 1 ) + + eTaskState eTaskGetState( xTaskHandle xTask ) + { + eTaskState eReturn; + xList *pxStateList; + const tskTCB * const pxTCB = ( tskTCB * ) xTask; + + if( pxTCB == pxCurrentTCB ) + { + /* The task calling this function is querying its own state. */ + eReturn = eRunning; + } + else + { + taskENTER_CRITICAL(); + { + pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(); + + if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) ) + { + /* The task being queried is referenced from one of the Blocked + lists. */ + eReturn = eBlocked; + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + else if( pxStateList == &xSuspendedTaskList ) + { + /* The task being queried is referenced from the suspended + list. */ + eReturn = eSuspended; + } + #endif + + #if ( INCLUDE_vTaskDelete == 1 ) + else if( pxStateList == &xTasksWaitingTermination ) + { + /* The task being queried is referenced from the deleted + tasks list. */ + eReturn = eDeleted; + } + #endif + + else + { + /* If the task is not in any other state, it must be in the + Ready (including pending ready) state. */ + eReturn = eReady; + } + } + + return eReturn; + } + +#endif /* INCLUDE_eTaskGetState */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask ) + { + tskTCB *pxTCB; + unsigned portBASE_TYPE uxReturn; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( xTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskPriorityGet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + + void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority ) + { + tskTCB *pxTCB; + unsigned portBASE_TYPE uxCurrentBasePriority, uxPriorityUsedOnEntry; + portBASE_TYPE xYieldRequired = pdFALSE; + + configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) ); + + /* Ensure the new priority is valid. */ + if( uxNewPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES ) + { + uxNewPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; + } + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the priority of the calling + task that is being changed. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + traceTASK_PRIORITY_SET( pxTCB, uxNewPriority ); + + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentBasePriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentBasePriority = pxTCB->uxPriority; + } + #endif + + if( uxCurrentBasePriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + priority than the calling task. */ + if( uxNewPriority > uxCurrentBasePriority ) + { + if( pxTCB != pxCurrentTCB ) + { + /* The priority of a task other than the currently + running task is being raised. Is the priority being + raised above that of the running task? */ + if( uxNewPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + } + else + { + /* The priority of the running task is being raised, + but the running task must already be the highest + priority task able to run so no yield is required. */ + } + } + else if( pxTCB == pxCurrentTCB ) + { + /* Setting the priority of the running task down means + there may now be another task of higher priority that + is ready to execute. */ + xYieldRequired = pdTRUE; + } + else + { + /* Setting the priority of any other task down does not + require a yield as the running task must be above the + new priority of the task being modified. */ + } + + /* Remember the ready list the task might be referenced from + before its uxPriority member is changed so the + taskRESET_READY_PRIORITY() macro can function correctly. */ + uxPriorityUsedOnEntry = pxTCB->uxPriority; + + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else + { + pxTCB->uxPriority = uxNewPriority; + } + #endif + + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* If the task is in the blocked or suspended list we need do + nothing more than change it's priority variable. However, if + the task is in a ready list it needs to be removed and placed + in the list appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* The task is currently in its ready list - remove before adding + it to it's new ready list. As we are in a critical section we + can do this even if the scheduler is suspended. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + /* It is known that the task is in its ready list so + there is no need to check again and the port level + reset macro can be called directly. */ + portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority ); + } + prvAddTaskToReadyList( pxTCB ); + } + + if( xYieldRequired == pdTRUE ) + { + portYIELD_WITHIN_API(); + } + + /* Remove compiler warning about unused variables when the port + optimised task selection is not being used. */ + ( void ) uxPriorityUsedOnEntry; + } + } + taskEXIT_CRITICAL(); + } + +#endif /* INCLUDE_vTaskPrioritySet */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskSuspend( xTaskHandle xTaskToSuspend ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then it is the running task that is + being suspended. */ + pxTCB = prvGetTCBFromHandle( xTaskToSuspend ); + + traceTASK_SUSPEND( pxTCB ); + + /* Remove task from the ready/delayed list and place in the suspended list. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + + /* Is the task waiting on an event also? */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(); + + if( pxTCB == pxCurrentTCB ) + { + if( xSchedulerRunning != pdFALSE ) + { + /* The current task has just been suspended. */ + portYIELD_WITHIN_API(); + } + else + { + /* The scheduler is not running, but the task that was pointed + to by pxCurrentTCB has just been suspended and pxCurrentTCB + must be adjusted to point to a different task. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) + { + /* No other tasks are ready, so set pxCurrentTCB back to + NULL so when the next task is created pxCurrentTCB will + be set to point to it no matter what its relative priority + is. */ + pxCurrentTCB = NULL; + } + else + { + vTaskSwitchContext(); + } + } + } + } + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) + { + portBASE_TYPE xReturn = pdFALSE; + const tskTCB * const pxTCB = ( tskTCB * ) xTask; + + /* It does not make sense to check if the calling task is suspended. */ + configASSERT( xTask ); + + /* Is the task we are attempting to resume actually in the + suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE ) + { + /* Is it in the suspended list because it is in the + Suspended state? It is possible to be in the suspended + list because it is blocked on a task with no timeout + specified. */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) + { + xReturn = pdTRUE; + } + } + } + + return xReturn; + } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */ + +#endif /* INCLUDE_vTaskSuspend */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskResume( xTaskHandle xTaskToResume ) + { + tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume; + + /* It does not make sense to resume the calling task. */ + configASSERT( xTaskToResume ); + + /* The parameter cannot be NULL as it is impossible to resume the + currently executing task. */ + if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) + { + taskENTER_CRITICAL(); + { + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME( pxTCB ); + + /* As we are in a critical section we can access the ready + lists even if the scheduler is suspended. */ + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* This yield may not cause the task just resumed to run, but + will leave the lists in the correct state for the next yield. */ + portYIELD_WITHIN_API(); + } + } + } + taskEXIT_CRITICAL(); + } + } + +#endif /* INCLUDE_vTaskSuspend */ + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + + portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume ) + { + portBASE_TYPE xYieldRequired = pdFALSE; + tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume; + unsigned portBASE_TYPE uxSavedInterruptStatus; + + configASSERT( xTaskToResume ); + + /* RTOS ports that support interrupt nesting have the concept of a + maximum system call (or maximum API call) interrupt priority. + Interrupts that are above the maximum system call priority are keep + permanently enabled, even when the RTOS kernel is in a critical section, + but cannot make any calls to FreeRTOS API functions. If configASSERT() + is defined in FreeRTOSConfig.h then + portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has + been assigned a priority above the configured maximum system call + priority. Only FreeRTOS functions that end in FromISR can be called + from interrupts that have been assigned a priority at or (logically) + below the maximum system call interrupt priority. FreeRTOS maintains a + separate interrupt safe API to ensure interrupt entry is as fast and as + simple as possible. More information (albeit Cortex-M specific) is + provided on the following link: + http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed, at which point a + yield will be performed if necessary. */ + vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xYieldRequired; + } + +#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ +/*-----------------------------------------------------------*/ + +void vTaskStartScheduler( void ) +{ +portBASE_TYPE xReturn; + + /* Add the idle task at the lowest priority. */ + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + { + /* Create the idle task, storing its handle in xIdleTaskHandle so it can + be returned by the xTaskGetIdleTaskHandle() function. */ + xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + } + #else + { + /* Create the idle task without storing its handle. */ + xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ + } + #endif /* INCLUDE_xTaskGetIdleTaskHandle */ + + #if ( configUSE_TIMERS == 1 ) + { + if( xReturn == pdPASS ) + { + xReturn = xTimerCreateTimerTask(); + } + } + #endif /* configUSE_TIMERS */ + + if( xReturn == pdPASS ) + { + /* Interrupts are turned off here, to ensure a tick does not occur + before or during the call to xPortStartScheduler(). The stacks of + the created tasks contain a status word with interrupts switched on + so interrupts will automatically get re-enabled when the first task + starts to run. */ + portDISABLE_INTERRUPTS(); + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to the task that will run first. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + + xSchedulerRunning = pdTRUE; + xTickCount = ( portTickType ) 0U; + + /* If configGENERATE_RUN_TIME_STATS is defined then the following + macro must be defined to configure the timer/counter used to generate + the run time counter time base. */ + portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + + /* Setting up the timer tick is hardware specific and thus in the + portable interface. */ + if( xPortStartScheduler() != pdFALSE ) + { + /* Should not reach here as if the scheduler is running the + function will not return. */ + } + else + { + /* Should only reach here if a task calls xTaskEndScheduler(). */ + } + } + else + { + /* This line will only be reached if the kernel could not be started, + because there was not enough FreeRTOS heap to create the idle task + or the timer task. */ + configASSERT( xReturn ); + } +} +/*-----------------------------------------------------------*/ + +void vTaskEndScheduler( void ) +{ + /* Stop the scheduler interrupts and call the portable scheduler end + routine so the original ISRs can be restored if necessary. The port + layer must ensure interrupts enable bit is left in the correct state. */ + portDISABLE_INTERRUPTS(); + xSchedulerRunning = pdFALSE; + vPortEndScheduler(); +} +/*----------------------------------------------------------*/ + +void vTaskSuspendAll( void ) +{ + /* A critical section is not required as the variable is of type + portBASE_TYPE. */ + ++uxSchedulerSuspended; +} +/*----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE != 0 ) + + static portTickType prvGetExpectedIdleTime( void ) + { + portTickType xReturn; + + if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY ) + { + xReturn = 0; + } + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) + { + /* There are other idle priority tasks in the ready state. If + time slicing is used then the very next tick interrupt must be + processed. */ + xReturn = 0; + } + else + { + xReturn = xNextTaskUnblockTime - xTickCount; + } + + return xReturn; + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskResumeAll( void ) +{ +tskTCB *pxTCB; +portBASE_TYPE xAlreadyYielded = pdFALSE; + + /* If uxSchedulerSuspended is zero then this function does not match a + previous call to vTaskSuspendAll(). */ + configASSERT( uxSchedulerSuspended ); + + /* It is possible that an ISR caused a task to be removed from an event + list while the scheduler was suspended. If this was the case then the + removed task will have been added to the xPendingReadyList. Once the + scheduler has been resumed it is safe to move all the pending ready + tasks from this list into their appropriate ready list. */ + taskENTER_CRITICAL(); + { + --uxSchedulerSuspended; + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U ) + { + /* Move any readied tasks from the pending list into the + appropriate ready list. */ + while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE ) + { + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxTCB ); + + /* If we have moved a task that has a priority higher than + the current task then we should yield. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldPending = pdTRUE; + } + } + + /* If any ticks occurred while the scheduler was suspended then + they should be processed now. This ensures the tick count does not + slip, and that any delayed tasks are resumed at the correct time. */ + if( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U ) + { + while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U ) + { + if( xTaskIncrementTick() != pdFALSE ) + { + xYieldPending = pdTRUE; + } + --uxPendedTicks; + } + } + + if( xYieldPending == pdTRUE ) + { + xAlreadyYielded = pdTRUE; + portYIELD_WITHIN_API(); + } + } + } + } + taskEXIT_CRITICAL(); + + return xAlreadyYielded; +} +/*-----------------------------------------------------------*/ + +portTickType xTaskGetTickCount( void ) +{ +portTickType xTicks; + + /* Critical section required if running on a 16 bit processor. */ + taskENTER_CRITICAL(); + { + xTicks = xTickCount; + } + taskEXIT_CRITICAL(); + + return xTicks; +} +/*-----------------------------------------------------------*/ + +portTickType xTaskGetTickCountFromISR( void ) +{ +portTickType xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are keep permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + xReturn = xTickCount; + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) +{ + /* A critical section is not required because the variables are of type + portBASE_TYPE. */ + return uxCurrentNumberOfTasks; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_pcTaskGetTaskName == 1 ) + + signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery ) + { + tskTCB *pxTCB; + + /* If null is passed in here then the name of the calling task is being queried. */ + pxTCB = prvGetTCBFromHandle( xTaskToQuery ); + configASSERT( pxTCB ); + return &( pxTCB->pcTaskName[ 0 ] ); + } + +#endif /* INCLUDE_pcTaskGetTaskName */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime ) + { + unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES; + + vTaskSuspendAll(); + { + /* Is there a space in the array for each task in the system? */ + if( uxArraySize >= uxCurrentNumberOfTasks ) + { + /* Fill in an xTaskStatusType structure with information on each + task in the Ready state. */ + do + { + uxQueue--; + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); + + } while( uxQueue > ( unsigned portBASE_TYPE ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* Fill in an xTaskStatusType structure with information on each + task in the Blocked state. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked ); + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxOverflowDelayedTaskList, eBlocked ); + + #if( INCLUDE_vTaskDelete == 1 ) + { + /* Fill in an xTaskStatusType structure with information on + each task that has been deleted but not yet cleaned up. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + /* Fill in an xTaskStatusType structure with information on + each task in the Suspended state. */ + uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1) + { + if( pulTotalRunTime != NULL ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) ); + #else + *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + } + } + #else + { + if( pulTotalRunTime != NULL ) + { + *pulTotalRunTime = 0; + } + } + #endif + } + } + ( void ) xTaskResumeAll(); + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + + xTaskHandle xTaskGetIdleTaskHandle( void ) + { + /* If xTaskGetIdleTaskHandle() is called before the scheduler has been + started, then xIdleTaskHandle will be NULL. */ + configASSERT( ( xIdleTaskHandle != NULL ) ); + return xIdleTaskHandle; + } + +#endif /* INCLUDE_xTaskGetIdleTaskHandle */ +/*----------------------------------------------------------*/ + +/* This conditional compilation should use inequality to 0, not equality to 1. +This is to ensure vTaskStepTick() is available when user defined low power mode +implementations require configUSE_TICKLESS_IDLE to be set to a value other than +1. */ +#if ( configUSE_TICKLESS_IDLE != 0 ) + + void vTaskStepTick( portTickType xTicksToJump ) + { + /* Correct the tick count value after a period during which the tick + was suppressed. Note this does *not* call the tick hook function for + each stepped tick. */ + configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime ); + xTickCount += xTicksToJump; + traceINCREASE_TICK_COUNT( xTicksToJump ); + } + +#endif /* configUSE_TICKLESS_IDLE */ +/*----------------------------------------------------------*/ + +portBASE_TYPE xTaskIncrementTick( void ) +{ +tskTCB * pxTCB; +portTickType xItemValue; +portBASE_TYPE xSwitchRequired = pdFALSE; + + /* Called by the portable layer each time a tick interrupt occurs. + Increments the tick then checks to see if the new tick value will cause any + tasks to be unblocked. */ + traceTASK_INCREMENT_TICK( xTickCount ); + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + /* Increment the RTOS tick, switching the delayed and overflowed + delayed lists if it wraps to 0. */ + ++xTickCount; + + { + /* Minor optimisation. The tick count cannot change in this + block. */ + const portTickType xConstTickCount = xTickCount; + + if( xConstTickCount == ( portTickType ) 0U ) + { + taskSWITCH_DELAYED_LISTS(); + } + + /* See if this tick has made a timeout expire. Tasks are stored in the + queue in the order of their wake time - meaning once one tasks has been + found whose block time has not expired there is no need not look any + further down the list. */ + if( xConstTickCount >= xNextTaskUnblockTime ) + { + for( ;; ) + { + if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) + { + /* The delayed list is empty. Set xNextTaskUnblockTime to + the maximum possible value so it is extremely unlikely that + the if( xTickCount >= xNextTaskUnblockTime ) test will pass + next time through. */ + xNextTaskUnblockTime = portMAX_DELAY; + break; + } + else + { + /* The delayed list is not empty, get the value of the item + at the head of the delayed list. This is the time at which + the task at the head of the delayed list must be removed + from the Blocked state. */ + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); + xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); + + if( xConstTickCount < xItemValue ) + { + /* It is not time to unblock this item yet, but the item + value is the time at which the task at the head of the + blocked list must be removed from the Blocked state - + so record the item value in xNextTaskUnblockTime. */ + xNextTaskUnblockTime = xItemValue; + break; + } + + /* It is time to remove the item from the Blocked state. */ + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? If so remove it + from the event list. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + } + + /* Place the unblocked task into the appropriate ready + list. */ + prvAddTaskToReadyList( pxTCB ); + + /* A task being unblocked cannot cause an immediate context + switch if preemption is turned off. */ + #if ( configUSE_PREEMPTION == 1 ) + { + /* Preemption is on, but a context switch should only + be performed if the unblocked task has a priority that + is equal to or higher than the currently executing + task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xSwitchRequired = pdTRUE; + } + } + #endif /* configUSE_PREEMPTION */ + } + } + } + } + + /* Tasks of equal priority to the currently running task will share + processing time (time slice) if preemption is on, and the application + writer has not explicitly turned time slicing off. */ + #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 ) + { + xSwitchRequired = pdTRUE; + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */ + + #if ( configUSE_TICK_HOOK == 1 ) + { + /* Guard against the tick hook being called when the pended tick + count is being unwound (when the scheduler is being unlocked). */ + if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U ) + { + vApplicationTickHook(); + } + } + #endif /* configUSE_TICK_HOOK */ + } + else + { + ++uxPendedTicks; + + /* The tick hook gets called at regular intervals, even if the + scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + vApplicationTickHook(); + } + #endif + } + + #if ( configUSE_PREEMPTION == 1 ) + { + if( xYieldPending != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + } + #endif /* configUSE_PREEMPTION */ + + return xSwitchRequired; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ) + { + tskTCB *xTCB; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + xTCB->pxTaskTag = pxHookFunction; + taskEXIT_CRITICAL(); + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) + { + tskTCB *xTCB; + pdTASK_HOOK_CODE xReturn; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + taskENTER_CRITICAL(); + xReturn = xTCB->pxTaskTag; + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) + { + tskTCB *xTCB; + portBASE_TYPE xReturn; + + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_APPLICATION_TASK_TAG */ +/*-----------------------------------------------------------*/ + +void vTaskSwitchContext( void ) +{ + if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + switch. */ + xYieldPending = pdTRUE; + } + else + { + xYieldPending = pdFALSE; + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE + portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); + #else + ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + #endif + + /* Add the amount of time the task has been running to the + accumulated time so far. The time the task started running was + stored in ulTaskSwitchedInTime. Note that there is no overflow + protection here so count values are only valid until the timer + overflows. The guard against negative values is to protect + against suspect run time stat counter implementations - which + are provided by the application, not the kernel. */ + if( ulTotalRunTime > ulTaskSwitchedInTime ) + { + pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); + } + ulTaskSwitchedInTime = ulTotalRunTime; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + taskFIRST_CHECK_FOR_STACK_OVERFLOW(); + taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + + taskSELECT_HIGHEST_PRIORITY_TASK(); + + traceTASK_SWITCHED_IN(); + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Switch Newlib's _impure_ptr variable to point to the _reent + structure specific to this task. */ + _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ + } +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) +{ +portTickType xTimeToWake; + + configASSERT( pxEventList ); + + /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED. */ + + /* Place the event list item of the TCB in the appropriate event list. + This is placed in the list in priority order so the highest priority task + is the first to be woken by the event. */ + vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + /* We must remove ourselves from the ready list before adding ourselves + to the blocked list as the same list item is used for both lists. We have + exclusive access to the ready lists as the scheduler is locked. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add ourselves to the suspended task list instead of a delayed task + list to ensure we are not woken by a timing event. We will block + indefinitely. */ + vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + } + #else /* INCLUDE_vTaskSuspend */ + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + #endif /* INCLUDE_vTaskSuspend */ +} +/*-----------------------------------------------------------*/ + +#if configUSE_TIMERS == 1 + + void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait ) + { + portTickType xTimeToWake; + + configASSERT( pxEventList ); + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements - + it should be called from a critical section. */ + + + /* Place the event list item of the TCB in the appropriate event list. + In this case it is assume that this is the only task that is going to + be waiting on this event list, so the faster vListInsertEnd() function + can be used in place of vListInsert. */ + vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) ); + + /* We must remove this task from the ready list before adding it to the + blocked list as the same list item is used for both lists. This + function is called form a critical section. */ + if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + /* The current task must be in a ready list, so there is no need to + check, and the port reset macro can be called directly. */ + portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); + } + + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + + traceTASK_DELAY_UNTIL(); + prvAddCurrentTaskToDelayedList( xTimeToWake ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) +{ +tskTCB *pxUnblockedTCB; +portBASE_TYPE xReturn; + + /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED. It can also be called from within an ISR. */ + + /* The event list is sorted in priority order, so we can remove the + first in the list, remove the TCB from the delayed list, and add + it to the ready list. + + If an event is for a queue that is locked then this function will never + get called - the lock count on the queue will get modified instead. This + means we can always expect exclusive access to the event list here. + + This function assumes that a check has already been made to ensure that + pxEventList is not empty. */ + pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + configASSERT( pxUnblockedTCB ); + ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyList( pxUnblockedTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed. */ + vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + } + + if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has + a higher priority than the calling task. This allows + the calling task to know if it should force a context + switch now. */ + xReturn = pdTRUE; + + /* Mark that a yield is pending in case the user is not using the + "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */ + xYieldPending = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) +{ + configASSERT( pxTimeOut ); + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) +{ +portBASE_TYPE xReturn; + + configASSERT( pxTimeOut ); + configASSERT( pxTicksToWait ); + + taskENTER_CRITICAL(); + { + /* Minor optimisation. The tick count cannot change in this block. */ + const portTickType xConstTickCount = xTickCount; + + #if ( INCLUDE_vTaskSuspend == 1 ) + /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is + the maximum block time then the task should block indefinitely, and + therefore never time out. */ + if( *pxTicksToWait == portMAX_DELAY ) + { + xReturn = pdFALSE; + } + else /* We are not blocking indefinitely, perform the checks below. */ + #endif + + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ + { + /* The tick count is greater than the time at which vTaskSetTimeout() + was called, but has also overflowed since vTaskSetTimeOut() was called. + It must have wrapped all the way around and gone past us again. This + passed since vTaskSetTimeout() was called. */ + xReturn = pdTRUE; + } + else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait ) + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); + vTaskSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskMissedYield( void ) +{ + xYieldPending = pdTRUE; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask ) + { + unsigned portBASE_TYPE uxReturn; + tskTCB *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( tskTCB * ) xTask; + uxReturn = pxTCB->uxTaskNumber; + } + else + { + uxReturn = 0U; + } + + return uxReturn; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle ) + { + tskTCB *pxTCB; + + if( xTask != NULL ) + { + pxTCB = ( tskTCB * ) xTask; + pxTCB->uxTaskNumber = uxHandle; + } + } + +#endif /* configUSE_TRACE_FACILITY */ + +/* + * ----------------------------------------------------------- + * The Idle task. + * ---------------------------------------------------------- + * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION( prvIdleTask, pvParameters ) +{ + /* Stop warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* See if any tasks have been deleted. */ + prvCheckTasksWaitingTermination(); + + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + see if any other task has become available. If we are using + preemption we don't need to do this as any task becoming available + will automatically get the processor anyway. */ + taskYIELD(); + } + #endif /* configUSE_PREEMPTION */ + + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + timesliced. If a task that is sharing the idle priority is ready + to run then the idle task should yield before the end of the + timeslice. + + A critical region is not required here as we are just reading from + the list, and an occasional incorrect value will not matter. If + the ready list at the idle priority contains more than one task + then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) + { + taskYIELD(); + } + } + #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */ + + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); + + /* Call the user defined function from within the idle task. This + allows the application designer to add background functionality + without the overhead of a separate task. + NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif /* configUSE_IDLE_HOOK */ + + /* This conditional compilation should use inequality to 0, not equality + to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when + user defined low power mode implementations require + configUSE_TICKLESS_IDLE to be set to a value other than 1. */ + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + portTickType xExpectedIdleTime; + + /* It is not desirable to suspend then resume the scheduler on + each iteration of the idle task. Therefore, a preliminary + test of the expected idle time is performed without the + scheduler suspended. The result here is not necessarily + valid. */ + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + vTaskSuspendAll(); + { + /* Now the scheduler is suspended, the expected idle + time can be sampled again, and this time its value can + be used. */ + configASSERT( xNextTaskUnblockTime >= xTickCount ); + xExpectedIdleTime = prvGetExpectedIdleTime(); + + if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) + { + traceLOW_POWER_IDLE_BEGIN(); + portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + traceLOW_POWER_IDLE_END(); + } + } + ( void ) xTaskResumeAll(); + } + } + #endif /* configUSE_TICKLESS_IDLE */ + } +} +/*-----------------------------------------------------------*/ + +#if configUSE_TICKLESS_IDLE != 0 + + eSleepModeStatus eTaskConfirmSleepModeStatus( void ) + { + eSleepModeStatus eReturn = eStandardSleep; + + if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) + { + /* A task was made ready while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else if( xYieldPending != pdFALSE ) + { + /* A yield was pended while the scheduler was suspended. */ + eReturn = eAbortSleep; + } + else + { + #if configUSE_TIMERS == 0 + { + /* The idle task exists in addition to the application tasks. */ + const unsigned portBASE_TYPE uxNonApplicationTasks = 1; + + /* If timers are not being used and all the tasks are in the + suspended list (which might mean they have an infinite block + time rather than actually being suspended) then it is safe to + turn all clocks off and just wait for external interrupts. */ + if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) ) + { + eReturn = eNoTasksWaitingTimeout; + } + } + #endif /* configUSE_TIMERS */ + } + + return eReturn; + } +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) +{ +unsigned portBASE_TYPE x; + + /* Store the task name in the TCB. */ + for( x = ( unsigned portBASE_TYPE ) 0; x < ( unsigned portBASE_TYPE ) configMAX_TASK_NAME_LEN; x++ ) + { + pxTCB->pcTaskName[ x ] = pcName[ x ]; + + /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than + configMAX_TASK_NAME_LEN characters just in case the memory after the + string is not accessible (extremely unlikely). */ + if( pcName[ x ] == 0x00 ) + { + break; + } + } + + /* Ensure the name string is terminated in the case that the string length + was greater or equal to configMAX_TASK_NAME_LEN. */ + pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ( signed char ) '\0'; + + /* This is used as an array index so must ensure it's not too large. First + remove the privilege bit if one is present. */ + if( uxPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES ) + { + uxPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U; + } + + pxTCB->uxPriority = uxPriority; + #if ( configUSE_MUTEXES == 1 ) + { + pxTCB->uxBasePriority = uxPriority; + } + #endif /* configUSE_MUTEXES */ + + vListInitialiseItem( &( pxTCB->xGenericListItem ) ); + vListInitialiseItem( &( pxTCB->xEventListItem ) ); + + /* Set the pxTCB as a link back from the xListItem. This is so we can get + back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U; + } + #endif /* portCRITICAL_NESTING_IN_TCB */ + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxTCB->pxTaskTag = NULL; + } + #endif /* configUSE_APPLICATION_TASK_TAG */ + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTCB->ulRunTimeCounter = 0UL; + } + #endif /* configGENERATE_RUN_TIME_STATS */ + + #if ( portUSING_MPU_WRAPPERS == 1 ) + { + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); + } + #else /* portUSING_MPU_WRAPPERS */ + { + ( void ) xRegions; + ( void ) usStackDepth; + } + #endif /* portUSING_MPU_WRAPPERS */ + + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + /* Initialise this task's Newlib reent structure. */ + _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ +} +/*-----------------------------------------------------------*/ + +#if ( portUSING_MPU_WRAPPERS == 1 ) + + void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) + { + tskTCB *pxTCB; + + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( xTaskToModify ); + + vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); + } + +#endif /* portUSING_MPU_WRAPPERS */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseTaskLists( void ) +{ +unsigned portBASE_TYPE uxPriority; + + for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < ( unsigned portBASE_TYPE ) configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( &xDelayedTaskList1 ); + vListInitialise( &xDelayedTaskList2 ); + vListInitialise( &xPendingReadyList ); + + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( &xTasksWaitingTermination ); + } + #endif /* INCLUDE_vTaskDelete */ + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( &xSuspendedTaskList ); + } + #endif /* INCLUDE_vTaskSuspend */ + + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; +} +/*-----------------------------------------------------------*/ + +static void prvCheckTasksWaitingTermination( void ) +{ + #if ( INCLUDE_vTaskDelete == 1 ) + { + portBASE_TYPE xListIsEmpty; + + /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called + too often in the idle task. */ + while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U ) + { + vTaskSuspendAll(); + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + ( void ) xTaskResumeAll(); + + if( xListIsEmpty == pdFALSE ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); + ( void ) uxListRemove( &( pxTCB->xGenericListItem ) ); + --uxCurrentNumberOfTasks; + --uxTasksDeleted; + } + taskEXIT_CRITICAL(); + + prvDeleteTCB( pxTCB ); + } + } + } + #endif /* vTaskDelete */ +} +/*-----------------------------------------------------------*/ + +static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) +{ + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the current block list. */ + vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) ); + + /* If the task entering the blocked state was placed at the head of the + list of blocked tasks then xNextTaskUnblockTime needs to be updated + too. */ + if( xTimeToWake < xNextTaskUnblockTime ) + { + xNextTaskUnblockTime = xTimeToWake; + } + } +} +/*-----------------------------------------------------------*/ + +static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) +{ +tskTCB *pxNewTCB; + + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function. */ + pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); + + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + else + { + /* Just to help debugging. */ + ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) ); + } + } + + return pxNewTCB; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) + { + volatile tskTCB *pxNextTCB, *pxFirstTCB; + unsigned portBASE_TYPE uxTask = 0; + + if( listCURRENT_LIST_LENGTH( pxList ) > ( unsigned portBASE_TYPE ) 0 ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + + /* Populate an xTaskStatusType structure within the + pxTaskStatusArray array for each task that is referenced from + pxList. See the definition of xTaskStatusType in task.h for the + meaning of each xTaskStatusType structure member. */ + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB; + pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] ); + pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber; + pxTaskStatusArray[ uxTask ].eCurrentState = eState; + pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority; + + #if ( configUSE_MUTEXES == 1 ) + { + pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority; + } + #else + { + pxTaskStatusArray[ uxTask ].uxBasePriority = 0; + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter; + } + #else + { + pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0; + } + #endif + + #if ( portSTACK_GROWTH > 0 ) + { + ppxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); + } + #else + { + pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); + } + #endif + + uxTask++; + + } while( pxNextTCB != pxFirstTCB ); + } + + return uxTask; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) + { + unsigned short usCount = 0U; + + while( *pucStackByte == tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + usCount++; + } + + usCount /= sizeof( portSTACK_TYPE ); + + return usCount; + } + +#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + + unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) + { + tskTCB *pxTCB; + unsigned char *pcEndOfStack; + unsigned portBASE_TYPE uxReturn; + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; + } + #else + { + pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; + } + #endif + + uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack ); + + return uxReturn; + } + +#endif /* INCLUDE_uxTaskGetStackHighWaterMark */ +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + static void prvDeleteTCB( tskTCB *pxTCB ) + { + /* This call is required specifically for the TriCore port. It must be + above the vPortFree() calls. The call is also used by ports/demos that + want to allocate and clean RAM statically. */ + portCLEAN_UP_TCB( pxTCB ); + + /* Free up the memory allocated by the scheduler for the task. It is up to + the task to free any memory allocated at the application level. */ + vPortFreeAligned( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + +#endif /* INCLUDE_vTaskDelete */ +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) + + xTaskHandle xTaskGetCurrentTaskHandle( void ) + { + xTaskHandle xReturn; + + /* A critical section is not required as this is not called from + an interrupt and the current TCB will always be the same for any + individual execution thread. */ + xReturn = pxCurrentTCB; + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + + portBASE_TYPE xTaskGetSchedulerState( void ) + { + portBASE_TYPE xReturn; + + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } + + return xReturn; + } + +#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityInherit( xTaskHandle const pxMutexHolder ) + { + tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + + /* If the mutex was given back by an interrupt while the queue was + locked then the mutex holder might now be NULL. */ + if( pxMutexHolder != NULL ) + { + if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) + { + /* Adjust the mutex holder state to account for its new priority. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + + /* If the task being modified is in the ready state it will need to + be moved into a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + + /* Inherit the priority before being moved into the new list. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + prvAddTaskToReadyList( pxTCB ); + } + else + { + /* Just inherit the priority. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + } + + traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority ); + } + } + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder ) + { + tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + + if( pxMutexHolder != NULL ) + { + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* We must be the running task to be able to give the mutex back. + Remove ourselves from the ready list we currently appear in. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 ) + { + taskRESET_READY_PRIORITY( pxTCB->uxPriority ); + } + + /* Disinherit the priority before adding the task into the new + ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + prvAddTaskToReadyList( pxTCB ); + } + } + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskEnterCritical( void ) + { + portDISABLE_INTERRUPTS(); + + if( xSchedulerRunning != pdFALSE ) + { + ( pxCurrentTCB->uxCriticalNesting )++; + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskExitCritical( void ) + { + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB->uxCriticalNesting > 0U ) + { + ( pxCurrentTCB->uxCriticalNesting )--; + + if( pxCurrentTCB->uxCriticalNesting == 0U ) + { + portENABLE_INTERRUPTS(); + } + } + } + } + +#endif /* portCRITICAL_NESTING_IN_TCB */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) + + void vTaskList( signed char *pcWriteBuffer ) + { + xTaskStatusType *pxTaskStatusArray; + volatile unsigned portBASE_TYPE uxArraySize, x; + char cStatus; + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that + * displays task names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that + * might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, + * and limited functionality implementation of sprintf() is provided in + * many of the FreeRTOS/Demo sub-directories in a file called + * printf-stdarg.c (note printf-stdarg.c does not provide a full + * snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskList(). + */ + + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL ); + + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + switch( pxTaskStatusArray[ x ].eCurrentState ) + { + case eReady: cStatus = tskREADY_CHAR; + break; + + case eBlocked: cStatus = tskBLOCKED_CHAR; + break; + + case eSuspended: cStatus = tskSUSPENDED_CHAR; + break; + + case eDeleted: cStatus = tskDELETED_CHAR; + break; + + default: /* Should not get here, but it is included + to prevent static checking errors. */ + cStatus = 0x00; + break; + } + + sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber ); + pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); + } + + /* Free the array again. */ + vPortFree( pxTaskStatusArray ); + } + } + +#endif /* configUSE_TRACE_FACILITY */ +/*----------------------------------------------------------*/ + +#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) + + void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) + { + xTaskStatusType *pxTaskStatusArray; + volatile unsigned portBASE_TYPE uxArraySize, x; + unsigned long ulTotalTime, ulStatsAsPercentage; + + /* + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many + * of the demo applications. Do not consider it to be part of the + * scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part + * of the uxTaskGetSystemState() output into a human readable table that + * displays the amount of time each task has spent in the Running state + * in both absolute and percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library + * function that might bloat the code size, use a lot of stack, and + * provide different results on different platforms. An alternative, + * tiny, third party, and limited functionality implementation of + * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in + * a file called printf-stdarg.c (note printf-stdarg.c does not provide + * a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly + * through a call to vTaskGetRunTimeStats(). + */ + + /* Make sure the write buffer does not contain a string. */ + *pcWriteBuffer = 0x00; + + /* Take a snapshot of the number of tasks in case it changes while this + function is executing. */ + uxArraySize = uxCurrentNumberOfTasks; + + /* Allocate an array index for each task. */ + pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) ); + + if( pxTaskStatusArray != NULL ) + { + /* Generate the (binary) data. */ + uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime ); + + /* For percentage calculations. */ + ulTotalTime /= 100UL; + + /* Avoid divide by zero errors. */ + if( ulTotalTime > 0 ) + { + /* Create a human readable table from the binary data. */ + for( x = 0; x < uxArraySize; x++ ) + { + /* What percentage of the total run time has the task used? + This will always be rounded down to the nearest integer. + ulTotalRunTimeDiv100 has already been divided by 100. */ + ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime; + + if( ulStatsAsPercentage > 0UL ) + { + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); + } + #endif + } + else + { + /* If the percentage is zero here then the task has + consumed less than 1% of the total run time. */ + #ifdef portLU_PRINTF_SPECIFIER_REQUIRED + { + sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #else + { + /* sizeof( int ) == sizeof( long ) so a smaller + printf() library can be used. */ + sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); + } + #endif + } + + pcWriteBuffer += strlen( ( char * ) pcWriteBuffer ); + } + } + + /* Free the array again. */ + vPortFree( pxTaskStatusArray ); + } + } + +#endif /* configGENERATE_RUN_TIME_STATS */ + + + diff --git a/source/freertos_blinky/readme.txt b/source/freertos_blinky/readme.txt new file mode 100644 index 0000000..c3c5e76 --- /dev/null +++ b/source/freertos_blinky/readme.txt @@ -0,0 +1,12 @@ +Example description +Welcome to the FreeRTOS basic blinky example. This example starts up +FreeRTOS and creates 3 tasks that blink LEDs at different rates. + +Special connection requirements +There are no special connection requirements for this example. + + +Supported boards and board setup: + LPCOPEN_11U6X_BOARD_LPCXPRESSO_11U68 + LPCOPEN_11U6X_BOARD_MANLEY_11U68 + diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.cproject b/source/lpc_board_nxp_lpcxpresso_11u68/.cproject new file mode 100644 index 0000000..4835fd4 --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/.cproject @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <?xml version="1.0" encoding="UTF-8"?> +<TargetConfig> +<Properties property_0="" property_3="NXP" property_4="LPC11U68" property_count="5" version="60100"/> +<infoList vendor="NXP"> +<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen"> +<chip> +<name>LPC11U68</name> +<family>LPC11U6x</family> +<vendor>NXP (formerly Philips)</vendor> +<reset board="None" core="Real" sys="Real"/> +<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/> +<memory can_program="true" id="Flash" is_ro="true" type="Flash"/> +<memory id="RAM" type="RAM"/> +<memory id="Periph" is_volatile="true" type="Peripheral"/> +<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/> +<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/> +<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/> +<peripheralInstance derived_from="V6M_NVIC" determined="infoFile" id="NVIC" location="0xe000e000"/> +<peripheralInstance derived_from="V6M_DCR" determined="infoFile" id="DCR" location="0xe000edf0"/> +<peripheralInstance derived_from="I2C0" determined="infoFile" id="I2C0" location="0x40000000"/> +<peripheralInstance derived_from="WWDT" determined="infoFile" id="WWDT" location="0x40004000"/> +<peripheralInstance derived_from="USART0" determined="infoFile" id="USART0" location="0x40008000"/> +<peripheralInstance derived_from="CT16B0" determined="infoFile" id="CT16B0" location="0x4000c000"/> +<peripheralInstance derived_from="CT16B1" determined="infoFile" id="CT16B1" location="0x40010000"/> +<peripheralInstance derived_from="CT32B0" determined="infoFile" id="CT32B0" location="0x40014000"/> +<peripheralInstance derived_from="CT32B1" determined="infoFile" id="CT32B1" location="0x40018000"/> +<peripheralInstance derived_from="ADC" determined="infoFile" id="ADC" location="0x4001c000"/> +<peripheralInstance derived_from="I2C1" determined="infoFile" id="I2C1" location="0x40020000"/> +<peripheralInstance derived_from="RTC" determined="infoFile" id="RTC" location="0x40024000"/> +<peripheralInstance derived_from="DMATRIGMUX" determined="infoFile" id="DMATRIGMUX" location="0x40028000"/> +<peripheralInstance derived_from="PMU" determined="infoFile" id="PMU" location="0x40038000"/> +<peripheralInstance derived_from="FLASHCTRL" determined="infoFile" id="FLASHCTRL" location="0x4003c000"/> +<peripheralInstance derived_from="SSP0" determined="infoFile" id="SSP0" location="0x40040000"/> +<peripheralInstance derived_from="IOCON" determined="infoFile" id="IOCON" location="0x40044000"/> +<peripheralInstance derived_from="SYSCON" determined="infoFile" id="SYSCON" location="0x40048000"/> +<peripheralInstance derived_from="USART4" determined="infoFile" id="USART4" location="0x4004c000"/> +<peripheralInstance derived_from="SSP1" determined="infoFile" id="SSP1" location="0x40058000"/> +<peripheralInstance derived_from="GINT0" determined="infoFile" id="GINT0" location="0x4005c000"/> +<peripheralInstance derived_from="GINT1" determined="infoFile" id="GINT1" location="0x40060000"/> +<peripheralInstance derived_from="USART1" determined="infoFile" id="USART1" location="0x4006c000"/> +<peripheralInstance derived_from="USART2" determined="infoFile" id="USART2" location="0x40070000"/> +<peripheralInstance derived_from="USART3" determined="infoFile" id="USART3" location="0x40074000"/> +<peripheralInstance derived_from="USB" determined="infoFile" id="USB" location="0x40080000"/> +<peripheralInstance derived_from="CRC" determined="infoFile" id="CRC" location="0x50000000"/> +<peripheralInstance derived_from="DMA" determined="infoFile" id="DMA" location="0x50004000"/> +<peripheralInstance derived_from="SCT0" determined="infoFile" id="SCT0" location="0x5000c000"/> +<peripheralInstance derived_from="SCT1" determined="infoFile" id="SCT1" location="0x5000e000"/> +<peripheralInstance derived_from="GPIO-PORT" determined="infoFile" id="GPIO-PORT" location="0xa0000000"/> +<peripheralInstance derived_from="PINT" determined="infoFile" id="PINT" location="0xa0004000"/> +</chip> +<processor> +<name gcc_name="cortex-m0">Cortex-M0</name> +<family>Cortex-M</family> +</processor> +<link href="LPC11U6x_peripheral.xme" show="embed" type="simple"/> +</info> +</infoList> +</TargetConfig> + + diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.project b/source/lpc_board_nxp_lpcxpresso_11u68/.project new file mode 100644 index 0000000..df8c992 --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/.project @@ -0,0 +1,26 @@ + + + lpc_board_nxp_lpcxpresso_11u68 + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/.settings/language.settings.xml b/source/lpc_board_nxp_lpcxpresso_11u68/.settings/language.settings.xml new file mode 100644 index 0000000..ad514b3 --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/inc/board.h b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board.h new file mode 100644 index 0000000..84a20ff --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board.h @@ -0,0 +1,111 @@ +/* + * @brief LPCXpresso 11U68 board file + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __BOARD_H_ +#define __BOARD_H_ + +#include "chip.h" +/* board_api.h is included at the bottom of this file after DEBUG setup */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup BOARD_NXP_LPCXPRESSO_11U68 NXP LPC11U68 LPCXpresso board support software API functions + * @ingroup LPCOPEN_11U6X_BOARD_LPCXPRESSO_11U68 + * The board support software API functions provide some simple abstracted + * functions used across multiple LPCOpen board examples. See @ref BOARD_COMMON_API + * for the functions defined by this board support layer.
+ * @{ + */ + +/** @defgroup BOARD_NXP_LPCXPRESSO_11U68_OPTIONS BOARD: NXP LPC11U68 LPCXpresso board build options + * This board has options that configure its operation at build-time.
+ * @{ + */ + +/** Define DEBUG_ENABLE to enable IO via the DEBUGSTR, DEBUGOUT, and + DEBUGIN macros. If not defined, DEBUG* functions will be optimized + out of the code at build time. + */ +#define DEBUG_ENABLE + +/** Define DEBUG_SEMIHOSTING along with DEBUG_ENABLE to enable IO support + via semihosting. You may need to use a C library that supports + semihosting with this option. + */ +// #define DEBUG_SEMIHOSTING + +/** Board UART used for debug output and input using the DEBUG* macros. This + is also the port used for Board_UARTPutChar, Board_UARTGetChar, and + Board_UARTPutSTR functions. + */ +#define DEBUG_UART LPC_USART0 + +/** + * @} + */ + +/* Board name */ +#define BOARD_NXP_LPCXPRESSO_11U68 + +/** + * Joystick defines + */ +#define JOY_UP 0x01 +#define JOY_DOWN 0x02 +#define JOY_LEFT 0x04 +#define JOY_RIGHT 0x08 +#define JOY_PRESS 0x10 + +/** + * @brief Initialize Joystick + * @return Nothing + */ +void Board_Joystick_Init(void); + +/** + * @brief Get Joystick status + * @return status of Joystick + */ +uint8_t Joystick_GetStatus(void); + +/** + * @} + */ + +#include "board_api.h" + +#ifdef __cplusplus +} +#endif + +#endif /* __BOARD_H_ */ diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/inc/board_api.h b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board_api.h new file mode 100644 index 0000000..7156104 --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/inc/board_api.h @@ -0,0 +1,187 @@ +/* + * @brief Common board API functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __BOARD_API_H_ +#define __BOARD_API_H_ + +#include "lpc_types.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup BOARD_COMMON_API BOARD: Common board functions + * @ingroup BOARD_Common + * This file contains common board definitions that are shared across + * boards and devices. All of these functions do not need to be + * implemented for a specific board, but if they are implemented, they + * should use this API standard. + * @{ + */ + +/** + * @brief Setup and initialize hardware prior to call to main() + * @return None + * @note Board_SystemInit() is called prior to the application and sets up system + * clocking, memory, and any resources needed prior to the application + * starting. + */ +void Board_SystemInit(void); + +/** + * @brief Setup pin multiplexer per board schematics + * @return None + * @note Board_SetupMuxing() should be called from SystemInit() prior to application + * main() is called. So that the PINs are set in proper state. + */ +void Board_SetupMuxing(void); + +/** + * @brief Setup system clocking + * @return None + * @note This sets up board clocking. + */ +void Board_SetupClocking(void); + +/** + * @brief Setup external system memory + * @return None + * @note This function is typically called after pin mux setup and clock setup and + * sets up any external memory needed by the system (DRAM, SRAM, etc.). Not all + * boards need this function. + */ +void Board_SetupExtMemory(void); + +/** + * @brief Set up and initialize all required blocks and functions related to the board hardware. + * @return None + */ +void Board_Init(void); + +/** + * @brief Initializes board UART for output, required for printf redirection + * @return None + */ +void Board_Debug_Init(void); + +/** + * @brief Sends a single character on the UART, required for printf redirection + * @param ch : character to send + * @return None + */ +void Board_UARTPutChar(char ch); + +/** + * @brief Get a single character from the UART, required for scanf input + * @return EOF if not character was received, or character value + */ +int Board_UARTGetChar(void); + +/** + * @brief Prints a string to the UART + * @param str : Terminated string to output + * @return None + */ +void Board_UARTPutSTR(char *str); + +/** + * @brief Sets the state of a board LED to on or off + * @param LEDNumber : LED number to set state for + * @param State : true for on, false for off + * @return None + */ +void Board_LED_Set(uint8_t LEDNumber, bool State); + +/** + * @brief Returns the current state of a board LED + * @param LEDNumber : LED number to set state for + * @return true if the LED is on, otherwise false + */ +bool Board_LED_Test(uint8_t LEDNumber); + +/** + * @brief Toggles the current state of a board LED + * @param LEDNumber : LED number to change state for + * @return None + */ +void Board_LED_Toggle(uint8_t LEDNumber); + +/** + * @brief Turn on Board LCD Backlight + * @param Intensity : Backlight intensity (0 = off, >=1 = on) + * @return None + * @note On boards where a GPIO is used to control backlight on/off state, a '0' or '1' + * value will turn off or on the backlight. On some boards, a non-0 value will + * control backlight intensity via a PWN. For PWM systems, the intensity value + * is a percentage value between 0 and 100%. + */ +void Board_SetLCDBacklight(uint8_t Intensity); + +/** + * @brief Function prototype for a MS delay function. Board layers or example code may + * define this function as needed. + */ +typedef void (*p_msDelay_func_t)(uint32_t); + +/* The DEBUG* functions are selected based on system configuration. + Code that uses the DEBUG* functions will have their I/O routed to + the UART, semihosting, or nowhere. */ +#if defined(DEBUG_ENABLE) +#if defined(DEBUG_SEMIHOSTING) +#define DEBUGINIT() +#define DEBUGOUT(...) printf(__VA_ARGS__) +#define DEBUGSTR(str) printf(str) +#define DEBUGIN() (int) EOF + +#else +#define DEBUGINIT() Board_Debug_Init() +#define DEBUGOUT(...) printf(__VA_ARGS__) +#define DEBUGSTR(str) Board_UARTPutSTR(str) +#define DEBUGIN() Board_UARTGetChar() +#endif /* defined(DEBUG_SEMIHOSTING) */ + +#else +#define DEBUGINIT() +#define DEBUGOUT(...) +#define DEBUGSTR(str) +#define DEBUGIN() (int) EOF +#endif /* defined(DEBUG_ENABLE) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __BOARD_API_H_ */ diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/src/board.c b/source/lpc_board_nxp_lpcxpresso_11u68/src/board.c new file mode 100644 index 0000000..318dcab --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/src/board.c @@ -0,0 +1,188 @@ +/* + * @brief NXP LPCXpresso 11U68 board file + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "board.h" +#include "retarget.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/* System oscillator rate and RTC oscillator rate */ +const uint32_t OscRateIn = 12000000; +const uint32_t RTCOscRateIn = 32768; + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Sends a character on the UART */ +void Board_UARTPutChar(char ch) +{ +#if defined(DEBUG_UART) + Chip_UART0_SendBlocking(DEBUG_UART, &ch, 1); +#endif +} + +/* Gets a character from the UART, returns EOF if no character is ready */ +int Board_UARTGetChar(void) +{ +#if defined(DEBUG_UART) + uint8_t data; + + if (Chip_UART0_Read(DEBUG_UART, &data, 1) == 1) { + return (int) data; + } +#endif + return EOF; +} + +/* Outputs a string on the debug UART */ +void Board_UARTPutSTR(char *str) +{ +#if defined(DEBUG_UART) + while (*str != '\0') { + Board_UARTPutChar(*str++); + } +#endif +} + +/* Initialize debug output via UART for board */ +void Board_Debug_Init(void) +{ +#if defined(DEBUG_UART) + Chip_UART0_Init(DEBUG_UART); + Chip_UART0_SetBaud(DEBUG_UART, 115200); + Chip_UART0_ConfigData(DEBUG_UART, (UART0_LCR_WLEN8 | UART0_LCR_SBS_1BIT)); + Chip_UART0_SetupFIFOS(DEBUG_UART, (UART0_FCR_FIFO_EN | UART0_FCR_TRG_LEV2)); + Chip_UART0_TXEnable(DEBUG_UART); +#endif +} + +#define MAXLEDS 3 +static const uint8_t ledports[MAXLEDS] = {2, 2, 2}; +static const uint8_t ledpins[MAXLEDS] = {17, 16, 18}; + +/* Initializes board LED(s) */ +static void Board_LED_Init(void) +{ + int idx; + + for (idx = 0; idx < MAXLEDS; idx++) { + /* Set the GPIO as output with initial state off (high) */ + Chip_GPIO_SetPinDIROutput(LPC_GPIO, ledports[idx], ledpins[idx]); + Chip_GPIO_SetPinState(LPC_GPIO, ledports[idx], ledpins[idx], true); + } +} + +/* Sets the state of a board LED to on or off */ +void Board_LED_Set(uint8_t LEDNumber, bool On) +{ + if (LEDNumber < MAXLEDS) { + /* Toggle state, low is on, high is off */ + Chip_GPIO_SetPinState(LPC_GPIO, ledports[LEDNumber], ledpins[LEDNumber], !On); + } +} + +/* Returns the current state of a board LED */ +bool Board_LED_Test(uint8_t LEDNumber) +{ + bool state = false; + + if (LEDNumber < MAXLEDS) { + state = !Chip_GPIO_GetPinState(LPC_GPIO, ledports[LEDNumber], ledpins[LEDNumber]); + } + + return state; +} + +/* Toggles the current state of a board LED */ +void Board_LED_Toggle(uint8_t LEDNumber) +{ + if (LEDNumber < MAXLEDS) { + Chip_GPIO_SetPinToggle(LPC_GPIO, ledports[LEDNumber], ledpins[LEDNumber]); + } +} + +/* Set up and initialize all required blocks and functions related to the + board hardware */ +void Board_Init(void) +{ + /* Sets up DEBUG UART */ + DEBUGINIT(); + + /* Initialize GPIO */ + Chip_GPIO_Init(LPC_GPIO); + + /* Initialize LEDs */ + Board_LED_Init(); +} + +/* Baseboard joystick buttons */ +#define NUM_BUTTONS 5 +static const uint8_t portButton[NUM_BUTTONS] = {0, 0, 0, 2, 2}; +static const uint8_t pinButton[NUM_BUTTONS] = {17, 20, 21, 2, 19}; +static const uint8_t stateButton[NUM_BUTTONS] = {JOY_PRESS, JOY_RIGHT, JOY_UP, + JOY_DOWN, JOY_LEFT}; + +/* Initialize Joystick */ +void Board_Joystick_Init(void) +{ + int i; + + /* IOCON states already selected in SystemInit(), GPIO setup only. Pullups + are external, so IOCON with no states */ + for (i = 0; i < NUM_BUTTONS; i++) { + Chip_GPIO_SetPinDIRInput(LPC_GPIO, portButton[i], pinButton[i]); + } +} + +/* Get Joystick status */ +uint8_t Joystick_GetStatus(void) +{ + uint8_t i, ret = 0; + + for (i = 0; i < NUM_BUTTONS; i++) { + if ((Chip_GPIO_GetPinState(LPC_GPIO, portButton[i], pinButton[i])) == false) { + ret |= stateButton[i]; + } + } + + return ret; +} diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/src/board_sysinit.c b/source/lpc_board_nxp_lpcxpresso_11u68/src/board_sysinit.c new file mode 100644 index 0000000..efb0c3e --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/src/board_sysinit.c @@ -0,0 +1,186 @@ +/* + * @brief NXP LPCXpresso 11U68 Sysinit file + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + + #include "board.h" + #include "string.h" + +/* The System initialization code is called prior to the application and + initializes the board for run-time operation. Board initialization + includes clock setup and default pin muxing configuration. */ + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/* Pin muxing table, only items that need changing from their default pin + state are in this table. Not every pin is mapped. */ +STATIC const PINMUX_GRP_T pinmuxing[] = { + /* LPCXpresso pin - Base board function - Mapped function */ + /* RESET-PIO0_0 - PIO/RESET (pin 4) - Reset */ + /* PIO0_1-ISP_EN - PIO (pin 51) - GPIO input */ + /* PIO0_2-SSP0_SSEL - PIO/SSEL (pin 8) - GPIO output for SSP0 CS */ + /* PIO0_3-VBUS - - USB VBUS */ + {0, 3, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO0_4-I2C_SCL - PIO/I2C-SCL (pin 41) - I2C0 SCL */ + {0, 4, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO0_5-I2C_SDA - PIO/I2C-SDA (pin 40) - I2C0 SDA */ + {0, 5, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO0_6 - - GPIO */ + /* PIO0_7 - PIO (pin 11) - GPIO */ + /* PIO0_8-SSP0_MISO - PIO/MISO (pin 6) - SSP0 MISO */ + {0, 8, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO0_9-SSP0_MOSI - PIO/MOSI (pin 5) - SSP0 MOSI */ + {0, 9, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* SWCLK-PIO0_10 - - SWCLK */ + /* PIO0_11-ADC_9 - PIO/AD5 (pin 20) - ADC_9 */ + {0, 11, (IOCON_FUNC2 | IOCON_MODE_INACT)}, + /* PIO0_12-ADC_8 - PIO/AD4/SWDIO (pin 19) - ADC_8 */ + {0, 12, (IOCON_FUNC2 | IOCON_MODE_INACT)}, + /* PIO0_13-ADC_7 - PIO/AD3 (pin 18) - ADC_7 */ + {0, 13, (IOCON_FUNC2 | IOCON_MODE_INACT)}, + /* PIO0_14-ADC_6 - PIO/AD2 (pin 17) - ADC_6 */ + {0, 14, (IOCON_FUNC2 | IOCON_MODE_INACT)}, + /* PIO0_16-WAKEUP - - GPIO input */ + /* PIO0_17 - PIO (pin 12) - GPIO */ + /* TO_MUX_PIO0_18-ISP_RX - PIO/RXD (pin 10) - UART0 RX */ + {0, 18, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO0_19-ISP_TX - PIO/TXD (pin 9) - UART0 TX */ + {0, 19, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO0_20 - PIO (pin 13) - GPIO */ + /* PIO0_21 - PIO (pin 14) - GPIO */ + /* PIO0_22 - PIO (pin 21) - GPIO */ + /* PIO0_23-ADC_1 - PIO/AD1 (pin 16) - ADC_1 */ + {0, 23, (IOCON_FUNC1 | IOCON_MODE_INACT)}, + /* PIO1_0 - PIO (pin 22) - GPIO */ + /* PIO1_1 - PIO/USB_CONNECT (pin 23) - GPIO */ + /* PIO1_2 - PIO/SWCLK (pin 24) - SWCLK */ + /* PIO1_3 - PIO (pin 25) - GPIO */ + /* PIO1_4 - PIO (pin 26) - GPIO */ + /* PIO1_5 - PIO (pin 27) - GPIO */ + /* PIO1_6 - PIO (pin 53) - GPIO */ + /* PIO1_7 - PIO (pin 52) - GPIO */ + /* PIO1_8 - PIO (pin 50) - GPIO */ + /* PIO1_9-ADC_0 - PIO/AD0 (pin 15) - ADC_0 */ + {1, 9, (IOCON_FUNC1 | IOCON_MODE_INACT)}, + /* PIO1_10 - PIO (pin 49) - GPIO */ + /* PIO1_11-I2C1_SCL - - I2C1 SCL */ + {1, 11, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_12 - PIO/USB_VBUS (pin 39) - GPIO input */ + /* PIO1_13 - PIO (pin 38) - GPIO output */ + /* PIO1_14-I2C_SDA - - I2C SDA */ + {1, 14, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_15 - PIO (pin 48) - GPIO */ + /* PIO1_16 - - GPIO */ + /* PIO1_17 - - GPIO */ + /* PIO1_18 - - GPIO input, with pullup */ + /* PIO1_19 - - GPIO */ + /* PIO1_20-SSP1_SCK - - SSP1 CLK */ + {1, 20, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_21-SSP1_MISO - - SSP1 MISO */ + {1, 21, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_22-SSP1_MOSI - - SSP1 MOSI */ + {1, 22, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_23-SSP1_SSEL - - SSP1 SSEL */ + {1, 23, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_24-CT32B0_MAT0 - - GPIO input, with pullup */ + /* PIO1_25 - - GPIO */ + /* PIO1_26-CT32B0_MAT2 - - CT32B0_MAT2 */ + {1, 26, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_27-CT32B0_MAT3 - - CT32B0_MAT3 */ + {1, 27, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_28 - - GPIO */ + /* PIO1_29-SSP0_SCK - PIO/SCK (pin 7) - SSP0 CLK */ + {1, 29, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO1_30 - - GPIO */ + /* PIO1_31 - - GPIO */ + /* PIO2_0 - - XTALIN */ + {2, 0, (IOCON_FUNC1 | IOCON_MODE_INACT)}, + /* PIO2_1 - - XTALOUT */ + {2, 1, (IOCON_FUNC1 | IOCON_MODE_INACT)}, + /* PIO2_2-SCT0_OUT1 - PIO (pin 46) - GPIO */ + /* PIO2_3-CT32B0_MAT1 - - CT32B0_MAT1 */ + {2, 3, (IOCON_FUNC2 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)}, + /* PIO2_4 - - GPIO */ + /* PIO2_5 - - GPIO */ + /* PIO2_6 - - GPIO */ + /* PIO2_7-SCT0_OUT2 - PIO (pin 47) - GPIO */ + /* PIO2_8 - - GPIO */ + /* PIO2_9 - - GPIO */ + /* PIO2_10 - - GPIO */ + /* PIO2_11 - - GPIO */ + /* PIO2_12 - - GPIO */ + /* PIO2_13 - - GPIO */ + /* PIO2_14 - - GPIO */ + /* PIO2_15 - - GPIO */ + /* PIO2_16-SCT1_OUT0 - PIO/MAT=PWM (pin 42) - LED1 GREEN */ + /* PIO2_17-SCT1_OUT1 - PIO/MAT=PWM (pin 43) - LED0 RED */ + /* PIO2_18-SCT1_OUT2 - PIO (pin 44) - LED2 BLUE */ + /* PIO2_19-SCT1_OUT3 - PIO (pin 45) - GPIO */ + /* PIO2_20 - - GPIO */ + /* PIO2_21 - - GPIO */ + /* PIO2_22 - - GPIO */ + /* PIO2_23 - - GPIO */ +}; + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Sets up system pin muxing */ +void Board_SetupMuxing(void) +{ + /* Enable IOCON clock */ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON); + + Chip_IOCON_SetPinMuxing(LPC_IOCON, pinmuxing, sizeof(pinmuxing) / sizeof(PINMUX_GRP_T)); +} + +/* Set up and initialize clocking prior to call to main */ +void Board_SetupClocking(void) +{ + Chip_SetupXtalClocking(); +} + +/* Set up and initialize hardware prior to call to main */ +void Board_SystemInit(void) +{ + /* Setup system clocking and muxing */ + Board_SetupMuxing();/* Muxing first as it sets up ext oscillator pins */ + Board_SetupClocking(); +} diff --git a/source/lpc_board_nxp_lpcxpresso_11u68/src/retarget.h b/source/lpc_board_nxp_lpcxpresso_11u68/src/retarget.h new file mode 100644 index 0000000..83372ed --- /dev/null +++ b/source/lpc_board_nxp_lpcxpresso_11u68/src/retarget.h @@ -0,0 +1,251 @@ +/* + * @brief IO redirection support + * + * This file adds re-direction support to the library for various + * projects. It can be configured in one of 3 ways - no redirection, + * redirection via a UART, or redirection via semihosting. If DEBUG + * is not defined, all printf statements will do nothing with the + * output being throw away. If DEBUG is defined, then the choice of + * output is selected by the DEBUG_SEMIHOSTING define. If the + * DEBUG_SEMIHOSTING is not defined, then output is redirected via + * the UART. If DEBUG_SEMIHOSTING is defined, then output will be + * attempted to be redirected via semihosting. If the UART method + * is used, then the Board_UARTPutChar and Board_UARTGetChar + * functions must be defined to be used by this driver and the UART + * must already be initialized to the correct settings. + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "board.h" + +/* Keil (Realview) support */ +#if defined(__CC_ARM) + +#include +#include + +#if defined(DEBUG_ENABLE) +#if defined(DEBUG_SEMIHOSTING) +#define ITM_Port8(n) (*((volatile unsigned char *) (0xE0000000 + 4 * n))) +#define ITM_Port16(n) (*((volatile unsigned short *) (0xE0000000 + 4 * n))) +#define ITM_Port32(n) (*((volatile unsigned long *) (0xE0000000 + 4 * n))) + +#define DEMCR (*((volatile unsigned long *) (0xE000EDFC))) +#define TRCENA 0x01000000 + +/* Write to SWO */ +void _ttywrch(int ch) +{ + if (DEMCR & TRCENA) { + while (ITM_Port32(0) == 0) {} + ITM_Port8(0) = ch; + } +} + +#else +static INLINE void BoardOutChar(char ch) +{ + Board_UARTPutChar(ch); +} + +#endif /* defined(DEBUG_SEMIHOSTING) */ +#endif /* defined(DEBUG_ENABLE) */ + +struct __FILE { + int handle; +}; + +FILE __stdout; +FILE __stdin; +FILE __stderr; + +void *_sys_open(const char *name, int openmode) +{ + return 0; +} + +int fputc(int c, FILE *f) +{ +#if defined(DEBUG_ENABLE) +#if defined(DEBUG_SEMIHOSTING) + _ttywrch(c); +#else + BoardOutChar((char) c); +#endif +#endif + return 0; +} + +int fgetc(FILE *f) +{ +#if defined(DEBUG_ENABLE) && !defined(DEBUG_SEMIHOSTING) + return Board_UARTGetChar(); +#else + return 0; +#endif +} + +int ferror(FILE *f) +{ + return EOF; +} + +void _sys_exit(int return_code) +{ +label: + __WFI(); + goto label; /* endless loop */ +} + +#endif /* defined (__CC_ARM) */ + +/* IAR support */ +#if defined(__ICCARM__) +/******************* + * + * Copyright 1998-2003 IAR Systems. All rights reserved. + * + * $Revision: 30870 $ + * + * This is a template implementation of the "__write" function used by + * the standard library. Replace it with a system-specific + * implementation. + * + * The "__write" function should output "size" number of bytes from + * "buffer" in some application-specific way. It should return the + * number of characters written, or _LLIO_ERROR on failure. + * + * If "buffer" is zero then __write should perform flushing of + * internal buffers, if any. In this case "handle" can be -1 to + * indicate that all handles should be flushed. + * + * The template implementation below assumes that the application + * provides the function "MyLowLevelPutchar". It should return the + * character written, or -1 on failure. + * + ********************/ + +#include + +#if defined(DEBUG_ENABLE) && !defined(DEBUG_SEMIHOSTING) + +_STD_BEGIN + +#pragma module_name = "?__write" + +/* + If the __write implementation uses internal buffering, uncomment + the following line to ensure that we are called with "buffer" as 0 + (i.e. flush) when the application terminates. */ +size_t __write(int handle, const unsigned char *buffer, size_t size) +{ +#if defined(DEBUG_ENABLE) + size_t nChars = 0; + + if (buffer == 0) { + /* + This means that we should flush internal buffers. Since we + don't we just return. (Remember, "handle" == -1 means that all + handles should be flushed.) + */ + return 0; + } + + /* This template only writes to "standard out" and "standard err", + for all other file handles it returns failure. */ + if (( handle != _LLIO_STDOUT) && ( handle != _LLIO_STDERR) ) { + return _LLIO_ERROR; + } + + for ( /* Empty */; size != 0; --size) { + Board_UARTPutChar(*buffer++); + ++nChars; + } + + return nChars; +#else + return size; +#endif /* defined(DEBUG_ENABLE) */ +} + +_STD_END +#endif + +#endif /* defined (__ICCARM__) */ + +#if defined( __GNUC__ ) +/* Include stdio.h to pull in __REDLIB_INTERFACE_VERSION__ */ +#include + +#if (__REDLIB_INTERFACE_VERSION__ >= 20000) +/* We are using new Redlib_v2 semihosting interface */ + #define WRITEFUNC __sys_write + #define READFUNC __sys_readc +#else +/* We are using original Redlib semihosting interface */ + #define WRITEFUNC __write + #define READFUNC __readc +#endif + +#if defined(DEBUG_ENABLE) +#if defined(DEBUG_SEMIHOSTING) +/* Do nothing, semihosting is enabled by default in LPCXpresso */ +#endif /* defined(DEBUG_SEMIHOSTING) */ +#endif /* defined(DEBUG_ENABLE) */ + +#if !defined(DEBUG_SEMIHOSTING) +int WRITEFUNC(int iFileHandle, char *pcBuffer, int iLength) +{ +#if defined(DEBUG_ENABLE) + unsigned int i; + for (i = 0; i < iLength; i++) { + Board_UARTPutChar(pcBuffer[i]); + } +#endif + + return iLength; +} + +/* Called by bottom level of scanf routine within RedLib C library to read + a character. With the default semihosting stub, this would read the character + from the debugger console window (which acts as stdin). But this version reads + the character from the LPC1768/RDB1768 UART. */ +int READFUNC(void) +{ +#if defined(DEBUG_ENABLE) + char c = Board_UARTGetChar(); + return (int) c; + +#else + return (int) -1; +#endif +} + +#endif /* !defined(DEBUG_SEMIHOSTING) */ +#endif /* defined ( __GNUC__ ) */ diff --git a/source/lpc_chip_11u6x/.DS_Store b/source/lpc_chip_11u6x/.DS_Store new file mode 100644 index 0000000..6da1c1f Binary files /dev/null and b/source/lpc_chip_11u6x/.DS_Store differ diff --git a/source/lpc_chip_11u6x/.cproject b/source/lpc_chip_11u6x/.cproject new file mode 100644 index 0000000..51b5575 --- /dev/null +++ b/source/lpc_chip_11u6x/.cproject @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <?xml version="1.0" encoding="UTF-8"?> +<TargetConfig> +<Properties property_0="" property_3="NXP" property_4="LPC11U68" property_count="5" version="60100"/> +<infoList vendor="NXP"> +<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen"> +<chip> +<name>LPC11U68</name> +<family>LPC11U6x</family> +<vendor>NXP (formerly Philips)</vendor> +<reset board="None" core="Real" sys="Real"/> +<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/> +<memory can_program="true" id="Flash" is_ro="true" type="Flash"/> +<memory id="RAM" type="RAM"/> +<memory id="Periph" is_volatile="true" type="Peripheral"/> +<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/> +<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/> +<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/> +<peripheralInstance derived_from="V6M_NVIC" determined="infoFile" id="NVIC" location="0xe000e000"/> +<peripheralInstance derived_from="V6M_DCR" determined="infoFile" id="DCR" location="0xe000edf0"/> +<peripheralInstance derived_from="I2C0" determined="infoFile" id="I2C0" location="0x40000000"/> +<peripheralInstance derived_from="WWDT" determined="infoFile" id="WWDT" location="0x40004000"/> +<peripheralInstance derived_from="USART0" determined="infoFile" id="USART0" location="0x40008000"/> +<peripheralInstance derived_from="CT16B0" determined="infoFile" id="CT16B0" location="0x4000c000"/> +<peripheralInstance derived_from="CT16B1" determined="infoFile" id="CT16B1" location="0x40010000"/> +<peripheralInstance derived_from="CT32B0" determined="infoFile" id="CT32B0" location="0x40014000"/> +<peripheralInstance derived_from="CT32B1" determined="infoFile" id="CT32B1" location="0x40018000"/> +<peripheralInstance derived_from="ADC" determined="infoFile" id="ADC" location="0x4001c000"/> +<peripheralInstance derived_from="I2C1" determined="infoFile" id="I2C1" location="0x40020000"/> +<peripheralInstance derived_from="RTC" determined="infoFile" id="RTC" location="0x40024000"/> +<peripheralInstance derived_from="DMATRIGMUX" determined="infoFile" id="DMATRIGMUX" location="0x40028000"/> +<peripheralInstance derived_from="PMU" determined="infoFile" id="PMU" location="0x40038000"/> +<peripheralInstance derived_from="FLASHCTRL" determined="infoFile" id="FLASHCTRL" location="0x4003c000"/> +<peripheralInstance derived_from="SSP0" determined="infoFile" id="SSP0" location="0x40040000"/> +<peripheralInstance derived_from="IOCON" determined="infoFile" id="IOCON" location="0x40044000"/> +<peripheralInstance derived_from="SYSCON" determined="infoFile" id="SYSCON" location="0x40048000"/> +<peripheralInstance derived_from="USART4" determined="infoFile" id="USART4" location="0x4004c000"/> +<peripheralInstance derived_from="SSP1" determined="infoFile" id="SSP1" location="0x40058000"/> +<peripheralInstance derived_from="GINT0" determined="infoFile" id="GINT0" location="0x4005c000"/> +<peripheralInstance derived_from="GINT1" determined="infoFile" id="GINT1" location="0x40060000"/> +<peripheralInstance derived_from="USART1" determined="infoFile" id="USART1" location="0x4006c000"/> +<peripheralInstance derived_from="USART2" determined="infoFile" id="USART2" location="0x40070000"/> +<peripheralInstance derived_from="USART3" determined="infoFile" id="USART3" location="0x40074000"/> +<peripheralInstance derived_from="USB" determined="infoFile" id="USB" location="0x40080000"/> +<peripheralInstance derived_from="CRC" determined="infoFile" id="CRC" location="0x50000000"/> +<peripheralInstance derived_from="DMA" determined="infoFile" id="DMA" location="0x50004000"/> +<peripheralInstance derived_from="SCT0" determined="infoFile" id="SCT0" location="0x5000c000"/> +<peripheralInstance derived_from="SCT1" determined="infoFile" id="SCT1" location="0x5000e000"/> +<peripheralInstance derived_from="GPIO-PORT" determined="infoFile" id="GPIO-PORT" location="0xa0000000"/> +<peripheralInstance derived_from="PINT" determined="infoFile" id="PINT" location="0xa0004000"/> +</chip> +<processor> +<name gcc_name="cortex-m0">Cortex-M0</name> +<family>Cortex-M</family> +</processor> +<link href="LPC11U6x_peripheral.xme" show="embed" type="simple"/> +</info> +</infoList> +</TargetConfig> + + diff --git a/source/lpc_chip_11u6x/.project b/source/lpc_chip_11u6x/.project new file mode 100644 index 0000000..5c96e51 --- /dev/null +++ b/source/lpc_chip_11u6x/.project @@ -0,0 +1,26 @@ + + + lpc_chip_11u6x + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/source/lpc_chip_11u6x/.settings/language.settings.xml b/source/lpc_chip_11u6x/.settings/language.settings.xml new file mode 100644 index 0000000..581c1f6 --- /dev/null +++ b/source/lpc_chip_11u6x/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/lpc_chip_11u6x/inc/adc_11u6x.h b/source/lpc_chip_11u6x/inc/adc_11u6x.h new file mode 100644 index 0000000..dd9fb05 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/adc_11u6x.h @@ -0,0 +1,549 @@ +/* + * @brief LPC11u6x ADC driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ADC_11U6X_H_ +#define __ADC_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup ADC_11U6X CHIP: LPC11u6x A/D conversion driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** Sequence index enumerations, used in various parts of the code for + register indexing and sequencer selection */ +typedef enum { + ADC_SEQA_IDX, + ADC_SEQB_IDX +} ADC_SEQ_IDX_T; + +/** + * @brief ADC register block structure + */ +typedef struct { /*!< ADCn Structure */ + __IO uint32_t CTRL; /*!< A/D Control Register. The AD0CR register must be written to select the operating mode before A/D conversion can occur. */ + __I uint32_t RESERVED0; + __IO uint32_t SEQ_CTRL[ADC_SEQB_IDX + 1]; /*!< A/D Sequence A & B Control Register. Controls triggering and channel selection for sonversion sequence. */ + __IO uint32_t SEQ_GDAT[ADC_SEQB_IDX + 1]; /*!< A/D Sequence A & B Global Data Register. Contains the result of the most recent A/D conversion for sequence. */ + __I uint32_t RESERVED1[2]; + __I uint32_t DR[12]; /*!< A/D Channel Data Register. This register contains the result of the most recent conversion completed on channel n. */ + __IO uint32_t THR_LOW[2]; /*!< A/D Low Compare Threshold Register 0 & 1. Contains the lower threshold level for automatic threshold comparison. */ + __IO uint32_t THR_HIGH[2]; /*!< A/D High Compare Threshold Register 0 & 1. Contains the higher threshold level for automatic threshold comparison. */ + __IO uint32_t CHAN_THRSEL; /*!< A/D Channel Threshold Select Register. Specifies which set of threshold compare registers to use. */ + __IO uint32_t INTEN; /*!< A/D Interrupt Enable Register. This register contains enable bits that enable sequence-A, sequence-B, threshold compare and overrun interrupts. */ + __IO uint32_t FLAGS; /*!< A/D Flags Register. This register contains interrupt flags. - To be checked */ + __IO uint32_t TRM; /*!< A/D Trim Register. */ +} LPC_ADC_T; + +/** Maximum clock rate in Hz (12-bit conversions) */ +#define ADC_MAX_CLOCK_RATE 50000000 +#define ADC_CALIBRATE_RATE 500000 + +/** + * @brief ADC register support bitfields and mask + */ +/** ADC Control register bit fields */ +#define ADC_CR_CLKDIV_MASK (0xFF << 0) /*!< Mask for Clock divider value */ +#define ADC_CR_CLKDIV_BITPOS (0) /*!< Bit position for Clock divider value */ +#define ADC_CR_MODE10BIT (1 << 9) /*!< 10-bit mode enable bit */ +#define ADC_CR_LPWRMODEBIT (1 << 10) /*!< Low power mode enable bit */ +#define ADC_CR_CALMODEBIT (1 << 30) /*!< Self calibration cycle enable bit */ +#define ADC_CR_BITACC(n) ((((n) & 0x1) << 9)) /*!< 12-bit or 10-bit ADC accuracy */ +#define ADC_CR_CLKDIV(n) ((((n) & 0xFF) << 0)) /*!< The APB clock (PCLK) is divided by (this value plus one) to produce the clock for the A/D */ +#define ADC_SAMPLE_RATE_CONFIG_MASK (ADC_CR_CLKDIV(0xFF) | ADC_CR_BITACC(0x01)) + +/** ADC Sequence Control register bit fields */ +#define ADC_SEQ_CTRL_CHANSEL(n) (1 << (n)) /*!< Channel select macro */ +#define ADC_SEQ_CTRL_CHANSEL_MASK (0xFFF) /*!< Channel select mask */ + +/** ADC hardware trigger sources in SEQ_CTRL */ +#define ADC_SEQ_CTRL_HWTRIG_ARM_TXEV (0 << 12) /*!< HW trigger input - ARM TXEV */ +#define ADC_SEQ_CTRL_HWTRIG_CT32B0_MAT0 (1 << 12) /*!< HW trigger input - Match output 0 of CT32B0 */ +#define ADC_SEQ_CTRL_HWTRIG_CT32B0_MAT1 (2 << 12) /*!< HW trigger input - Match output 1 of CT32B1 or SCT_OUT0 */ +#define ADC_SEQ_CTRL_HWTRIG_SCT_OUT0 (2 << 12) /*!< HW trigger input - Match output 1 of CT32B1 or SCT_OUT0 */ +#define ADC_SEQ_CTRL_HWTRIG_CT16B0_MAT0 (3 << 12) /*!< HW trigger input - Match output 0 of CT16B0 */ +#define ADC_SEQ_CTRL_HWTRIG_CT16B0_MAT1 (4 << 12) /*!< HW trigger input - Match output 1 of CT16B1 or SCT_OUT1 */ +#define ADC_SEQ_CTRL_HWTRIG_SCT_OUT1 (4 << 12) /*!< HW trigger input - Match output 1 of CT16B1 or SCT_OUT1 */ +#define ADC_SEQ_CTRL_HWTRIG_CT16B0_CAP0 (5 << 12) /*!< HW trigger input - Capture input 0 of CT16B0 */ +#define ADC_SEQ_CTRL_HWTRIG_CT16B1_CAP0 (6 << 12) /*!< HW trigger input - Capture input 0 of CT16B1 */ +#define ADC_SEQ_CTRL_HWTRIG_CT32B0_CAP0 (7 << 12) /*!< HW trigger input - Capture input 0 of CT32B1 */ +#define ADC_SEQ_CTRL_HWTRIG_MASK (0x3F << 12) /*!< HW trigger input bitfield mask */ + +/** SEQ_CTRL register bit fields */ +#define ADC_SEQ_CTRL_HWTRIG_POLPOS (1 << 18) /*!< HW trigger polarity - positive edge */ +#define ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS (1 << 19) /*!< HW trigger bypass synchronisation */ +#define ADC_SEQ_CTRL_START (1 << 26) /*!< Start conversion enable bit */ +#define ADC_SEQ_CTRL_BURST (1 << 27) /*!< Repeated conversion enable bit */ +#define ADC_SEQ_CTRL_SINGLESTEP (1 << 28) /*!< Single step enable bit */ +#define ADC_SEQ_CTRL_LOWPRIO (1 << 29) /*!< High priority enable bit (regardless of name) */ +#define ADC_SEQ_CTRL_MODE_EOS (1 << 30) /*!< Mode End of sequence enable bit */ +#define ADC_SEQ_CTRL_SEQ_ENA (1UL << 31) /*!< Sequence enable bit */ + +/** ADC global data register bit fields */ +#define ADC_SEQ_GDAT_RESULT_MASK (0xFFF << 4) /*!< Result value mask */ +#define ADC_SEQ_GDAT_RESULT_BITPOS (4) /*!< Result start bit position */ +#define ADC_SEQ_GDAT_THCMPRANGE_MASK (0x3 << 16) /*!< Comparion range mask */ +#define ADC_SEQ_GDAT_THCMPRANGE_BITPOS (16) /*!< Comparison range bit position */ +#define ADC_SEQ_GDAT_THCMPCROSS_MASK (0x3 << 18) /*!< Comparion cross mask */ +#define ADC_SEQ_GDAT_THCMPCROSS_BITPOS (18) /*!< Comparison cross bit position */ +#define ADC_SEQ_GDAT_CHAN_MASK (0xF << 26) /*!< Channel number mask */ +#define ADC_SEQ_GDAT_CHAN_BITPOS (26) /*!< Channel number bit position */ +#define ADC_SEQ_GDAT_OVERRUN (1 << 30) /*!< Overrun bit */ +#define ADC_SEQ_GDAT_DATAVALID (1UL << 31) /*!< Data valid bit */ + +/** ADC Data register bit fields */ +#define ADC_DR_RESULT(n) ((((n) >> 4) & 0xFFF)) /*!< Macro for getting the ADC data value */ +#define ADC_DR_THCMPRANGE_MASK (0x3 << 16) /*!< Comparion range mask */ +#define ADC_DR_THCMPRANGE_BITPOS (16) /*!< Comparison range bit position */ +#define ADC_DR_THCMPRANGE(n) (((n) >> ADC_DR_THCMPRANGE_BITPOS) & 0x3) +#define ADC_DR_THCMPCROSS_MASK (0x3 << 18) /*!< Comparion cross mask */ +#define ADC_DR_THCMPCROSS_BITPOS (18) /*!< Comparison cross bit position */ +#define ADC_DR_THCMPCROSS(n) (((n) >> ADC_DR_THCMPCROSS_BITPOS) & 0x3) +#define ADC_DR_CHAN_MASK (0xF << 26) /*!< Channel number mask */ +#define ADC_DR_CHAN_BITPOS (26) /*!< Channel number bit position */ +#define ADC_DR_CHANNEL(n) (((n) >> ADC_DR_CHAN_BITPOS) & 0xF) /*!< Channel number bit position */ +#define ADC_DR_OVERRUN (1 << 30) /*!< Overrun bit */ +#define ADC_DR_DATAVALID (1UL << 31) /*!< Data valid bit */ +#define ADC_DR_DONE(n) (((n) >> 31)) + +/** ADC low/high Threshold register bit fields */ +#define ADC_THR_VAL_MASK (0xFFF << 4) /*!< Threshold value bit mask */ +#define ADC_THR_VAL_POS (4) /*!< Threshold value bit position */ + +/** ADC Threshold select register bit fields */ +#define ADC_THRSEL_CHAN_SEL_THR1(n) (1 << (n)) /*!< Select THR1 register for channel n */ + +/** ADC Interrupt Enable register bit fields */ +#define ADC_INTEN_SEQA_ENABLE (1 << 0) /*!< Sequence A Interrupt enable bit */ +#define ADC_INTEN_SEQB_ENABLE (1 << 1) /*!< Sequence B Interrupt enable bit */ +#define ADC_INTEN_SEQN_ENABLE(seq) (1 << (seq)) /*!< Sequence A/B Interrupt enable bit */ +#define ADC_INTEN_OVRRUN_ENABLE (1 << 2) /*!< Overrun Interrupt enable bit */ +#define ADC_INTEN_CMP_DISBALE (0) /*!< Disable comparison interrupt value */ +#define ADC_INTEN_CMP_OUTSIDETH (1) /*!< Outside threshold interrupt value */ +#define ADC_INTEN_CMP_CROSSTH (2) /*!< Crossing threshold interrupt value */ +#define ADC_INTEN_CMP_MASK (3) /*!< Comparison interrupt value mask */ +#define ADC_INTEN_CMP_ENABLE(isel, ch) (((isel) & ADC_INTEN_CMP_MASK) << ((2 * (ch)) + 3)) /*!< Interrupt selection for channel */ + +/** ADC Flags register bit fields */ +#define ADC_FLAGS_THCMP_MASK(ch) (1 << (ch)) /*!< Threshold comparison status for channel */ +#define ADC_FLAGS_OVRRUN_MASK(ch) (1 << (12 + (ch))) /*!< Overrun status for channel */ +#define ADC_FLAGS_SEQA_OVRRUN_MASK (1 << 24) /*!< Seq A Overrun status */ +#define ADC_FLAGS_SEQB_OVRRUN_MASK (1 << 25) /*!< Seq B Overrun status */ +#define ADC_FLAGS_SEQN_OVRRUN_MASK(seq) (1 << (24 + (seq))) /*!< Seq A/B Overrun status */ +#define ADC_FLAGS_SEQA_INT_MASK (1 << 28) /*!< Seq A Interrupt status */ +#define ADC_FLAGS_SEQB_INT_MASK (1 << 29) /*!< Seq B Interrupt status */ +#define ADC_FLAGS_SEQN_INT_MASK(seq) (1 << (28 + (seq)))/*!< Seq A/B Interrupt status */ +#define ADC_FLAGS_THCMP_INT_MASK (1 << 30) /*!< Threshold comparison Interrupt status */ +#define ADC_FLAGS_OVRRUN_INT_MASK (1UL << 31) /*!< Overrun Interrupt status */ + +/** ADC Trim register bit fields */ +#define ADC_TRIM_VRANGE_HIGHV (0 << 5) /*!< Voltage range bit - High volatge (2.7V to 3.6V) */ +#define ADC_TRIM_VRANGE_LOWV (1 << 5) /*!< Voltage range bit - Low volatge (1.8V to 2.7V) */ + +/** + * @brief Initialize the ADC peripheral + * @param pADC : The base of ADC peripheral on the chip + * @param flags : ADC flags for init (ADC_CR_MODE10BIT and/or ADC_CR_LPWRMODEBIT) + * @return Nothing + * @note To select low-power ADC mode, enable the ADC_CR_LPWRMODEBIT flag. + * To select 10-bit conversion mode, enable the ADC_CR_MODE10BIT flag.
+ * Example: Chip_ADC_Init(LPC_ADC, (ADC_CR_MODE10BIT | ADC_CR_LPWRMODEBIT)); + */ +void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags); + +/** + * @brief Shutdown ADC + * @param pADC : The base of ADC peripheral on the chip + * @return Nothing + * @note Disables the ADC clocks and ADC power + */ +void Chip_ADC_DeInit(LPC_ADC_T *pADC); + +/** + * @brief Set ADC divider + * @param pADC : The base of ADC peripheral on the chip + * @param div : ADC divider value to set minus 1 + * @return Nothing + * @note The value is used as a divider to generate the ADC + * clock rate from the ADC input clock. The ADC input clock is based + * on the system clock. Valid values for this function are from 0 to 255 + * with 0=divide by 1, 1=divide by 2, 2=divide by 3, etc.
+ * Do not decrement this value by 1.
+ * To set the ADC clock rate to 1MHz, use the following function:
+ * Chip_ADC_SetDivider(LPC_ADC, (Chip_Clock_GetSystemClockRate() / 1000000) - 1); + */ +STATIC INLINE void Chip_ADC_SetDivider(LPC_ADC_T *pADC, uint8_t div) +{ + uint32_t temp; + + temp = pADC->CTRL & ~(ADC_CR_CLKDIV_MASK); + pADC->CTRL = temp | (uint32_t) div; +} + +/** + * @brief Set ADC clock rate + * @param pADC : The base of ADC peripheral on the chip + * @param rate : rate in Hz to set ADC clock to (maximum ADC_MAX_SAMPLE_RATE) + * @return Nothing + */ +void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate); + +/** + * @brief Get ADC divider + * @param pADC : The base of ADC peripheral on the chip + * @return the current ADC divider + * @note This function returns the divider that is used to generate the + * ADC frequency. The returned value must be incremented by 1. The + * frequency can be determined with the following function:
+ * adc_freq = Chip_Clock_GetSystemClockRate() / (Chip_ADC_GetDivider(LPC_ADC) + 1); + */ +STATIC INLINE uint8_t Chip_ADC_GetDivider(LPC_ADC_T *pADC) +{ + return pADC->CTRL & ADC_CR_CLKDIV_MASK; +} + +/** + * @brief Start ADC calibration + * @param pADC : The base of ADC peripheral on the chip + * @return Nothing + * @note Calibration is not done as part of Chip_ADC_Init(), but + * is required after the call to Chip_ADC_Init() or after returning + * from a power-down state. + */ +void Chip_ADC_StartCalibration(LPC_ADC_T *pADC); + +/** + * @brief Check if ADC calibration is done + * @param pADC : The base of ADC peripheral on the chip + * @return TRUE if calibration is complete, otherwise FALSE. + */ +bool Chip_ADC_IsCalibrationDone(LPC_ADC_T *pADC); + +/** + * @brief Helper function for safely setting ADC sequencer register bits + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to set bits for + * @param bits : Or'ed bits of a sequencer register to set + * @return Nothing + * @note This function will safely set the ADC sequencer register bits + * while maintaining bits 20..25 as 0, regardless of the read state of those bits. + */ +void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits); + +/** + * @brief Helper function for safely clearing ADC sequencer register bits + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to clear bits for + * @param bits : Or'ed bits of a sequencer register to clear + * @return Nothing + * @note This function will safely clear the ADC sequencer register bits + * while maintaining bits 20..25 as 0, regardless of the read state of those bits. + */ +void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits); + +/** + * @brief Sets up ADC conversion sequencer A or B + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to setup + * @param options : OR'ed Sequencer options to setup (see notes) + * @return Nothing + * @note Sets up sequencer options for a conversion sequence. This function + * should be used to setup the selected channels for the sequence, the sequencer + * trigger, the trigger polarity, synchronization bypass, priority, and mode. All + * options are passed to the functions as a OR'ed list of values. This function will + * disable/clear the sequencer start/burst/single step/enable if they are enabled.
+ * Select the channels by OR'ing in one or more ADC_SEQ_CTRL_CHANSEL(ch) values.
+ * Select the hardware trigger by OR'ing in one ADC_SEQ_CTRL_HWTRIG_* value.
+ * Select a positive edge hardware trigger by OR'ing in ADC_SEQ_CTRL_HWTRIG_POLPOS.
+ * Select trigger bypass synchronisation by OR'ing in ADC_SEQ_CTRL_HWTRIG_SYNCBYPASS.
+ * Select ADC single step on trigger/start by OR'ing in ADC_SEQ_CTRL_SINGLESTEP.
+ * Select higher priority conversion on the other sequencer by OR'ing in ADC_SEQ_CTRL_LOWPRIO.
+ * Select end of seqeuence instead of end of conversion interrupt by OR'ing in ADC_SEQ_CTRL_MODE_EOS.
+ * Example for setting up sequencer A (channels 0-2, trigger on high edge of PIO0_2, interrupt on end of sequence):
+ * Chip_ADC_SetupSequencer(LPC_ADC, ADC_SEQA_IDX, ( + * ADC_SEQ_CTRL_CHANSEL(0) | ADC_SEQ_CTRL_CHANSEL(1) | ADC_SEQ_CTRL_CHANSEL(2) | + * ADC_SEQ_CTRL_HWTRIG_PIO0_2 | ADC_SEQ_CTRL_HWTRIG_POLPOS | ADC_SEQ_CTRL_MODE_EOS)); + */ +STATIC INLINE void Chip_ADC_SetupSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t options) +{ + pADC->SEQ_CTRL[seqIndex] = options; +} + +/** + * @brief Enables a sequencer + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to enable + * @return Nothing + */ +STATIC INLINE void Chip_ADC_EnableSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex) +{ + Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_SEQ_ENA); +} + +/** + * @brief Disables a sequencer + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to disable + * @return Nothing + */ +STATIC INLINE void Chip_ADC_DisableSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex) +{ + Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_SEQ_ENA); +} + +/** + * @brief Forces a sequencer trigger event (software trigger of ADC) + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to start + * @return Nothing + * @note This function sets the START bit for the sequencer to force a + * single conversion sequence or a single step conversion. + */ +STATIC INLINE void Chip_ADC_StartSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex) +{ + Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_START); +} + +/** + * @brief Starts sequencer burst mode + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to start burst on + * @return Nothing + * @note This function sets the BURST bit for the sequencer to force + * continuous conversion. Use Chip_ADC_StopBurstSequencer() to stop the + * ADC burst sequence. + */ +STATIC INLINE void Chip_ADC_StartBurstSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex) +{ + Chip_ADC_SetSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST); +} + +/** + * @brief Stops sequencer burst mode + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to stop burst on + * @return Nothing + */ +STATIC INLINE void Chip_ADC_StopBurstSequencer(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex) +{ + Chip_ADC_ClearSequencerBits(pADC, seqIndex, ADC_SEQ_CTRL_BURST); +} + +/** ADC sequence global data register threshold comparison range enumerations */ +typedef enum { + ADC_DR_THCMPRANGE_INRANGE, + ADC_DR_THCMPRANGE_RESERVED, + ADC_DR_THCMPRANGE_BELOW, + ADC_DR_THCMPRANGE_ABOVE +} ADC_DR_THCMPRANGE_T; + +/** ADC sequence global data register threshold comparison cross enumerations */ +typedef enum { + ADC_DR_THCMPCROSS_NOCROSS, + ADC_DR_THCMPCROSS_RESERVED, + ADC_DR_THCMPCROSS_DOWNWARD, + ADC_DR_THCMPCROSS_UPWARD +} ADC_DR_THCMPCROSS_T; + +/** + * @brief Read a ADC sequence global data register + * @param pADC : The base of ADC peripheral on the chip + * @param seqIndex : Sequencer to read + * @return Current raw value of the ADC sequence A or B global data register + * @note This function returns the raw value of the data register and clears + * the overrun and datavalid status for the register. Once this register is read, + * the following functions can be used to parse the raw value:
+ * uint32_t adcDataRawValue = Chip_ADC_ReadSequencerDataReg(LPC_ADC, ADC_SEQA_IDX); // Get raw value + * uint32_t adcDataValue = ADC_DR_RESULT(adcDataRawValue); // Aligned and masked ADC data value + * ADC_DR_THCMPRANGE_T adcRange = (ADC_DR_THCMPRANGE_T) ADC_DR_THCMPRANGE(adcDataRawValue); // Sample range compared to threshold low/high + * ADC_DR_THCMPCROSS_T adcRange = (ADC_DR_THCMPCROSS_T) ADC_DR_THCMPCROSS(adcDataRawValue); // Sample cross compared to threshold low + * uint32_t channel = ADC_DR_CHANNEL(adcDataRawValue); // ADC channel for this sample/data + * bool adcDataOverrun = (bool) ((adcDataRawValue & ADC_DR_OVERRUN) != 0); // Data overrun flag + * bool adcDataValid = (bool) ((adcDataRawValue & ADC_SEQ_GDAT_DATAVALID) != 0); // Data valid flag + */ +STATIC INLINE uint32_t Chip_ADC_GetSequencerDataReg(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex) +{ + return pADC->SEQ_GDAT[seqIndex]; +} + +/** + * @brief Read a ADC data register + * @param pADC : The base of ADC peripheral on the chip + * @param index : Data register to read, 1-8 + * @return Current raw value of the ADC data register + * @note This function returns the raw value of the data register and clears + * the overrun and datavalid status for the register. Once this register is read, + * the following functions can be used to parse the raw value:
+ * uint32_t adcDataRawValue = Chip_ADC_ReadSequencerDataReg(LPC_ADC, ADC_SEQA_IDX); // Get raw value + * uint32_t adcDataValue = ADC_DR_RESULT(adcDataRawValue); // Aligned and masked ADC data value + * ADC_DR_THCMPRANGE_T adcRange = (ADC_DR_THCMPRANGE_T) ADC_DR_THCMPRANGE(adcDataRawValue); // Sample range compared to threshold low/high + * ADC_DR_THCMPCROSS_T adcRange = (ADC_DR_THCMPCROSS_T) ADC_DR_THCMPCROSS(adcDataRawValue); // Sample cross compared to threshold low + * uint32_t channel = ADC_DR_CHANNEL(adcDataRawValue); // ADC channel for this sample/data + * bool adcDataOverrun = (bool) ((adcDataRawValue & ADC_DR_OVERRUN) != 0); // Data overrun flag + * bool adcDataValid = (bool) ((adcDataRawValue & ADC_SEQ_GDAT_DATAVALID) != 0); // Data valid flag + */ +STATIC INLINE uint32_t Chip_ADC_GetDataReg(LPC_ADC_T *pADC, uint8_t index) +{ + return pADC->DR[index]; +} + +/** + * @brief Set Threshold low value in ADC + * @param pADC : The base of ADC peripheral on the chip + * @param thrnum : Threshold register value (1 for threshold register 1, 0 for threshold register 0) + * @param value : Threshold low data value (should be 12-bit value) + * @return None + */ +STATIC INLINE void Chip_ADC_SetThrLowValue(LPC_ADC_T *pADC, uint8_t thrnum, uint16_t value) +{ + pADC->THR_LOW[thrnum] = (((uint32_t) value) << ADC_THR_VAL_POS); +} + +/** + * @brief Set Threshold high value in ADC + * @param pADC : The base of ADC peripheral on the chip + * @param thrnum : Threshold register value (1 for threshold register 1, 0 for threshold register 0) + * @param value : Threshold high data value (should be 12-bit value) + * @return None + */ +STATIC INLINE void Chip_ADC_SetThrHighValue(LPC_ADC_T *pADC, uint8_t thrnum, uint16_t value) +{ + pADC->THR_HIGH[thrnum] = (((uint32_t) value) << ADC_THR_VAL_POS); +} + +/** + * @brief Select threshold 0 values for comparison for selected channels + * @param pADC : The base of ADC peripheral on the chip + * @param channels : An OR'ed value of one or more ADC_THRSEL_CHAN_SEL_THR1(ch) values + * @return None + * @note Select multiple channels to use the threshold 0 comparison.
+ * Example:
+ * Chip_ADC_SelectTH0Channels(LPC_ADC, (ADC_THRSEL_CHAN_SEL_THR1(1) | ADC_THRSEL_CHAN_SEL_THR1(2))); // Selects channels 1 and 2 for threshold 0 + */ +void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels); + +/** + * @brief Select threshold 1 value for comparison for selected channels + * @param pADC : The base of ADC peripheral on the chip + * @param channels : An OR'ed value of one or more ADC_THRSEL_CHAN_SEL_THR1(ch) values + * @return None + * @note Select multiple channels to use the 1 threshold comparison.
+ * Example:
+ * Chip_ADC_SelectTH1Channels(LPC_ADC, (ADC_THRSEL_CHAN_SEL_THR1(4) | ADC_THRSEL_CHAN_SEL_THR1(5))); // Selects channels 4 and 5 for 1 threshold + */ +void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels); + +/** + * @brief Enable interrupts in ADC (sequencers A/B and overrun) + * @param pADC : The base of ADC peripheral on the chip + * @param intMask : Interrupt values to be enabled (see notes) + * @return None + * @note Select one or more OR'ed values of ADC_INTEN_SEQA_ENABLE, + * ADC_INTEN_SEQB_ENABLE, and ADC_INTEN_OVRRUN_ENABLE to enable the + * specific ADC interrupts. + */ +void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask); + +/** + * @brief Disable interrupts in ADC (sequencers A/B and overrun) + * @param pADC : The base of ADC peripheral on the chip + * @param intMask : Interrupt values to be disabled (see notes) + * @return None + * @note Select one or more OR'ed values of ADC_INTEN_SEQA_ENABLE, + * ADC_INTEN_SEQB_ENABLE, and ADC_INTEN_OVRRUN_ENABLE to disable the + * specific ADC interrupts. + */ +void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask); + +/** Threshold interrupt event options */ +typedef enum { + ADC_INTEN_THCMP_DISABLE, + ADC_INTEN_THCMP_OUTSIDE, + ADC_INTEN_THCMP_CROSSING, +} ADC_INTEN_THCMP_T; + +/** + * @brief Enable a threshold event interrupt in ADC + * @param pADC : The base of ADC peripheral on the chip + * @param ch : ADC channel to set threshold inetrrupt for, 1-8 + * @param thInt : Selected threshold interrupt type + * @return None + */ +void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt); + +/** + * @brief Get flags register in ADC + * @param pADC : The base of ADC peripheral on the chip + * @return Flags register value (ORed ADC_FLAG* values) + * @note Mask the return value of this function with the ADC_FLAGS_* + * definitions to determine the overall ADC interrupt events.
+ * Example:
+ * if (Chip_ADC_GetFlags(LPC_ADC) & ADC_FLAGS_THCMP_MASK(3) // Check of threshold comp status for ADC channel 3 + */ +STATIC INLINE uint32_t Chip_ADC_GetFlags(LPC_ADC_T *pADC) +{ + return pADC->FLAGS; +} + +/** + * @brief Clear flags register in ADC + * @param pADC : The base of ADC peripheral on the chip + * @param flags : An Or'ed values of ADC_FLAGS_* values to clear + * @return Flags register value (ORed ADC_FLAG* values) + */ +STATIC INLINE void Chip_ADC_ClearFlags(LPC_ADC_T *pADC, uint32_t flags) +{ + pADC->FLAGS = flags; +} + +/** + * @brief Set Trim register in ADC + * @param pADC : The base of ADC peripheral on the chip + * @param trim : Trim value (ADC_TRIM_VRANGE_HIGHV or ADC_TRIM_VRANGE_LOWV) + * @return None + */ +STATIC INLINE void Chip_ADC_SetTrim(LPC_ADC_T *pADC, uint32_t trim) +{ + pADC->TRM = trim; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ADC_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/chip.h b/source/lpc_chip_11u6x/inc/chip.h new file mode 100644 index 0000000..7bb889b --- /dev/null +++ b/source/lpc_chip_11u6x/inc/chip.h @@ -0,0 +1,229 @@ +/* + * @brief LPC11U6x basic chip inclusion file + * + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CHIP_H_ +#define __CHIP_H_ + +#include "lpc_types.h" +#include "sys_config.h" +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef CORE_M0PLUS +#error CORE_M0PLUS is not defined for the LPC11U6x architecture +#error CORE_M0PLUS should be defined as part of your compiler define list +#endif + +#if !defined(CHIP_LPC11U6X) +#error "CHIP_LPC11U6X is not defined!" +#endif + +/** @defgroup PERIPH_11U6X_BASE CHIP: LPC11u6x Peripheral addresses and register set declarations + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +#define LPC_PMU_BASE 0x40038000 +#define LPC_IOCON_BASE 0x40044000 +#define LPC_SYSCTL_BASE 0x40048000 +#define LPC_GPIO_PORT_BASE 0xA0000000 +#define LPC_GPIO_GROUP_INT0_BASE 0x4005C000 +#define LPC_GPIO_GROUP_INT1_BASE 0x40060000 +#define LPC_PIN_INT_BASE 0xA0004000 +#define LPC_USART0_BASE 0x40008000 +#define LPC_USART1_BASE 0x4006C000 +#define LPC_USART2_BASE 0x40070000 +#define LPC_USART3_BASE 0x40074000 +#define LPC_USART4_BASE 0x4004C000 +#define LPC_I2C0_BASE 0x40000000 +#define LPC_I2C1_BASE 0x40020000 +#define LPC_SSP0_BASE 0x40040000 +#define LPC_SSP1_BASE 0x40058000 +#define LPC_USB0_BASE 0x40080000 +#define LPC_ADC_BASE 0x4001C000 +#define LPC_SCT0_BASE 0x5000C000 +#define LPC_SCT1_BASE 0x5000E000 +#define LPC_TIMER16_0_BASE 0x4000C000 +#define LPC_TIMER16_1_BASE 0x40010000 +#define LPC_TIMER32_0_BASE 0x40014000 +#define LPC_TIMER32_1_BASE 0x40018000 +#define LPC_RTC_BASE 0x40024000 +#define LPC_WWDT_BASE 0x40004000 +#define LPC_DMA_BASE 0x50004000 +#define LPC_CRC_BASE 0x50000000 +#define LPC_FLASH_BASE 0x4003C000 +#define LPC_DMATRIGMUX_BASE 0x40028000UL + +#define LPC_PMU ((LPC_PMU_T *) LPC_PMU_BASE) +#define LPC_IOCON ((LPC_IOCON_T *) LPC_IOCON_BASE) +#define LPC_SYSCTL ((LPC_SYSCTL_T *) LPC_SYSCTL_BASE) +#define LPC_GPIO ((LPC_GPIO_T *) LPC_GPIO_PORT_BASE) +#define LPC_GPIOGROUP ((LPC_GPIOGROUPINT_T *) LPC_GPIO_GROUP_INT0_BASE) +#define LPC_PININT ((LPC_PIN_INT_T *) LPC_PIN_INT_BASE) +#define LPC_USART0 ((LPC_USART0_T *) LPC_USART0_BASE) +#define LPC_USART1 ((LPC_USARTN_T *) LPC_USART1_BASE) +#define LPC_USART2 ((LPC_USARTN_T *) LPC_USART2_BASE) +#define LPC_USART3 ((LPC_USARTN_T *) LPC_USART3_BASE) +#define LPC_USART4 ((LPC_USARTN_T *) LPC_USART4_BASE) +#define LPC_I2C0 ((LPC_I2C_T *) LPC_I2C0_BASE) +#define LPC_I2C1 ((LPC_I2C_T *) LPC_I2C1_BASE) +#define LPC_SSP0 ((LPC_SSP_T *) LPC_SSP0_BASE) +#define LPC_SSP1 ((LPC_SSP_T *) LPC_SSP1_BASE) +#define LPC_USB ((LPC_USB_T *) LPC_USB0_BASE) +#define LPC_ADC ((LPC_ADC_T *) LPC_ADC_BASE) +#define LPC_SCT0 ((LPC_SCT_T *) LPC_SCT0_BASE) +#define LPC_SCT1 ((LPC_SCT_T *) LPC_SCT1_BASE) +#define LPC_TIMER16_0 ((LPC_TIMER_T *) LPC_TIMER16_0_BASE) +#define LPC_TIMER16_1 ((LPC_TIMER_T *) LPC_TIMER16_1_BASE) +#define LPC_TIMER32_0 ((LPC_TIMER_T *) LPC_TIMER32_0_BASE) +#define LPC_TIMER32_1 ((LPC_TIMER_T *) LPC_TIMER32_1_BASE) +#define LPC_RTC ((LPC_RTC_T *) LPC_RTC_BASE) +#define LPC_WWDT ((LPC_WWDT_T *) LPC_WWDT_BASE) +#define LPC_DMA ((LPC_DMA_T *) LPC_DMA_BASE) +#define LPC_DMATRIGMUX ((LPC_DMATRIGMUX_T *) LPC_DMATRIGMUX_BASE) +#define LPC_CRC ((LPC_CRC_T *) LPC_CRC_BASE) +#define LPC_FMC ((LPC_FMC_T *) LPC_FLASH_BASE) + +/* IRQ Handler Alias list */ +#define UART1_4_IRQHandler USART1_4_IRQHandler +#define UART2_3_IRQHandler USART2_3_IRQHandler +#define UART0_IRQHandler USART0_IRQHandler + +/** + * @} + */ + +/** @ingroup CHIP_11U6X_DRIVER_OPTIONS + * @{ + */ + +/** + * @brief System oscillator rate + * This value is defined externally to the chip layer and contains + * the value in Hz for the external oscillator for the board. If using the + * internal oscillator, this rate can be 0. + */ +extern const uint32_t OscRateIn; + +/** + * @brief RTC oscillator rate + * This value is defined externally to the chip layer and contains + * the value in Hz for the RTC oscillator for the board. This is + * usually 32KHz (32768). If not using the RTC, this rate can be 0. + */ +extern const uint32_t RTCOscRateIn; + +/** + * @} + */ + +/* Include order is important! */ +#include "romapi_11u6x.h" +#include "syscon_11u6x.h" +#include "clock_11u6x.h" +#include "iocon_11u6x.h" +#include "pmu_11u6x.h" +#include "crc_11u6x.h" +#include "gpio_11u6x.h" +#include "pinint_11u6x.h" +#include "gpiogroup_11u6x.h" +#include "timer_11u6x.h" +#include "uart_0_11u6x.h" +#include "uart_n_11u6x.h" +#include "ssp_11u6x.h" +#include "adc_11u6x.h" +#include "dma_11u6x.h" +#include "i2c_11u6x.h" +#include "i2cm_11u6x.h" +#include "usbd_11u6x.h" +#include "sct_11u6x.h" +#include "rtc_11u6x.h" +#include "wwdt_11u6x.h" +#include "fmc_11u6x.h" + +/** @defgroup SUPPORT_11U6X_FUNC CHIP: LPC11u6x support functions + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief Current system clock rate, mainly used for sysTick + */ +extern uint32_t SystemCoreClock; + +/** + * @brief Update system core clock rate, should be called if the + * system has a clock rate change + * @return None + */ +void SystemCoreClockUpdate(void); + +/** + * @brief Set up and initialize hardware prior to call to main() + * @return None + * @note Chip_SystemInit() is called prior to the application and sets up + * system clocking prior to the application starting. + */ +void Chip_SystemInit(void); + +/** + * @brief USB Pin and clock initialization + * Calling this function will initialize the USB pins and the clock + * @return None + * @note This function will assume that the chip is clocked by an + * external crystal oscillator of frequency 12MHz and the Oscillator + * is running. + */ +void Chip_USB_Init(void); + +/** + * @brief Clock and PLL initialization based on the external oscillator + * @return None + * @note This function assumes an external crystal oscillator + * frequency of 12MHz. + */ +void Chip_SetupXtalClocking(void); + +/** + * @brief Clock and PLL initialization based on the internal oscillator + * @return None + */ +void Chip_SetupIrcClocking(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CHIP_H_ */ diff --git a/source/lpc_chip_11u6x/inc/clock_11u6x.h b/source/lpc_chip_11u6x/inc/clock_11u6x.h new file mode 100644 index 0000000..600f087 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/clock_11u6x.h @@ -0,0 +1,589 @@ +/* + * @brief LPC11U6X Clock control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CLOCK_11U6X_H_ +#define __CLOCK_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CLOCK_11U6X CHIP: LPC11u6x Clock Control block driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** Internal oscillator frequency */ +#define SYSCTL_IRC_FREQ (12000000) + +/** + * @brief Set System PLL divider values + * @param msel : PLL feedback divider value. M = msel + 1. + * @param psel : PLL post divider value. P = (1<SYSPLLCTRL = (msel & 0x1F) | ((psel & 0x3) << 5); +} + +/** + * @brief Read System PLL lock status + * @return true of the PLL is locked. false if not locked + */ +STATIC INLINE bool Chip_Clock_IsSystemPLLLocked(void) +{ + return (bool) ((LPC_SYSCTL->SYSPLLSTAT & 1) != 0); +} + +/** + * Clock sources for system PLL + */ +typedef enum CHIP_SYSCTL_PLLCLKSRC { + SYSCTL_PLLCLKSRC_IRC = 0, /*!< Internal oscillator in */ + SYSCTL_PLLCLKSRC_MAINOSC, /*!< Crystal (main) oscillator in */ + SYSCTL_PLLCLKSRC_SYSOSC = SYSCTL_PLLCLKSRC_MAINOSC, + SYSCTL_PLLCLKSRC_RESERVED1, /*!< Reserved */ + SYSCTL_PLLCLKSRC_RTC32K, /*!< RTC 32KHz clock */ +} CHIP_SYSCTL_PLLCLKSRC_T; + +/** + * @brief Set System PLL clock source + * @param src : Clock source for system PLL + * @return Nothing + * @note This function will also toggle the clock source update register + * to update the clock source. + */ +void Chip_Clock_SetSystemPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src); + +/** + * @brief Set USB PLL divider values + * @param msel : PLL feedback divider value. M = msel + 1. + * @param psel : PLL post divider value. P = (1<USBPLLCTRL = (msel & 0x1F) | ((psel & 0x3) << 5); +} + +/** + * @brief Read USB PLL lock status + * @return true of the PLL is locked. false if not locked + */ +STATIC INLINE bool Chip_Clock_IsUSBPLLLocked(void) +{ + return (bool) ((LPC_SYSCTL->USBPLLSTAT & 1) != 0); +} + +/** + * Clock sources for USB PLL + */ +typedef enum CHIP_SYSCTL_USBPLLCLKSRC { + SYSCTL_USBPLLCLKSRC_IRC = 0, /*!< Internal oscillator in */ + SYSCTL_USBPLLCLKSRC_MAINOSC, /*!< Crystal (main) oscillator in */ + SYSCTL_USBPLLCLKSRC_SYSOSC = SYSCTL_USBPLLCLKSRC_MAINOSC, + SYSCTL_USBPLLCLKSRC_RESERVED1, /*!< Reserved */ + SYSCTL_USBPLLCLKSRC_RESERVED2, /*!< Reserved */ +} CHIP_SYSCTL_USBPLLCLKSRC_T; + +/** + * @brief Set USB PLL clock source + * @param src : Clock source for USB PLL + * @return Nothing + * @note This function will also toggle the clock source update register + * to update the clock source. + */ +void Chip_Clock_SetUSBPLLSource(CHIP_SYSCTL_USBPLLCLKSRC_T src); + +/** + * @brief Bypass System Oscillator and set oscillator frequency range + * @param bypass : Flag to bypass oscillator + * @param highfr : Flag to set oscillator range from 15-25 MHz + * @return Nothing + * @note Sets the PLL input to bypass the oscillator. This would be + * used if an external clock that is not an oscillator is attached + * to the XTALIN pin. + */ +void Chip_Clock_SetPLLBypass(bool bypass, bool highfr); + +/** + * @brief Enable the RTC 32KHz output + * @return Nothing + * @note This clock can be used for the main clock directly, but + * do not use this clock with the system PLL. + */ +STATIC INLINE void Chip_Clock_EnableRTCOsc(void) +{ + LPC_SYSCTL->RTCOSCCTRL = 1; +} + +/** + * @brief Disable the RTC 32KHz output + * @return Nothing + */ +STATIC INLINE void Chip_Clock_DisableRTCOsc(void) +{ + LPC_SYSCTL->RTCOSCCTRL = 0; +} + +/** + * Watchdog and low frequency oscillator frequencies plus or minus 40% + */ +typedef enum CHIP_WDTLFO_OSC { + WDTLFO_OSC_ILLEGAL, + WDTLFO_OSC_0_60, /*!< 0.6 MHz watchdog/LFO rate */ + WDTLFO_OSC_1_05, /*!< 1.05 MHz watchdog/LFO rate */ + WDTLFO_OSC_1_40, /*!< 1.4 MHz watchdog/LFO rate */ + WDTLFO_OSC_1_75, /*!< 1.75 MHz watchdog/LFO rate */ + WDTLFO_OSC_2_10, /*!< 2.1 MHz watchdog/LFO rate */ + WDTLFO_OSC_2_40, /*!< 2.4 MHz watchdog/LFO rate */ + WDTLFO_OSC_2_70, /*!< 2.7 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_00, /*!< 3.0 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_25, /*!< 3.25 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_50, /*!< 3.5 MHz watchdog/LFO rate */ + WDTLFO_OSC_3_75, /*!< 3.75 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_00, /*!< 4.0 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_20, /*!< 4.2 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_40, /*!< 4.4 MHz watchdog/LFO rate */ + WDTLFO_OSC_4_60 /*!< 4.6 MHz watchdog/LFO rate */ +} CHIP_WDTLFO_OSC_T; + +/** + * @brief Setup Watchdog oscillator rate and divider + * @param wdtclk : Selected watchdog clock rate + * @param div : Watchdog divider value, even value between 2 and 64 + * @return Nothing + * @note Watchdog rate = selected rate divided by divider rate + */ +STATIC INLINE void Chip_Clock_SetWDTOSC(CHIP_WDTLFO_OSC_T wdtclk, uint8_t div) +{ + LPC_SYSCTL->WDTOSCCTRL = (((uint32_t) wdtclk) << 5) | ((div >> 1) - 1); +} + +/** + * Clock sources for main system clock + */ +typedef enum CHIP_SYSCTL_MAINCLKSRC { + SYSCTL_MAINCLKSRC_IRC = 0, /*!< Internal oscillator */ + SYSCTL_MAINCLKSRC_PLLIN, /*!< System PLL input */ + SYSCTL_MAINCLKSRC_WDTOSC, /*!< Watchdog oscillator rate */ + SYSCTL_MAINCLKSRC_PLLOUT, /*!< System PLL output */ +} CHIP_SYSCTL_MAINCLKSRC_T; + +/** + * @brief Set main system clock source + * @param src : Clock source for main system + * @return Nothing + * @note This function will also toggle the clock source update register + * to update the clock source. + */ +void Chip_Clock_SetMainClockSource(CHIP_SYSCTL_MAINCLKSRC_T src); + +/** + * @brief Returns the main clock source + * @return Which clock is used for the core clock source? + */ +STATIC INLINE CHIP_SYSCTL_MAINCLKSRC_T Chip_Clock_GetMainClockSource(void) +{ + return (CHIP_SYSCTL_MAINCLKSRC_T) (LPC_SYSCTL->MAINCLKSEL); +} + +/** + * @brief Set system clock divider + * @param div : divider for system clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The system clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetSysClockDiv(uint32_t div) +{ + LPC_SYSCTL->SYSAHBCLKDIV = div; +} + +/** + * System and peripheral clocks + */ +typedef enum CHIP_SYSCTL_CLOCK { + SYSCTL_CLOCK_SYS = 0, /*!< 0: System clock */ + SYSCTL_CLOCK_ROM, /*!< 1: ROM clock */ + SYSCTL_CLOCK_RAM0, /*!< 2: RAM0 clock */ + SYSCTL_CLOCK_FLASHREG, /*!< 3: FLASH register interface clock */ + SYSCTL_CLOCK_FLASHARRAY, /*!< 4: FLASH array access clock */ + SYSCTL_CLOCK_I2C0, /*!< 5: I2C0 clock */ + SYSCTL_CLOCK_GPIO, /*!< 6: GPIO clock */ + SYSCTL_CLOCK_CT16B0, /*!< 7: 16-bit Counter/timer 0 clock */ + SYSCTL_CLOCK_CT16B1, /*!< 8: 16-bit Counter/timer 1 clock */ + SYSCTL_CLOCK_CT32B0, /*!< 9: 32-bit Counter/timer 0 clock */ + SYSCTL_CLOCK_CT32B1, /*!< 10: 32-bit Counter/timer 1 clock */ + SYSCTL_CLOCK_SSP0, /*!< 11: SSP0 clock */ + SYSCTL_CLOCK_UART0, /*!< 12: UART0 clock */ + SYSCTL_CLOCK_ADC, /*!< 13: ADC clock */ + SYSCTL_CLOCK_USB, /*!< 14: USB clock */ + SYSCTL_CLOCK_WDT, /*!< 15: Watchdog timer clock */ + SYSCTL_CLOCK_IOCON, /*!< 16: IOCON block clock */ + SYSCTL_CLOCK_RESERVED17, /*!< 17: Reserved */ + SYSCTL_CLOCK_SSP1, /*!< 18: SSP1 clock */ + SYSCTL_CLOCK_PINT, /*!< 19: GPIO Pin int register interface clock */ + SYSCTL_CLOCK_USART1, /*!< 20: USART1 clock */ + SYSCTL_CLOCK_USART2, /*!< 21: USART2 clock */ + SYSCTL_CLOCK_USART3_4, /*!< 22: USART3_4 clock */ + SYSCTL_CLOCK_P0INT, /*!< 23: GPIO GROUP1 interrupt register clock */ + SYSCTL_CLOCK_GROUP0INT = SYSCTL_CLOCK_P0INT,/*!< 23: GPIO GROUP0 interrupt register interface clock */ + SYSCTL_CLOCK_P1INT, /*!< 24: GPIO GROUP1 interrupt register clock */ + SYSCTL_CLOCK_GROUP1INT = SYSCTL_CLOCK_P1INT,/*!< 24: GPIO GROUP1 interrupt register interface clock */ + SYSCTL_CLOCK_I2C1, /*!< 25: I2C1 clock */ + SYSCTL_CLOCK_RAM1, /*!< 26: SRAM block clock */ + SYSCTL_CLOCK_USBRAM, /*!< 27: USB SRAM block clock */ + SYSCTL_CLOCK_CRC, /*!< 25: CRC clock */ + SYSCTL_CLOCK_DMA, /*!< 25: DMA clock */ + SYSCTL_CLOCK_RTC, /*!< 25: RTC clock */ + SYSCTL_CLOCK_SCT0_1, /*!< 25: SCT 0/1 clock */ +} CHIP_SYSCTL_CLOCK_T; + +/** + * @brief Enable a system or peripheral clock + * @param clk : Clock to enable + * @return Nothing + */ +STATIC INLINE void Chip_Clock_EnablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) +{ + LPC_SYSCTL->SYSAHBCLKCTRL |= (1 << clk); +} + +/** + * @brief Disable a system or peripheral clock + * @param clk : Clock to disable + * @return Nothing + */ +STATIC INLINE void Chip_Clock_DisablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) +{ + LPC_SYSCTL->SYSAHBCLKCTRL &= ~(1 << clk); +} + +/** + * @brief Set SSP0 divider + * @param div : divider for SSP0 clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The SSP0 clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetSSP0ClockDiv(uint32_t div) +{ + LPC_SYSCTL->SSP0CLKDIV = div; +} + +/** + * @brief Return SSP0 divider + * @return divider for SSP0 clock + * @note A value of 0 means the clock is disabled. + */ +STATIC INLINE uint32_t Chip_Clock_GetSSP0ClockDiv(void) +{ + return LPC_SYSCTL->SSP0CLKDIV; +} + +/** + * @brief Set USART0 divider clock + * @param div : divider for UART clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The UART clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetUSART0ClockDiv(uint32_t div) +{ + LPC_SYSCTL->USART0CLKDIV = div; +} + +/** + * @brief Return USART0 divider + * @return divider for UART clock + * @note A value of 0 means the clock is disabled. + */ +STATIC INLINE uint32_t Chip_Clock_GetUASRT0ClockDiv(void) +{ + return LPC_SYSCTL->USART0CLKDIV; +} + +/** + * @brief Set SSP1 divider clock + * @param div : divider for SSP1 clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The SSP1 clock + * rate is the main system clock divided by this value. + */ +STATIC INLINE void Chip_Clock_SetSSP1ClockDiv(uint32_t div) +{ + LPC_SYSCTL->SSP1CLKDIV = div; +} + +/** + * @brief Return SSP1 divider + * @return divider for SSP1 clock + * @note A value of 0 means the clock is disabled. + */ +STATIC INLINE uint32_t Chip_Clock_GetSSP1ClockDiv(void) +{ + return LPC_SYSCTL->SSP1CLKDIV; +} + +/** + * @brief Set USART 1/2/3/4 UART base rate (up to main clock rate) + * @param rate : Desired rate for fractional divider/multipler output + * @param fEnable : true to use fractional clocking, false for integer clocking + * @return Actual rate generated + * @note USARTs 1 - 4 use the same base clock for their baud rate + * basis. This function is used to generate that clock, while the + * UART driver's SetBaud functions will attempt to get the closest + * baud rate from this base clock without altering it. This needs + * to be setup prior to individual UART setup.
+ * UARTs need a base clock 16x faster than the baud rate, so if you + * need a 115.2Kbps baud rate, you will need a clock rate of at + * least (115.2K * 16). The UART base clock is generated from the + * main system clock, so fractional clocking may be the only + * possible choice when using a low main system clock frequency. + * Do not alter the FRGCLKDIV register after this call. + */ +uint32_t Chip_Clock_SetUSARTNBaseClockRate(uint32_t rate, bool fEnable); + +/** + * @brief Get USART 1/2/3/4 UART base rate + * @return USART 1/2/3/4 UART base rate + */ +uint32_t Chip_Clock_GetUSARTNBaseClockRate(void); + +/** + * @brief Set USART 1/2/3/4 fractional baud rate divider clock + * @param div : divider for USART 1/2/3/4 fractional baud rate clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. + * This does not affect USART0. + */ +STATIC INLINE void Chip_Clock_SetUSARTNBaseClockDiv(uint8_t div) +{ + LPC_SYSCTL->FRGCLKDIV = (uint32_t) div; +} + +/** + * @brief Return USART 1/2/3/4 fractional baud rate divider + * @return divider for USART 1/2/3/4 fractional baud rate clock + * @note A value of 0 means the clock is disabled. + * This does not affect USART0. + */ +STATIC INLINE uint32_t Chip_Clock_GetUSARTNBaseClockDiv(void) +{ + return LPC_SYSCTL->FRGCLKDIV; +} + +/** + * @brief Set The USART Fractional Generator Divider + * @param div : Fractional Generator Divider value, should be 0xFF + * @return Nothing + */ +STATIC INLINE void Chip_Clock_SetUSARTNFRGDivider(uint8_t div) +{ + LPC_SYSCTL->UARTFRGDIV = (uint32_t) div; +} + +/** + * @brief Set The USART Fractional Generator Divider + * @return Value of USART Fractional Generator Divider + */ +STATIC INLINE uint32_t Chip_Clock_GetUSARTNFRGDivider(void) +{ + return LPC_SYSCTL->UARTFRGDIV; +} + +/** + * @brief Set The USART Fractional Generator Multiplier + * @param mult : An 8-bit value (0-255) U_PCLK = UARTCLKDIV/(1 + MULT/256) + * @return Nothing + */ +STATIC INLINE void Chip_Clock_SetUSARTNFRGMultiplier(uint8_t mult) +{ + LPC_SYSCTL->UARTFRGMULT = (uint32_t) mult; +} + +/** + * @brief Get The USART Fractional Generator Multiplier + * @return Value of USART Fractional Generator Multiplier + */ +STATIC INLINE uint32_t Chip_Clock_GetUSARTNFRGMultiplier(void) +{ + return LPC_SYSCTL->UARTFRGMULT; +} + +/** + * Clock sources for USB + */ +typedef enum CHIP_SYSCTL_USBCLKSRC { + SYSCTL_USBCLKSRC_PLLOUT = 0, /*!< USB PLL out */ + SYSCTL_USBCLKSRC_MAINSYSCLK, /*!< Main system clock */ +} CHIP_SYSCTL_USBCLKSRC_T; + +/** + * @brief Set USB clock source and divider + * @param src : Clock source for USB + * @param div : divider for USB clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The USB clock + * rate is either the main system clock or USB PLL output clock divided + * by this value. This function will also toggle the clock source + * update register to update the clock source. + */ +void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src, uint32_t div); + +/** + * Clock sources for CLKOUT + */ +typedef enum CHIP_SYSCTL_CLKOUTSRC { + SYSCTL_CLKOUTSRC_IRC = 0, /*!< Internal oscillator for CLKOUT */ + SYSCTL_CLKOUTSRC_MAINOSC, /*!< Main oscillator for CLKOUT */ + SYSCTL_CLKOUTSRC_SYSOSC = SYSCTL_CLKOUTSRC_MAINOSC, + SYSCTL_CLKOUTSRC_WDTOSC, /*!< Watchdog oscillator for CLKOUT */ + SYSCTL_CLKOUTSRC_MAINSYSCLK, /*!< Main system clock for CLKOUT */ +} CHIP_SYSCTL_CLKOUTSRC_T; + +/** + * @brief Set CLKOUT clock source and divider + * @param src : Clock source for CLKOUT + * @param div : divider for CLKOUT clock + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. The CLKOUT clock + * rate is the clock source divided by the divider. This function will + * also toggle the clock source update register to update the clock + * source. + */ +void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src, uint32_t div); + +/** + * @brief Set IOCON glitch filter clock divider value + * @param index : IOCON divider index (0 - 6) to set + * @param div : value for IOCON filter divider value + * @return Nothing + * @note Use 0 to disable, or a divider value of 1 to 255. + */ +STATIC INLINE void Chip_Clock_SetIOCONFiltClockDiv(int index, uint32_t div) +{ + LPC_SYSCTL->IOCONCLKDIV[6 - index] = div; +} + +/** + * @brief Return IOCON glitch filter clock divider value + * @param index : IOCON divider index (0 - 6) to get + * @return IOCON glitch filter clock divider value + */ +STATIC INLINE uint32_t Chip_Clock_GetIOCONFiltClockDiv(int index) +{ + return LPC_SYSCTL->IOCONCLKDIV[6 - index]; +} + +/** + * @brief Returns the main oscillator clock rate + * @return main oscillator clock rate in Hz + */ +STATIC INLINE uint32_t Chip_Clock_GetMainOscRate(void) +{ + return OscRateIn; +} + +/** + * @brief Returns the internal oscillator (IRC) clock rate + * @return internal oscillator (IRC) clock rate in Hz + */ +STATIC INLINE uint32_t Chip_Clock_GetIntOscRate(void) +{ + return SYSCTL_IRC_FREQ; +} + +/** + * @brief Returns the RTC clock rate + * @return RTC oscillator clock rate in Hz + */ +STATIC INLINE uint32_t Chip_Clock_GetRTCOscRate(void) +{ + return RTCOscRateIn; +} + +/** + * @brief Return estimated watchdog oscillator rate + * @return Estimated watchdog oscillator rate + * @note This rate is accurate to plus or minus 40%. + */ +uint32_t Chip_Clock_GetWDTOSCRate(void); + +/** + * @brief Return System PLL input clock rate + * @return System PLL input clock rate + */ +uint32_t Chip_Clock_GetSystemPLLInClockRate(void); + +/** + * @brief Return System PLL output clock rate + * @return System PLL output clock rate + */ +uint32_t Chip_Clock_GetSystemPLLOutClockRate(void); + +/** + * @brief Return USB PLL input clock rate + * @return USB PLL input clock rate + */ +uint32_t Chip_Clock_GetUSBPLLInClockRate(void); + +/** + * @brief Return USB PLL output clock rate + * @return USB PLL output clock rate + */ +uint32_t Chip_Clock_GetUSBPLLOutClockRate(void); + +/** + * @brief Return main clock rate + * @return main clock rate + */ +uint32_t Chip_Clock_GetMainClockRate(void); + +/** + * @brief Return system clock rate + * @return system clock rate + */ +uint32_t Chip_Clock_GetSystemClockRate(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CLOCK_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/cmsis.h b/source/lpc_chip_11u6x/inc/cmsis.h new file mode 100644 index 0000000..7fd0c75 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/cmsis.h @@ -0,0 +1,153 @@ +/* + * @brief Basic CMSIS include file for LPC11U6X + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CMSIS_11U6X_H_ +#define __CMSIS_11U6X_H_ + +#include "lpc_types.h" +#include "sys_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CMSIS_11U6X CHIP: LPC11U6X CMSIS include file + * @ingroup CHIP_11U6X_CMSIS_Drivers + * @{ + */ + +#if defined(__ARMCC_VERSION) +// Kill warning "#pragma push with no matching #pragma pop" + #pragma diag_suppress 2525 + #pragma push + #pragma anon_unions +#elif defined(__CWCC__) + #pragma push + #pragma cpp_extensions on +#elif defined(__GNUC__) +/* anonymous unions are enabled by default */ +#elif defined(__IAR_SYSTEMS_ICC__) +// #pragma push // FIXME not usable for IAR + #pragma language=extended +#else + #error Not supported compiler type +#endif + +/* + * ========================================================================== + * ---------- Interrupt Number Definition ----------------------------------- + * ========================================================================== + */ + +#if !defined(CHIP_LPC11U6X) +#error Incorrect or missing device variant (CHIP_LPC11U6X) +#endif + +/** @defgroup CMSIS_11U6X_IRQ CHIP_LPC11U6X: CHIP_LPC11U6X peripheral interrupt numbers + * @{ + */ + +typedef enum { + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M0 Hard Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M0 SV Call Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M0 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M0 System Tick Interrupt */ + + PIN_INT0_IRQn = 0, /*!< Pin Interrupt 0 */ + PIN_INT1_IRQn = 1, /*!< Pin Interrupt 1 */ + PIN_INT2_IRQn = 2, /*!< Pin Interrupt 2 */ + PIN_INT3_IRQn = 3, /*!< Pin Interrupt 3 */ + PIN_INT4_IRQn = 4, /*!< Pin Interrupt 4 */ + PIN_INT5_IRQn = 5, /*!< Pin Interrupt 5 */ + PIN_INT6_IRQn = 6, /*!< Pin Interrupt 6 */ + PIN_INT7_IRQn = 7, /*!< Pin Interrupt 7 */ + GINT0_IRQn = 8, /*!< GPIO interrupt status of port 0 */ + GINT1_IRQn = 9, /*!< GPIO interrupt status of port 1 */ + I2C1_IRQn = 10, /*!< I2C1 Interrupt */ + USART1_4_IRQn = 11, /*!< Combined USART1 and USART4 interrupts */ + USART2_3_IRQn = 12, /*!< Combined USART2 and USART3 interrupts */ + SCT0_1_IRQn = 13, /*!< Combined SCT0 and SCT1 interrupts */ + SSP1_IRQn = 14, /*!< SSP1 Interrupt */ + I2C0_IRQn = 15, /*!< I2C0 Interrupt */ + TIMER_16_0_IRQn = 16, /*!< 16-bit Timer0 Interrupt */ + TIMER_16_1_IRQn = 17, /*!< 16-bit Timer1 Interrupt */ + TIMER_32_0_IRQn = 18, /*!< 32-bit Timer0 Interrupt */ + TIMER_32_1_IRQn = 19, /*!< 32-bit Timer1 Interrupt */ + SSP0_IRQn = 20, /*!< SSP0 Interrupt */ + USART0_IRQn = 21, /*!< USART0 interrupt */ + USB0_IRQn = 22, /*!< USB IRQ interrupt */ + USB0_FIQ_IRQn = 23, /*!< USB FIQ interrupt */ + ADC_A_IRQn = 24, /*!< ADC_A Converter Interrupt */ + RTC_IRQn = 25, /*!< RTC Interrupt */ + BOD_WDT_IRQn = 26, /*!< Shared Brown Out Detect(BOD) and WDT Interrupts */ + FMC_IRQn = 27, /*!< FLASH Interrupt */ + DMA_IRQn = 28, /*!< DMA Interrupt */ + ADC_B_IRQn = 29, /*!< ADC_B Interrupt */ + USB_WAKEUP_IRQn = 30, /*!< USB wake-up interrupt Interrupt */ + RESERVED31_IRQn = 31, +} IRQn_Type; + +/** + * @} + */ + +/* + * ========================================================================== + * ----------- Processor and Core Peripheral Section ------------------------ + * ========================================================================== + */ + +/** @defgroup CMSIS_11U6X_COMMON CHIP: LPC11U6X Cortex CMSIS definitions + * @{ + */ + +/* Configuration of the Cortex-M0+ Processor and Core Peripherals */ +#define __CM0_REV 0x0000 /*!< Cortex-M0 Core Revision */ +#define __MPU_PRESENT 0 /*!< MPU present or not */ +#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ + +/** + * @} + */ + +#include "core_cm0plus.h" /*!< Cortex-M0+ processor and core peripherals */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CMSIS_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/core_cm0plus.h b/source/lpc_chip_11u6x/inc/core_cm0plus.h new file mode 100644 index 0000000..5cea74e --- /dev/null +++ b/source/lpc_chip_11u6x/inc/core_cm0plus.h @@ -0,0 +1,793 @@ +/**************************************************************************//** + * @file core_cm0plus.h + * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** \ingroup Cortex-M0+ + @{ + */ + +/* CMSIS CM0P definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16) | \ + __CM0PLUS_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#endif + +/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all +*/ +#define __FPU_USED 0 + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif +#endif + +#include /* standard types definitions */ +#include /* Core Instruction Access */ +#include /* Core Function Access */ + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0PLUS_REV + #define __CM0PLUS_REV 0x0000 + #warning "__CM0PLUS_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0 + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0 + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2 + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0 + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ +#else + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ +#endif + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + + +/** \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + + +/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ +#if (__CORTEX_M != 0x04) + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ +#else + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ +#endif + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + + +/** \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/*@} end of group CMSIS_CORE */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IO uint32_t ISER[1]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31]; + __IO uint32_t ICER[1]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31]; + __IO uint32_t ISPR[1]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31]; + __IO uint32_t ICPR[1]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31]; + uint32_t RESERVED4[64]; + __IO uint32_t IP[8]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if (__VTOR_PRESENT == 1) + __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IO uint32_t SHP[2]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if (__VTOR_PRESENT == 1) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8 /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1) +/** \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register */ +#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register */ +#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register */ +#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register */ +#define MPU_RBAR_ADDR_Pos 8 /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register */ +#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) + are only accessible over DAP and not via processor. Therefore + they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0+ Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( (((uint32_t)(IRQn) ) & 0x03) * 8 ) +#define _SHP_IDX(IRQn) ( ((((uint32_t)(IRQn) & 0x0F)-8) >> 2) ) +#define _IP_IDX(IRQn) ( ((uint32_t)(IRQn) >> 2) ) + + +/** \brief Enable External Interrupt + + The function enables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Disable External Interrupt + + The function disables a device-specific interrupt in the NVIC interrupt controller. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Get Pending Interrupt + + The function reads the pending register in the NVIC and returns the pending bit + for the specified interrupt. + + \param [in] IRQn Interrupt number. + + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t) ((NVIC->ISPR[0] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); +} + + +/** \brief Set Pending Interrupt + + The function sets the pending bit of an external interrupt. + + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); +} + + +/** \brief Clear Pending Interrupt + + The function clears the pending bit of an external interrupt. + + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ +} + + +/** \brief Set Interrupt Priority + + The function sets the priority of an interrupt. + + \note The priority cannot be set for every core interrupt. + + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if(IRQn < 0) { + SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } + else { + NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) | + (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); } +} + + +/** \brief Get Interrupt Priority + + The function reads the priority of an interrupt. The interrupt + number can be positive to specify an external (device specific) + interrupt, or negative to specify an internal (core) interrupt. + + + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented + priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if(IRQn < 0) { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */ + else { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & 0xFF) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ +} + + +/** \brief System Reset + + The function initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + while(1); /* wait until reset */ +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0) + +/** \brief System Tick Configuration + + The function initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + + \param [in] ticks Number of ticks between two interrupts. + + \return 0 Function succeeded. + \return 1 Function failed. + + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ + + SysTick->LOAD = ticks - 1; /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ + +#ifdef __cplusplus +} +#endif diff --git a/source/lpc_chip_11u6x/inc/core_cmFunc.h b/source/lpc_chip_11u6x/inc/core_cmFunc.h new file mode 100644 index 0000000..0a18faf --- /dev/null +++ b/source/lpc_chip_11u6x/inc/core_cmFunc.h @@ -0,0 +1,636 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V3.20 + * @date 25. February 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xff); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/** \brief Enable IRQ Interrupts + + This function enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** \brief Disable IRQ Interrupts + + This function disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** \brief Get Control Register + + This function returns the content of the Control Register. + + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** \brief Set Control Register + + This function writes the given value to the Control Register. + + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** \brief Get IPSR Register + + This function returns the content of the IPSR Register. + + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get APSR Register + + This function returns the content of the APSR Register. + + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get xPSR Register + + This function returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** \brief Get Process Stack Pointer + + This function returns the current value of the Process Stack Pointer (PSP). + + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Process Stack Pointer + + This function assigns the given value to the Process Stack Pointer (PSP). + + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** \brief Get Main Stack Pointer + + This function returns the current value of the Main Stack Pointer (MSP). + + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** \brief Set Main Stack Pointer + + This function assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** \brief Get Priority Mask + + This function returns the current state of the priority mask bit from the Priority Mask Register. + + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Priority Mask + + This function assigns the given value to the Priority Mask Register. + + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03) + +/** \brief Enable FIQ + + This function enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** \brief Disable FIQ + + This function disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** \brief Get Base Priority + + This function returns the current value of the Base Priority register. + + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); + return(result); +} + + +/** \brief Set Base Priority + + This function assigns the given value to the Base Priority register. + + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** \brief Get Fault Mask + + This function returns the current value of the Fault Mask register. + + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** \brief Set Fault Mask + + This function assigns the given value to the Fault Mask register. + + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + +#if (__CORTEX_M == 0x04) + +/** \brief Get FPSCR + + This function returns the current value of the Floating Point Status/Control register. + + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** \brief Set FPSCR + + This function assigns the given value to the Floating Point Status/Control register. + + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04) */ + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all instrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +#endif /* __CORE_CMFUNC_H */ diff --git a/source/lpc_chip_11u6x/inc/core_cmInstr.h b/source/lpc_chip_11u6x/inc/core_cmInstr.h new file mode 100644 index 0000000..d213f0e --- /dev/null +++ b/source/lpc_chip_11u6x/inc/core_cmInstr.h @@ -0,0 +1,688 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V3.20 + * @date 05. March 2013 + * + * @note + * + ******************************************************************************/ +/* Copyright (c) 2009 - 2013 ARM LIMITED + + All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + - Neither the name of ARM nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + * + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + ---------------------------------------------------------------------------*/ + + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ +/* ARM armcc specific functions */ + +#if (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __rbit + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH(value, ptr) __strex(value, ptr) + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW(value, ptr) __strex(value, ptr) + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +#define __CLREX __clrex + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + +#endif /* (__CORTEX_M >= 0x03) */ + + + +#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ +/* IAR iccarm specific functions */ + +#include + + +#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ +/* TI CCS specific functions */ + +#include + + +#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ +/* GNU gcc specific functions */ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constrant "l" + * Otherwise, use general registers, specified by constrant "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** \brief No Operation + + No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** \brief Wait For Interrupt + + Wait For Interrupt is a hint instruction that suspends execution + until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** \brief Wait For Event + + Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** \brief Send Event + + Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** \brief Instruction Synchronization Barrier + + Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or + memory, after the instruction has been completed. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb"); +} + + +/** \brief Data Synchronization Barrier + + This function acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb"); +} + + +/** \brief Data Memory Barrier + + This function ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb"); +} + + +/** \brief Reverse byte order (32 bit) + + This function reverses the byte order in integer value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Reverse byte order (16 bit) + + This function reverses the byte order in two unsigned short values. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** \brief Reverse byte order in signed short value + + This function reverses the byte order in a signed short value with sign extension to integer. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + uint32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** \brief Rotate Right in unsigned value (32 bit) + + This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32 - op2)); +} + + +/** \brief Breakpoint + + This function causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +#if (__CORTEX_M >= 0x03) + +/** \brief Reverse bit order of value + + This function reverses the bit order of the given value. + + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + + +/** \brief LDR Exclusive (8 bit) + + This function performs a exclusive LDR command for 8 bit value. + + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (16 bit) + + This function performs a exclusive LDR command for 16 bit values. + + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return(result); +} + + +/** \brief LDR Exclusive (32 bit) + + This function performs a exclusive LDR command for 32 bit values. + + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** \brief STR Exclusive (8 bit) + + This function performs a exclusive STR command for 8 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (16 bit) + + This function performs a exclusive STR command for 16 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief STR Exclusive (32 bit) + + This function performs a exclusive STR command for 32 bit values. + + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** \brief Remove the exclusive lock + + This function removes the exclusive lock which is created by LDREX. + + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** \brief Signed Saturate + + This function saturates a signed value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Unsigned Saturate + + This function saturates an unsigned value. + + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** \brief Count leading zeros + + This function counts the number of leading zeros of a data value. + + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x03) */ + + + + +#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ +/* TASKING carm specific functions */ + +/* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/source/lpc_chip_11u6x/inc/crc_11u6x.h b/source/lpc_chip_11u6x/inc/crc_11u6x.h new file mode 100644 index 0000000..45ed474 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/crc_11u6x.h @@ -0,0 +1,262 @@ +/* + * @brief LPC11u6x Cyclic Redundancy Check (CRC) Engine driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __CRC_11U6X_H_ +#define __CRC_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CRC_11U6X CHIP: LPC11u6x Cyclic Redundancy Check Engine driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief CRC register block structure + */ +typedef struct { /*!< CRC Structure */ + __IO uint32_t MODE; /*!< CRC Mode Register */ + __IO uint32_t SEED; /*!< CRC SEED Register */ + union { + __I uint32_t SUM; /*!< CRC Checksum Register. */ + __O uint32_t WRDATA32; /*!< CRC Data Register: write size 32-bit*/ + __O uint16_t WRDATA16; /*!< CRC Data Register: write size 16-bit*/ + __O uint8_t WRDATA8; /*!< CRC Data Register: write size 8-bit*/ + }; + +} LPC_CRC_T; + +/* + * @brief CRC MODE register description + */ +#define CRC_MODE_POLY_BITMASK ((0x03)) /** CRC polynomial Bit mask */ +#define CRC_MODE_POLY_CCITT (0x00) /** Select CRC-CCITT polynomial */ +#define CRC_MODE_POLY_CRC16 (0x01) /** Select CRC-16 polynomial */ +#define CRC_MODE_POLY_CRC32 (0x02) /** Select CRC-32 polynomial */ +#define CRC_MODE_WRDATA_BITMASK (0x03 << 2) /** CRC WR_Data Config Bit mask */ +#define CRC_MODE_WRDATA_BIT_RVS (1 << 2) /** Select Bit order reverse for WR_DATA (per byte) */ +#define CRC_MODE_WRDATA_CMPL (1 << 3) /** Select One's complement for WR_DATA */ +#define CRC_MODE_SUM_BITMASK (0x03 << 4) /** CRC Sum Config Bit mask */ +#define CRC_MODE_SUM_BIT_RVS (1 << 4) /** Select Bit order reverse for CRC_SUM */ +#define CRC_MODE_SUM_CMPL (1 << 5) /** Select One's complement for CRC_SUM */ + +#define MODE_CFG_CCITT (0x00) /** Pre-defined mode word for default CCITT setup */ +#define MODE_CFG_CRC16 (0x15) /** Pre-defined mode word for default CRC16 setup */ +#define MODE_CFG_CRC32 (0x36) /** Pre-defined mode word for default CRC32 setup */ + +#define CRC_SEED_CCITT (0x0000FFFF)/** Initial seed value for CCITT mode */ +#define CRC_SEED_CRC16 (0x00000000)/** Initial seed value for CRC16 mode */ +#define CRC_SEED_CRC32 (0xFFFFFFFF)/** Initial seed value for CRC32 mode */ + +/** + * @brief CRC polynomial + */ +typedef enum IP_CRC_001_POLY { + CRC_POLY_CCITT = CRC_MODE_POLY_CCITT, /**< CRC-CCIT polynomial */ + CRC_POLY_CRC16 = CRC_MODE_POLY_CRC16, /**< CRC-16 polynomial */ + CRC_POLY_CRC32 = CRC_MODE_POLY_CRC32, /**< CRC-32 polynomial */ + CRC_POLY_LAST, +} CRC_POLY_T; + +/** + * @brief Initializes the CRC Engine + * @return Nothing + */ +void Chip_CRC_Init(void); + +/** + * @brief Deinitializes the CRC Engine + * @return Nothing + */ +void Chip_CRC_Deinit(void); + +/** + * @brief Set the polynomial used for the CRC calculation + * @param poly : The enumerated polynomial to be used + * @param flags : An Or'ed value of flags that setup the mode + * @return Nothing + * @note Flags for setting up the mode word include CRC_MODE_WRDATA_BIT_RVS, + * CRC_MODE_WRDATA_CMPL, CRC_MODE_SUM_BIT_RVS, and CRC_MODE_SUM_CMPL. + */ +STATIC INLINE void Chip_CRC_SetPoly(CRC_POLY_T poly, uint32_t flags) +{ + LPC_CRC->MODE = (uint32_t) poly | flags; +} + +/** + * @brief Sets up the CRC engine for CRC16 mode + * @return Nothing + */ +STATIC INLINE void Chip_CRC_UseCRC16(void) +{ + LPC_CRC->MODE = MODE_CFG_CRC16; + LPC_CRC->SEED = CRC_SEED_CRC16; +} + +/** + * @brief Sets up the CRC engine for CRC32 mode + * @return Nothing + */ +STATIC INLINE void Chip_CRC_UseCRC32(void) +{ + LPC_CRC->MODE = MODE_CFG_CRC32; + LPC_CRC->SEED = CRC_SEED_CRC32; +} + +/** + * @brief Sets up the CRC engine for CCITT mode + * @return Nothing + */ +STATIC INLINE void Chip_CRC_UseCCITT(void) +{ + LPC_CRC->MODE = MODE_CFG_CCITT; + LPC_CRC->SEED = CRC_SEED_CCITT; +} + +/** + * @brief Engage the CRC engine with defaults based on the polynomial to be used + * @param poly : The enumerated polynomial to be used + * @return Nothing + */ +void Chip_CRC_UseDefaultConfig(CRC_POLY_T poly); + +/** + * @brief Set the CRC Mode bits + * @param mode : Mode value + * @return Nothing + */ +STATIC INLINE void Chip_CRC_SetMode(uint32_t mode) +{ + LPC_CRC->MODE = mode; +} + +/** + * @brief Get the CRC Mode bits + * @return The current value of the CRC Mode bits + */ +STATIC INLINE uint32_t Chip_CRC_GetMode(void) +{ + return LPC_CRC->MODE; +} + +/** + * @brief Set the seed bits used by the CRC_SUM register + * @param seed : Seed value + * @return Nothing + */ +STATIC INLINE void Chip_CRC_SetSeed(uint32_t seed) +{ + LPC_CRC->SEED = seed; +} + +/** + * @brief Get the CRC seed value + * @return Seed value + */ +STATIC INLINE uint32_t Chip_CRC_GetSeed(void) +{ + return LPC_CRC->SEED; +} + +/** + * @brief Convenience function for writing 8-bit data to the CRC engine + * @param data : 8-bit data to write + * @return Nothing + */ +STATIC INLINE void Chip_CRC_Write8(uint8_t data) +{ + LPC_CRC->WRDATA8 = data; +} + +/** + * @brief Convenience function for writing 16-bit data to the CRC engine + * @param data : 16-bit data to write + * @return Nothing + */ +STATIC INLINE void Chip_CRC_Write16(uint16_t data) +{ + LPC_CRC->WRDATA16 = data; +} + +/** + * @brief Convenience function for writing 32-bit data to the CRC engine + * @param data : 32-bit data to write + * @return Nothing + */ +STATIC INLINE void Chip_CRC_Write32(uint32_t data) +{ + LPC_CRC->WRDATA32 = data; +} + +/** + * @brief Gets the CRC Sum based on the Mode and Seed as previously configured + * @return CRC Checksum value + */ +STATIC INLINE uint32_t Chip_CRC_Sum(void) +{ + return LPC_CRC->SUM; +} + +/** + * @brief Convenience function for computing a standard CCITT checksum from an 8-bit data block + * @param data : Pointer to the block of 8-bit data + * @param bytes : The number of bytes pointed to by data + * @return Check sum value + */ +uint32_t Chip_CRC_CRC8(const uint8_t *data, uint32_t bytes); + +/** + * @brief Convenience function for computing a standard CRC16 checksum from 16-bit data block + * @param data : Pointer to the block of 16-bit data + * @param hwords : The number of 16 byte entries pointed to by data + * @return Check sum value + */ +uint32_t Chip_CRC_CRC16(const uint16_t *data, uint32_t hwords); + +/** + * @brief Convenience function for computing a standard CRC32 checksum from 32-bit data block + * @param data : Pointer to the block of 32-bit data + * @param words : The number of 32-bit entries pointed to by data + * @return Check sum value + */ +uint32_t Chip_CRC_CRC32(const uint32_t *data, uint32_t words); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CRC_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/dma_11u6x.h b/source/lpc_chip_11u6x/inc/dma_11u6x.h new file mode 100644 index 0000000..a25caff --- /dev/null +++ b/source/lpc_chip_11u6x/inc/dma_11u6x.h @@ -0,0 +1,734 @@ +/* + * @brief LPC11u6x DMA chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __DMA_11U6X_H_ +#define __DMA_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup DMA_11U6X CHIP: LPC11u6x DMA Controller driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief DMA Controller shared registers structure + */ +typedef struct { /*!< DMA shared registers structure */ + __IO uint32_t ENABLESET; /*!< DMA Channel Enable read and Set for all DMA channels */ + __I uint32_t RESERVED0; + __O uint32_t ENABLECLR; /*!< DMA Channel Enable Clear for all DMA channels */ + __I uint32_t RESERVED1; + __I uint32_t ACTIVE; /*!< DMA Channel Active status for all DMA channels */ + __I uint32_t RESERVED2; + __I uint32_t BUSY; /*!< DMA Channel Busy status for all DMA channels */ + __I uint32_t RESERVED3; + __IO uint32_t ERRINT; /*!< DMA Error Interrupt status for all DMA channels */ + __I uint32_t RESERVED4; + __IO uint32_t INTENSET; /*!< DMA Interrupt Enable read and Set for all DMA channels */ + __I uint32_t RESERVED5; + __O uint32_t INTENCLR; /*!< DMA Interrupt Enable Clear for all DMA channels */ + __I uint32_t RESERVED6; + __IO uint32_t INTA; /*!< DMA Interrupt A status for all DMA channels */ + __I uint32_t RESERVED7; + __IO uint32_t INTB; /*!< DMA Interrupt B status for all DMA channels */ + __I uint32_t RESERVED8; + __O uint32_t SETVALID; /*!< DMA Set ValidPending control bits for all DMA channels */ + __I uint32_t RESERVED9; + __O uint32_t SETTRIG; /*!< DMA Set Trigger control bits for all DMA channels */ + __I uint32_t RESERVED10; + __O uint32_t ABORT; /*!< DMA Channel Abort control for all DMA channels */ +} LPC_DMA_COMMON_T; + +/** + * @brief DMA Controller shared registers structure + */ +typedef struct { /*!< DMA channel register structure */ + __IO uint32_t CFG; /*!< DMA Configuration register */ + __I uint32_t CTLSTAT; /*!< DMA Control and status register */ + __IO uint32_t XFERCFG; /*!< DMA Transfer configuration register */ + __I uint32_t RESERVED; +} LPC_DMA_CHANNEL_T; + +/* DMA channel mapping - each channel is mapped to an individual peripheral + and direction or a DMA imput mux trigger */ +typedef enum { + SSP0_RX_DMA = 0, /*!< SSP0 receive DMA channel */ + DMA_CH0 = SSP0_RX_DMA, + DMAREQ_SSP0_TX, /*!< SSP0 transmit DMA channel */ + DMA_CH1 = DMAREQ_SSP0_TX, + DMAREQ_SSP1_RX, /*!< SSP1 receive DMA channel */ + DMA_CH2 = DMAREQ_SSP1_RX, + DMAREQ_SSP1_TX, /*!< SSP1 transmit DMA channel */ + DMA_CH3 = DMAREQ_SSP1_TX, + DMAREQ_USART0_RX, /*!< USART0 receive DMA channel */ + DMA_CH4 = DMAREQ_USART0_RX, + DMAREQ_USART0_TX, /*!< USART0 transmit DMA channel */ + DMA_CH5 = DMAREQ_USART0_TX, + DMAREQ_USART1_RX, /*!< USART1 transmit DMA channel */ + DMA_CH6 = DMAREQ_USART1_RX, + DMAREQ_USART1_TX, /*!< USART1 transmit DMA channel */ + DMA_CH7 = DMAREQ_USART1_TX, + DMAREQ_USART2_RX, /*!< USART2 transmit DMA channel */ + DMA_CH8 = DMAREQ_USART2_RX, + DMAREQ_USART2_TX, /*!< USART2 transmit DMA channel */ + DMA_CH9 = DMAREQ_USART2_TX, + DMAREQ_USART3_RX, /*!< USART3 transmit DMA channel */ + DMA_CH10 = DMAREQ_USART3_RX, + DMAREQ_USART3_TX, /*!< USART3 transmit DMA channel */ + DMA_CH11 = DMAREQ_USART3_TX, + DMAREQ_USART4_RX, /*!< USART4 transmit DMA channel */ + DMA_CH12 = DMAREQ_USART4_RX, + DMAREQ_USART4_TX, /*!< USART4 transmit DMA channel */ + DMA_CH13 = DMAREQ_USART4_TX, + DMAREQ_RESERVED_14, + DMA_CH14 = DMAREQ_RESERVED_14, + DMAREQ_RESERVED_15, + DMA_CH15 = DMAREQ_RESERVED_15 +} DMA_CHID_T; + +/* On LPC412x, Max DMA channel is 22 */ +#define MAX_DMA_CHANNEL (DMA_CH15 + 1) + +/** + * @brief DMA Controller register block structure + */ +typedef struct { /*!< DMA Structure */ + __IO uint32_t CTRL; /*!< DMA control register */ + __I uint32_t INTSTAT; /*!< DMA Interrupt status register */ + __IO uint32_t SRAMBASE; /*!< DMA SRAM address of the channel configuration table */ + __I uint32_t RESERVED2[5]; + LPC_DMA_COMMON_T DMACOMMON[1]; /*!< DMA shared channel (common) registers */ + __I uint32_t RESERVED0[225]; + LPC_DMA_CHANNEL_T DMACH[MAX_DMA_CHANNEL]; /*!< DMA channel registers */ +} LPC_DMA_T; + +/** @defgroup DMA_COMMONDRV_11U6X CHIP: LPC11u6x DMA Controller driver common functions + * @{ + */ + +/** + * @brief Initialize DMA controller + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + */ +STATIC INLINE void Chip_DMA_Init(LPC_DMA_T *pDMA) +{ + (void) pDMA; + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_DMA); +} + +/** + * @brief De-Initialize DMA controller + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + */ +STATIC INLINE void Chip_DMA_DeInit(LPC_DMA_T *pDMA) +{ + (void) pDMA; + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_DMA); +} + +/** + * @brief Enable DMA controller + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + */ +STATIC INLINE void Chip_DMA_Enable(LPC_DMA_T *pDMA) +{ + pDMA->CTRL = 1; +} + +/** + * @brief Disable DMA controller + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + */ +STATIC INLINE void Chip_DMA_Disable(LPC_DMA_T *pDMA) +{ + pDMA->CTRL = 0; +} + +/* DMA interrupt status bits (common) */ +#define DMA_INTSTAT_ACTIVEINT 0x2 /*!< Summarizes whether any enabled interrupts are pending */ +#define DMA_INTSTAT_ACTIVEERRINT 0x4 /*!< Summarizes whether any error interrupts are pending */ + +/** + * @brief Get pending interrupt or error interrupts + * @param pDMA : The base of DMA controller on the chip + * @return An Or'ed value of DMA_INTSTAT_* types + * @note If any DMA channels have an active interrupt or error interrupt + * pending, this functional will a common status that applies to all + * channels. + */ +STATIC INLINE uint32_t Chip_DMA_GetIntStatus(LPC_DMA_T *pDMA) +{ + return pDMA->INTSTAT; +} + +/* DMA channel source/address/next descriptor */ +typedef struct { + uint32_t xfercfg; /*!< Transfer configuration (only used in linked lists and ping-pong configs) */ + uint32_t source; /*!< DMA transfer source end address */ + uint32_t dest; /*!< DMA transfer desintation end address */ + uint32_t next; /*!< Link to next DMA descriptor, must be 16 byte aligned */ +} DMA_CHDESC_T; + +/* DMA SRAM table - this can be optionally used with the Chip_DMA_SetSRAMBase() + function if a DMA SRAM table is needed. */ +extern DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL]; + +/** + * @brief Set DMA controller SRAM base address + * @param pDMA : The base of DMA controller on the chip + * @param base : The base address where the DMA descriptors will be stored + * @return Nothing + * @note A 256 byte block of memory aligned on a 256 byte boundary must be + * provided for this function. It sets the base address used for + * DMA descriptor table (16 descriptors total that use 16 bytes each).
+ * + * A pre-defined table with correct alignment can be used for this + * function by calling Chip_DMA_SetSRAMBase(LPC_DMA, DMA_ADDR(Chip_DMA_Table)); + */ +STATIC INLINE void Chip_DMA_SetSRAMBase(LPC_DMA_T *pDMA, uint32_t base) +{ + pDMA->SRAMBASE = base; +} + +/** + * @brief Returns DMA controller SRAM base address + * @param pDMA : The base of DMA controller on the chip + * @return The base address where the DMA descriptors are stored + */ +STATIC INLINE uint32_t Chip_DMA_GetSRAMBase(LPC_DMA_T *pDMA) +{ + return pDMA->SRAMBASE; +} + +/** + * @} + */ + +/** @defgroup DMA_COMMON_11U6X CHIP: LPC11u6x DMA Controller driver common channel functions + * @{ + */ + +/** + * @brief Enables a single DMA channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_EnableChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].ENABLESET = (1 << ch); +} + +/** + * @brief Disables a single DMA channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_DisableChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].ENABLECLR = (1 << ch); +} + +/** + * @brief Returns all enabled DMA channels + * @param pDMA : The base of DMA controller on the chip + * @return An Or'ed value of all enabled DMA channels (0 - 15) + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) is enabled. A low state is disabled. + */ +STATIC INLINE uint32_t Chip_DMA_GetEnabledChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].ENABLESET; +} + +/** + * @brief Returns all active DMA channels + * @param pDMA : The base of DMA controller on the chip + * @return An Or'ed value of all active DMA channels (0 - 15) + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) is active. A low state is inactive. A active + * channel indicates that a DMA operation has been started but + * not yet fully completed. + */ +STATIC INLINE uint32_t Chip_DMA_GetActiveChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].ACTIVE; +} + +/** + * @brief Returns all busy DMA channels + * @param pDMA : The base of DMA controller on the chip + * @return An Or'ed value of all busy DMA channels (0 - 15) + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) is busy. A low state is not busy. A DMA + * channel is considered busy when there is any operation + * related to that channel in the DMA controller�s internal + * pipeline. + */ +STATIC INLINE uint32_t Chip_DMA_GetBusyChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].BUSY; +} + +/** + * @brief Returns pending error interrupt status for all DMA channels + * @param pDMA : The base of DMA controller on the chip + * @return An Or'ed value of all channels (0 - 15) error interrupt status + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) has a pending error interrupt. A low state + * indicates no error interrupt. + */ +STATIC INLINE uint32_t Chip_DMA_GetErrorIntChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].ERRINT; +} + +/** + * @brief Clears a pending error interrupt status for a single DMA channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_ClearErrorIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].ERRINT = (1 << ch); +} + +/** + * @brief Enables a single DMA channel's interrupt used in common DMA interrupt + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_EnableIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].INTENSET = (1 << ch); +} + +/** + * @brief Disables a single DMA channel's interrupt used in common DMA interrupt + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_DisableIntChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].INTENCLR = (1 << ch); +} + +/** + * @brief Returns all enabled interrupt channels + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) has an enabled interrupt for the channel. + * A low state indicates that the DMA channel will not contribute + * to the common DMA interrupt status. + */ +STATIC INLINE uint32_t Chip_DMA_GetEnableIntChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].INTENSET; +} + +/** + * @brief Returns active A interrupt status for all channels + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) has an active A interrupt for the channel. + * A low state indicates that the A interrupt is not active. + */ +STATIC INLINE uint32_t Chip_DMA_GetActiveIntAChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].INTA; +} + +/** + * @brief Clears active A interrupt status for a single channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_ClearActiveIntAChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].INTA = (1 << ch); +} + +/** + * @brief Returns active B interrupt status for all channels + * @param pDMA : The base of DMA controller on the chip + * @return Nothing + * @note A high values in bits 0 .. 15 in the return values indicates + * that the channel for that bit (bit 0 = channel 0, bit 1 - + * channel 1, etc.) has an active B interrupt for the channel. + * A low state indicates that the B interrupt is not active. + */ +STATIC INLINE uint32_t Chip_DMA_GetActiveIntBChannels(LPC_DMA_T *pDMA) +{ + return pDMA->DMACOMMON[0].INTB; +} + +/** + * @brief Clears active B interrupt status for a single channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_ClearActiveIntBChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].INTB = (1 << ch); +} + +/** + * @brief Sets the VALIDPENDING control bit for a single channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + * @note See the User Manual for more information for what this bit does. + * + */ +STATIC INLINE void Chip_DMA_SetValidChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].SETVALID = (1 << ch); +} + +/** + * @brief Sets the TRIG bit for a single channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + * @note See the User Manual for more information for what this bit does. + */ +STATIC INLINE void Chip_DMA_SetTrigChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].SETTRIG = (1 << ch); +} + +/** + * @brief Aborts a DMA operation for a single channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + * @note To abort a channel, the channel should first be disabled. Then wait + * until the channel is no longer busy by checking the corresponding + * bit in BUSY. Finally, abort the channel operation. This prevents the + * channel from restarting an incomplete operation when it is enabled + * again. + */ +STATIC INLINE void Chip_DMA_AbortChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + pDMA->DMACOMMON[0].ABORT = (1 << ch); +} + +/** + * @} + */ + +/** @defgroup DMATRIGMUX_11U6X CHIP: LPC11u6x DMA trigger selection driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief DMA trigger pin muxing structure + */ +typedef struct { /*!< DMA trigger pin muxing register structure */ + __IO uint32_t DMA_ITRIG_INMUX[MAX_DMA_CHANNEL]; /*!< Trigger input select register for DMA channels */ +} LPC_DMATRIGMUX_T; + +/* DMA triggers that can mapped to DMA channels */ +typedef enum { + DMATRIG_ADC0_SEQA_IRQ = 0, /*!< ADC0 sequencer A interrupt as trigger */ + DMATRIG_ADC0_SEQB_IRQ, /*!< ADC0 sequencer B interrupt as trigger */ + DMATRIG_CT16B0_MAT0, /*!< 16-bit counter/timer 0 interrupt as trigger */ + DMATRIG_CT16B1_MAT0, /*!< 16-bit counter/timer 1 interrupt as trigger */ + DMATRIG_CT32B0_MAT0, /*!< 32-bit counter/timer 0 interrupt as trigger */ + DMATRIG_CT32B1_MAT0, /*!< 32-bit counter/timer 1 interrupt as trigger */ + DMATRIG_PINT0, /*!< Pin interrupt 0 as trigger */ + DMATRIG_PINT1, /*!< Pin interrupt 1 as trigger */ + DMATRIG_SCT0_DMA0, /*!< SCT 0, DMA 0 as trigger */ + DMATRIG_SCT0_DMA1, /*!< SCT 1, DMA 1 as trigger */ + DMATRIG_SCT1_DMA0, /*!< SCT 0, DMA 0 as trigger */ + DMATRIG_SCT1_DMA1 /*!< SCT 1, DMA 1 as trigger */ +} DMA_TRIGSRC_T; + +/** + * @brief Select a trigger source for a DMA channel + * @param pDMATRIG : The base of DMA trigger setup block on the chip + * @param ch : DMA channel ID + * @param trig : Trigger source for the DMA channel + * @return Nothing + * @note A DMA trigger source only needs to be setup when the DMA is setup + * for hardware trigger mode (when Chip_DMA_SetupChannelConfig() is + * called with DMA_CFG_HWTRIGEN as OR'ed option). + */ +STATIC INLINE void Chip_DMA_SetHWTrigger(LPC_DMATRIGMUX_T *pDMATRIG, DMA_CHID_T ch, DMA_TRIGSRC_T trig) +{ + pDMATRIG->DMA_ITRIG_INMUX[ch] = (uint32_t) trig; +} + +/** + * @} + */ + +/** @defgroup DMA_CHANNEL_11U6X CHIP: LPC11u6x DMA Controller driver channel specific functions + * @{ + */ + +/* Support macro for DMA_CHDESC_T */ +#define DMA_ADDR(addr) ((uint32_t) (addr)) + +/* Support definitions for setting the configuration of a DMA channel. You + will need to get more information on these options from the User manual. */ +#define DMA_CFG_PERIPHREQEN (1 << 0) /*!< Enables Peripheral DMA requests */ +#define DMA_CFG_HWTRIGEN (1 << 1) /*!< Use hardware triggering via imput mux */ +#define DMA_CFG_TRIGPOL_LOW (0 << 4) /*!< Hardware trigger is active low or falling edge */ +#define DMA_CFG_TRIGPOL_HIGH (1 << 4) /*!< Hardware trigger is active high or rising edge */ +#define DMA_CFG_TRIGTYPE_EDGE (0 << 5) /*!< Hardware trigger is edge triggered */ +#define DMA_CFG_TRIGTYPE_LEVEL (1 << 5) /*!< Hardware trigger is level triggered */ +#define DMA_CFG_TRIGBURST_SNGL (0 << 6) /*!< Single transfer. Hardware trigger causes a single transfer */ +#define DMA_CFG_TRIGBURST_BURST (1 << 6) /*!< Burst transfer (see UM) */ +#define DMA_CFG_BURSTPOWER_1 (0 << 8) /*!< Set DMA burst size to 1 transfer */ +#define DMA_CFG_BURSTPOWER_2 (1 << 8) /*!< Set DMA burst size to 2 transfers */ +#define DMA_CFG_BURSTPOWER_4 (2 << 8) /*!< Set DMA burst size to 4 transfers */ +#define DMA_CFG_BURSTPOWER_8 (3 << 8) /*!< Set DMA burst size to 8 transfers */ +#define DMA_CFG_BURSTPOWER_16 (4 << 8) /*!< Set DMA burst size to 16 transfers */ +#define DMA_CFG_BURSTPOWER_32 (5 << 8) /*!< Set DMA burst size to 32 transfers */ +#define DMA_CFG_BURSTPOWER_64 (6 << 8) /*!< Set DMA burst size to 64 transfers */ +#define DMA_CFG_BURSTPOWER_128 (7 << 8) /*!< Set DMA burst size to 128 transfers */ +#define DMA_CFG_BURSTPOWER_256 (8 << 8) /*!< Set DMA burst size to 256 transfers */ +#define DMA_CFG_BURSTPOWER_512 (9 << 8) /*!< Set DMA burst size to 512 transfers */ +#define DMA_CFG_BURSTPOWER_1024 (10 << 8) /*!< Set DMA burst size to 1024 transfers */ +#define DMA_CFG_BURSTPOWER(n) ((n) << 8) /*!< Set DMA burst size to 2^n transfers, max n=10 */ +#define DMA_CFG_SRCBURSTWRAP (1 << 14) /*!< Source burst wrapping is enabled for this DMA channel */ +#define DMA_CFG_DSTBURSTWRAP (1 << 15) /*!< Destination burst wrapping is enabled for this DMA channel */ +#define DMA_CFG_CHPRIORITY(p) ((p) << 16) /*!< Sets DMA channel priority, min 0 (highest), max 3 (lowest) */ + +/** + * @brief Setup a DMA channel configuration + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @param cfg : An Or'ed value of DMA_CFG_* values that define the channel's configuration + * @return Nothing + * @note This function sets up all configurable options for the DMA channel. + * These options are usually set once for a channel and then unchanged.
+ * + * The following example show how to configure the channel for peripheral + * DMA requests, burst transfer size of 1 (in 'transfers', not bytes), + * continuous reading of the same source address, incrementing destination + * address, and highest channel priority.
+ * Example: Chip_DMA_SetupChannelConfig(pDMA, SSP0_RX_DMA, + * (DMA_CFG_PERIPHREQEN | DMA_CFG_TRIGBURST_BURST | DMA_CFG_BURSTPOWER_1 | + * DMA_CFG_SRCBURSTWRAP | DMA_CFG_CHPRIORITY(0)));
+ * + * The following example show how to configure the channel for an external + * trigger from the imput mux with low edge polarity, a burst transfer size of 8, + * incrementing source and destination addresses, and lowest channel + * priority.
+ * Example: Chip_DMA_SetupChannelConfig(pDMA, DMA_CH14, + * (DMA_CFG_HWTRIGEN | DMA_CFG_TRIGPOL_LOW | DMA_CFG_TRIGTYPE_EDGE | + * DMA_CFG_TRIGBURST_BURST | DMA_CFG_BURSTPOWER_8 | + * DMA_CFG_CHPRIORITY(3)));
+ * + * For non-peripheral DMA triggering (DMA_CFG_HWTRIGEN definition), use the + * DMA input mux functions to configure the DMA trigger source for a DMA channel. + */ +STATIC INLINE void Chip_DMA_SetupChannelConfig(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t cfg) +{ + pDMA->DMACH[ch].CFG = cfg; +} + +/* DMA channel control and status register definitions */ +#define DMA_CTLSTAT_VALIDPENDING (1 << 0) /*!< Valid pending flag for this channel */ +#define DMA_CTLSTAT_TRIG (1 << 2) /*!< Trigger flag. Indicates that the trigger for this channel is currently set */ + +/** + * @brief Returns channel specific status flags + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return AN Or'ed value of DMA_CTLSTAT_VALIDPENDING and DMA_CTLSTAT_TRIG + */ +STATIC INLINE uint32_t Chip_DMA_GetChannelStatus(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + return pDMA->DMACH[ch].XFERCFG; +} + +/* DMA channel transfer configuration registers definitions */ +#define DMA_XFERCFG_CFGVALID (1 << 0) /*!< Configuration Valid flag */ +#define DMA_XFERCFG_RELOAD (1 << 1) /*!< Indicates whether the channels control structure will be reloaded when the current descriptor is exhausted */ +#define DMA_XFERCFG_SWTRIG (1 << 2) /*!< Software Trigger */ +#define DMA_XFERCFG_CLRTRIG (1 << 3) /*!< Clear Trigger */ +#define DMA_XFERCFG_SETINTA (1 << 4) /*!< Set Interrupt flag A for this channel to fire when descriptor is complete */ +#define DMA_XFERCFG_SETINTB (1 << 5) /*!< Set Interrupt flag B for this channel to fire when descriptor is complete */ +#define DMA_XFERCFG_WIDTH_8 (0 << 8) /*!< 8-bit transfers are performed */ +#define DMA_XFERCFG_WIDTH_16 (1 << 8) /*!< 16-bit transfers are performed */ +#define DMA_XFERCFG_WIDTH_32 (2 << 8) /*!< 32-bit transfers are performed */ +#define DMA_XFERCFG_SRCINC_0 (0 << 12) /*!< DMA source address is not incremented after a transfer */ +#define DMA_XFERCFG_SRCINC_1 (1 << 12) /*!< DMA source address is incremented by 1 (width) after a transfer */ +#define DMA_XFERCFG_SRCINC_2 (2 << 12) /*!< DMA source address is incremented by 2 (width) after a transfer */ +#define DMA_XFERCFG_SRCINC_4 (3 << 12) /*!< DMA source address is incremented by 4 (width) after a transfer */ +#define DMA_XFERCFG_DSTINC_0 (0 << 14) /*!< DMA destination address is not incremented after a transfer */ +#define DMA_XFERCFG_DSTINC_1 (1 << 14) /*!< DMA destination address is incremented by 1 (width) after a transfer */ +#define DMA_XFERCFG_DSTINC_2 (2 << 14) /*!< DMA destination address is incremented by 2 (width) after a transfer */ +#define DMA_XFERCFG_DSTINC_4 (3 << 14) /*!< DMA destination address is incremented by 4 (width) after a transfer */ +#define DMA_XFERCFG_XFERCOUNT(n) ((n - 1) << 16) /*!< DMA transfer count in 'transfers', between (0)1 and (1023)1024 */ + +/** + * @brief Setup a DMA channel transfer configuration + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @param cfg : An Or'ed value of DMA_XFERCFG_* values that define the channel's transfer configuration + * @return Nothing + * @note This function sets up the transfer configuration for the DMA channel.
+ * + * The following example show how to configure the channel's transfer for + * multiple transfer descriptors (ie, ping-pong), interrupt 'A' trigger on + * transfer descriptor completion, 128 byte size transfers, and source and + * destination address increment.
+ * Example: Chip_DMA_SetupChannelTransfer(pDMA, SSP0_RX_DMA, + * (DMA_XFERCFG_CFGVALID | DMA_XFERCFG_RELOAD | DMA_XFERCFG_SETINTA | + * DMA_XFERCFG_WIDTH_8 | DMA_XFERCFG_SRCINC_1 | DMA_XFERCFG_DSTINC_1 | + * DMA_XFERCFG_XFERCOUNT(128)));
+ */ +STATIC INLINE void Chip_DMA_SetupChannelTransfer(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t cfg) +{ + pDMA->DMACH[ch].XFERCFG = cfg; +} + +/** + * @brief Set DMA transfer register interrupt bits (safe) + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @param mask : Bits to set + * @return Nothing + * @note This function safely sets bits in the DMA channel specific XFERCFG + * register. + */ +void Chip_DMA_SetTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask); + +/** + * @brief Clear DMA transfer register interrupt bits (safe) + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @param mask : Bits to clear + * @return Nothing + * @note This function safely clears bits in the DMA channel specific XFERCFG + * register. + */ +void Chip_DMA_ClearTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask); + +/** + * @brief Update the transfer size in an existing DMA channel transfer configuration + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @param trans : Number of transfers to update the transfer configuration to (1 - 1023) + * @return Nothing + */ +void Chip_DMA_SetupChannelTransferSize(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t trans); + +/** + * @brief Sets a DMA channel configuration as valid + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_SetChannelValid(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_CFGVALID); +} + +/** + * @brief Sets a DMA channel configuration as invalid + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_SetChannelInValid(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + Chip_DMA_ClearTranBits(pDMA, ch, DMA_XFERCFG_CFGVALID); +} + +/** + * @brief Performs a software trigger of the DMA channel + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @return Nothing + */ +STATIC INLINE void Chip_DMA_SWTriggerChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch) +{ + Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_SWTRIG); +} + +/** + * @brief Sets up a DMA channel with the passed DMA transfer descriptor + * @param pDMA : The base of DMA controller on the chip + * @param ch : DMA channel ID + * @param desc : Pointer to DMA transfer descriptor + * @return false if the DMA channel was active, otherwise true + * @note This function will set the DMA descriptor in the SRAM table to the + * the passed descriptor. This function is only meant to be used when + * the DMA channel is not active and can be used to setup the + * initial transfer for a linked list or ping-pong buffer or just a + * single transfer without a next descriptor.
+ * + * If using this function to write the initial transfer descriptor in + * a linked list or ping-pong buffer configuration, it should contain a + * non-NULL 'next' field pointer. + */ +bool Chip_DMA_SetupTranChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch, DMA_CHDESC_T *desc); + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DMA_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/error.h b/source/lpc_chip_11u6x/inc/error.h new file mode 100644 index 0000000..b1528ff --- /dev/null +++ b/source/lpc_chip_11u6x/inc/error.h @@ -0,0 +1,156 @@ +/* + * @brief Error code returned by Boot ROM drivers/library functions + * @ingroup Common + * + * This file contains unified error codes to be used across driver, + * middleware, applications, hal and demo software. + * + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_ERROR_H__ +#define __LPC_ERROR_H__ + +/** Error code returned by Boot ROM drivers/library functions + * + * Error codes are a 32-bit value with : + * - The 16 MSB contains the peripheral code number + * - The 16 LSB contains an error code number associated to that peripheral + * + */ +typedef enum { + /**\b 0x00000000*/ LPC_OK = 0, /**< enum value returned on Success */ + /**\b 0xFFFFFFFF*/ ERR_FAILED = -1, /**< enum value returned on general failure */ + /**\b 0xFFFFFFFE*/ ERR_TIME_OUT = -2, /**< enum value returned on general timeout */ + /**\b 0xFFFFFFFD*/ ERR_BUSY = -3, /**< enum value returned when resource is busy */ + + /* ISP related errors */ + ERR_ISP_BASE = 0x00000000, + /*0x00000001*/ ERR_ISP_INVALID_COMMAND = ERR_ISP_BASE + 1, + /*0x00000002*/ ERR_ISP_SRC_ADDR_ERROR, /* Source address not on word boundary */ + /*0x00000003*/ ERR_ISP_DST_ADDR_ERROR, /* Destination address not on word or 256 byte boundary */ + /*0x00000004*/ ERR_ISP_SRC_ADDR_NOT_MAPPED, + /*0x00000005*/ ERR_ISP_DST_ADDR_NOT_MAPPED, + /*0x00000006*/ ERR_ISP_COUNT_ERROR, /* Byte count is not multiple of 4 or is not a permitted value */ + /*0x00000007*/ ERR_ISP_INVALID_SECTOR, + /*0x00000008*/ ERR_ISP_SECTOR_NOT_BLANK, + /*0x00000009*/ ERR_ISP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION, + /*0x0000000A*/ ERR_ISP_COMPARE_ERROR, + /*0x0000000B*/ ERR_ISP_BUSY,/* Flash programming hardware interface is busy */ + /*0x0000000C*/ ERR_ISP_PARAM_ERROR, /* Insufficient number of parameters */ + /*0x0000000D*/ ERR_ISP_ADDR_ERROR, /* Address not on word boundary */ + /*0x0000000E*/ ERR_ISP_ADDR_NOT_MAPPED, + /*0x0000000F*/ ERR_ISP_CMD_LOCKED, /* Command is locked */ + /*0x00000010*/ ERR_ISP_INVALID_CODE,/* Unlock code is invalid */ + /*0x00000011*/ ERR_ISP_INVALID_BAUD_RATE, + /*0x00000012*/ ERR_ISP_INVALID_STOP_BIT, + /*0x00000013*/ ERR_ISP_CODE_READ_PROTECTION_ENABLED, + + /* ROM API related errors */ + ERR_API_BASE = 0x00010000, + /**\b 0x00010001*/ ERR_API_INVALID_PARAMS = ERR_API_BASE + 1, /**< Invalid parameters*/ + /**\b 0x00010002*/ ERR_API_INVALID_PARAM1, /**< PARAM1 is invalid */ + /**\b 0x00010003*/ ERR_API_INVALID_PARAM2, /**< PARAM2 is invalid */ + /**\b 0x00010004*/ ERR_API_INVALID_PARAM3, /**< PARAM3 is invalid */ + /**\b 0x00010005*/ ERR_API_MOD_INIT,/**< API is called before module init */ + + /* SPIFI API related errors */ + ERR_SPIFI_BASE = 0x00020000, + /*0x00020001*/ ERR_SPIFI_DEVICE_ERROR = ERR_SPIFI_BASE + 1, + /*0x00020002*/ ERR_SPIFI_INTERNAL_ERROR, + /*0x00020003*/ ERR_SPIFI_TIMEOUT, + /*0x00020004*/ ERR_SPIFI_OPERAND_ERROR, + /*0x00020005*/ ERR_SPIFI_STATUS_PROBLEM, + /*0x00020006*/ ERR_SPIFI_UNKNOWN_EXT, + /*0x00020007*/ ERR_SPIFI_UNKNOWN_ID, + /*0x00020008*/ ERR_SPIFI_UNKNOWN_TYPE, + /*0x00020009*/ ERR_SPIFI_UNKNOWN_MFG, + + /* Security API related errors */ + ERR_SEC_BASE = 0x00030000, + /*0x00030001*/ ERR_SEC_AES_WRONG_CMD = ERR_SEC_BASE + 1, + /*0x00030002*/ ERR_SEC_AES_NOT_SUPPORTED, + /*0x00030003*/ ERR_SEC_AES_KEY_ALREADY_PROGRAMMED, + + /* USB device stack related errors */ + ERR_USBD_BASE = 0x00040000, + /**\b 0x00040001*/ ERR_USBD_INVALID_REQ = ERR_USBD_BASE + 1,/**< invalid request */ + /**\b 0x00040002*/ ERR_USBD_UNHANDLED, /**< Callback did not process the event */ + /**\b 0x00040003*/ ERR_USBD_STALL, /**< Stall the endpoint on which the call back is called */ + /**\b 0x00040004*/ ERR_USBD_SEND_ZLP, /**< Send ZLP packet on the endpoint on which the call back is called */ + /**\b 0x00040005*/ ERR_USBD_SEND_DATA, /**< Send data packet on the endpoint on which the call back is called */ + /**\b 0x00040006*/ ERR_USBD_BAD_DESC, /**< Bad descriptor*/ + /**\b 0x00040007*/ ERR_USBD_BAD_CFG_DESC, /**< Bad config descriptor*/ + /**\b 0x00040008*/ ERR_USBD_BAD_INTF_DESC, /**< Bad interface descriptor*/ + /**\b 0x00040009*/ ERR_USBD_BAD_EP_DESC,/**< Bad endpoint descriptor*/ + /**\b 0x0004000a*/ ERR_USBD_BAD_MEM_BUF,/**< Bad alignment of buffer passed. */ + /**\b 0x0004000b*/ ERR_USBD_TOO_MANY_CLASS_HDLR,/**< Too many class handlers. */ + + /* CGU related errors */ + ERR_CGU_BASE = 0x00050000, + /*0x00050001*/ ERR_CGU_NOT_IMPL = ERR_CGU_BASE + 1, + /*0x00050002*/ ERR_CGU_INVALID_PARAM, + /*0x00050003*/ ERR_CGU_INVALID_SLICE, + /*0x00050004*/ ERR_CGU_OUTPUT_GEN, + /*0x00050005*/ ERR_CGU_DIV_SRC, + /*0x00050006*/ ERR_CGU_DIV_VAL, + /*0x00050007*/ ERR_CGU_SRC, + + /* I2C related errors */ + ERR_I2C_BASE = 0x00060000, + /*0x00060001*/ ERR_I2C_NAK = ERR_I2C_BASE + 1, + /*0x00060002*/ ERR_I2C_BUFFER_OVERFLOW, + /*0x00060003*/ ERR_I2C_BYTE_COUNT_ERR, + /*0x00060004*/ ERR_I2C_LOSS_OF_ARBRITRATION, + /*0x00060005*/ ERR_I2C_SLAVE_NOT_ADDRESSED, + /*0x00060006*/ ERR_I2C_LOSS_OF_ARBRITRATION_NAK_BIT, + /*0x00060007*/ ERR_I2C_GENERAL_FAILURE, + /*0x00060008*/ ERR_I2C_REGS_SET_TO_DEFAULT, + /*0x00060009*/ ERR_I2C_TIMEOUT, + /*0x0006000A*/ ERR_I2C_BUFFER_UNDERFLOW, + + ERR_DMA_BASE = 0x000D0000, + /*0x000D0001*/ ERR_DMA_ERROR_INT = ERR_DMA_BASE + 1, + /*0x000D0002*/ ERR_DMA_CHANNEL_NUMBER, + /*0x000D0003*/ ERR_DMA_CHANNEL_DISABLED, + /*0x000D0004*/ ERR_DMA_BUSY, + /*0x000D0005*/ ERR_DMA_NOT_ALIGNMENT, + /*0x000D0006*/ ERR_DMA_PING_PONG_EN, + /*0x000D0007*/ ERR_DMA_CHANNEL_VALID_PENDING +} ErrorCode_t; + +#ifndef offsetof +#define offsetof(s, m) (int) &(((s *) 0)->m) +#endif + +#define COMPILE_TIME_ASSERT(pred) switch (0) { \ + case 0: \ + case pred:; } + +#endif /* __LPC_ERROR_H__ */ diff --git a/source/lpc_chip_11u6x/inc/fmc_11u6x.h b/source/lpc_chip_11u6x/inc/fmc_11u6x.h new file mode 100644 index 0000000..1056fc3 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/fmc_11u6x.h @@ -0,0 +1,140 @@ +/* + * @brief FLASH Memory Controller (FMC) registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __FMC_11U6X_H_ +#define __FMC_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup FMC_11U6X CHIP: LPC11u6x FLASH Memory Controller driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief FLASH Memory Controller Unit register block structure + */ +typedef struct { /*!< FMC Structure */ + __I uint32_t RESERVED1[4]; + __IO uint32_t FLASHTIM; + __I uint32_t RESERVED2[3]; + __IO uint32_t FMSSTART; + __IO uint32_t FMSSTOP; + __I uint32_t RESERVED3; + __I uint32_t FMSW[1]; +} LPC_FMC_T; + +/** + * @brief FLASH Access time definitions + */ +typedef enum { + FLASHTIM_1CLK_CPU = 0, /*!< Flash accesses use 1 CPU clocks */ + FLASHTIM_2CLK_CPU = 1, /*!< Flash accesses use 2 CPU clocks */ + FLASHTIM_3CLK_CPU = 2, /*!< Flash accesses use 3 CPU clocks */ +} FMC_FLASHTIM_T; + +/** + * @brief Set FLASH access time in clocks + * @param clks : Clock cycles for FLASH access (minus 1) + * @return Nothing + */ +STATIC INLINE void Chip_FMC_SetFLASHAccess(FMC_FLASHTIM_T clks) +{ + uint32_t tmp = LPC_FMC->FLASHTIM & (~(0x3)); + + /* Don't alter upper bits */ + LPC_FMC->FLASHTIM = tmp | clks; +} + +/* Flash signature start and busy status bit */ +#define FMC_FLASHSIG_BUSY (1UL << 17) + +/** + * @brief Start computation of a signature for a FLASH memory range + * @param start : Starting FLASH address for computation, must be aligned on 16 byte boundary + * @param stop : Ending FLASH address for computation, must be aligned on 16 byte boundary + * @return Nothing + * @note Only bits 20..4 are used for the FLASH signature computation. + * Use the Chip_FMC_IsSignatureBusy() function to determine when the + * signature computation operation is complete and use the + * Chip_FMC_GetSignature() function to get the computed signature. + */ +STATIC INLINE void Chip_FMC_ComputeSignature(uint32_t start, uint32_t stop) +{ + LPC_FMC->FMSSTART = (start >> 4); + LPC_FMC->FMSSTOP = (stop >> 4) | FMC_FLASHSIG_BUSY; +} + +/** + * @brief Start computation of a signature for a FLASH memory address and block count + * @param start : Starting FLASH address for computation, must be aligned on 16 byte boundary + * @param blocks : Number of 16 byte blocks used for computation + * @return Nothing + * @note Only bits 20..4 are used for the FLASH signature computation. + * Use the Chip_FMC_IsSignatureBusy() function to determine when the + * signature computation operation is complete and the + * Chip_FMC_GetSignature() function to get the computed signature. + */ +STATIC INLINE void Chip_FMC_ComputeSignatureBlocks(uint32_t start, uint32_t blocks) +{ + Chip_FMC_ComputeSignature(start, (start + (blocks * 16))); +} + +/** + * @brief Check for signature geenration completion + * @return true if the signature computation is running, false if finished + */ +STATIC INLINE bool Chip_FMC_IsSignatureBusy(void) +{ + return (bool) ((LPC_FMC->FMSSTOP & FMC_FLASHSIG_BUSY) != 0); +} + +/** + * @brief Returns the generated FLASH signature value + * @param index : Not used, must be 0 + * @return the generated FLASH signature value + */ +STATIC INLINE uint32_t Chip_FMC_GetSignature(int index) +{ + return LPC_FMC->FMSW[index]; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __FMC_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/gpio_11u6x.h b/source/lpc_chip_11u6x/inc/gpio_11u6x.h new file mode 100644 index 0000000..eb14c74 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/gpio_11u6x.h @@ -0,0 +1,471 @@ +/* + * @brief LPC11u6x GPIO driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __GPIO_11U6X_H_ +#define __GPIO_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup GPIO_11U6X CHIP: LPC11u6x GPIO driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief GPIO port register block structure + */ +typedef struct { /*!< GPIO_PORT Structure */ + __IO uint8_t B[128][32]; /*!< Offset 0x0000: Byte pin registers ports 0 to n; pins PIOn_0 to PIOn_31 */ + __IO uint32_t W[32][32]; /*!< Offset 0x1000: Word pin registers port 0 to n */ + __IO uint32_t DIR[32]; /*!< Offset 0x2000: Direction registers port n */ + __IO uint32_t MASK[32]; /*!< Offset 0x2080: Mask register port n */ + __IO uint32_t PIN[32]; /*!< Offset 0x2100: Portpin register port n */ + __IO uint32_t MPIN[32]; /*!< Offset 0x2180: Masked port register port n */ + __IO uint32_t SET[32]; /*!< Offset 0x2200: Write: Set register for port n Read: output bits for port n */ + __O uint32_t CLR[32]; /*!< Offset 0x2280: Clear port n */ + __O uint32_t NOT[32]; /*!< Offset 0x2300: Toggle port n */ +} LPC_GPIO_T; + +/** + * @brief Initialize GPIO block + * @param pGPIO : The base of GPIO peripheral on the chip + * @return Nothing + */ +void Chip_GPIO_Init(LPC_GPIO_T *pGPIO); + +/** + * @brief De-Initialize GPIO block + * @param pGPIO : The base of GPIO peripheral on the chip + * @return Nothing + */ +void Chip_GPIO_DeInit(LPC_GPIO_T *pGPIO); + +/** + * @brief Set a GPIO port/bit state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to set + * @param pin : GPIO pin to set + * @param setting : true for high, false for low + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_WritePortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t pin, bool setting) +{ + pGPIO->B[port][pin] = setting; +} + +/** + * @brief Set a GPIO pin state via the GPIO byte register + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : GPIO pin to set + * @param setting : true for high, false for low + * @return Nothing + * @note This function replaces Chip_GPIO_WritePortBit() + */ +STATIC INLINE void Chip_GPIO_SetPinState(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool setting) +{ + pGPIO->B[port][pin] = setting; +} + +/** + * @brief Read a GPIO state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to read + * @param pin : GPIO pin to read + * @return true of the GPIO is high, false if low + * @note It is recommended to use the Chip_GPIO_GetPinState() function instead. + */ +STATIC INLINE bool Chip_GPIO_ReadPortBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t pin) +{ + return (bool) pGPIO->B[port][pin]; +} + +/** + * @brief Get a GPIO pin state via the GPIO byte register + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : GPIO pin to get state for + * @return true if the GPIO is high, false if low + * @note This function replaces Chip_GPIO_ReadPortBit() + */ +STATIC INLINE bool Chip_GPIO_GetPinState(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + return (bool) pGPIO->B[port][pin]; +} + +/** + * @brief Set a GPIO direction + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to set + * @param bit : GPIO bit to set + * @param setting : true for output, false for input + * @return Nothing + * @note It is recommended to use the Chip_GPIO_SetPinDIROutput(), + * Chip_GPIO_SetPinDIRInput() or Chip_GPIO_SetPinDIR() functions instead + * of this function. + */ +void Chip_GPIO_WriteDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit, bool setting); + +/** + * @brief Set GPIO direction for a single GPIO pin to an output + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : GPIO pin to set direction on as output + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPinDIROutput(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO->DIR[port] |= 1UL << pin; +} + +/** + * @brief Set GPIO direction for a single GPIO pin to an input + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : GPIO pin to set direction on as input + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPinDIRInput(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO->DIR[port] &= ~(1UL << pin); +} + +/** + * @brief Set GPIO direction for a single GPIO pin + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : GPIO pin to set direction for + * @param output : true for output, false for input + * @return Nothing + */ +void Chip_GPIO_SetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool output); + +/** + * @brief Read a GPIO direction (out or in) + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO port to read + * @param bit : GPIO bit to read + * @return true of the GPIO is an output, false if input + * @note It is recommended to use the Chip_GPIO_GetPinDIR() function instead. + */ +STATIC INLINE bool Chip_GPIO_ReadDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit) +{ + return (bool) (((pGPIO->DIR[port]) >> bit) & 1); +} + +/** + * @brief Get GPIO direction for a single GPIO pin + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : GPIO pin to get direction for + * @return true if the GPIO is an output, false if input + */ +STATIC INLINE bool Chip_GPIO_GetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + return (bool) (((pGPIO->DIR[port]) >> pin) & 1); +} + +/** + * @brief Set Direction for a GPIO port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param portNum : port Number + * @param bitValue : GPIO bit to set + * @param out : Direction value, 0 = input, !0 = output + * @return None + * @note Bits set to '0' are not altered. It is recommended to use the + * Chip_GPIO_SetPortDIR() function instead. + */ +void Chip_GPIO_SetDir(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue, uint8_t out); + +/** + * @brief Set GPIO direction for a all selected GPIO pins to an output + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pinMask : GPIO pin mask to set direction on as output (bits 0..b for pins 0..n) + * @return Nothing + * @note Sets multiple GPIO pins to the output direction, each bit's position that is + * high sets the corresponding pin number for that bit to an output. + */ +STATIC INLINE void Chip_GPIO_SetPortDIROutput(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask) +{ + pGPIO->DIR[port] |= pinMask; +} + +/** + * @brief Set GPIO direction for a all selected GPIO pins to an input + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pinMask : GPIO pin mask to set direction on as input (bits 0..b for pins 0..n) + * @return Nothing + * @note Sets multiple GPIO pins to the input direction, each bit's position that is + * high sets the corresponding pin number for that bit to an input. + */ +STATIC INLINE void Chip_GPIO_SetPortDIRInput(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask) +{ + pGPIO->DIR[port] &= ~pinMask; +} + +/** + * @brief Set GPIO direction for a all selected GPIO pins to an input or output + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pinMask : GPIO pin mask to set direction on (bits 0..b for pins 0..n) + * @param outSet : Direction value, false = set as inputs, true = set as outputs + * @return Nothing + * @note Sets multiple GPIO pins to the input direction, each bit's position that is + * high sets the corresponding pin number for that bit to an input. + */ +void Chip_GPIO_SetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask, bool outSet); + +/** + * @brief Get GPIO direction for a all GPIO pins + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @return a bitfield containing the input and output states for each pin + * @note For pins 0..n, a high state in a bit corresponds to an output state for the + * same pin, while a low state corresponds to an input state. + */ +STATIC INLINE uint32_t Chip_GPIO_GetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO->DIR[port]; +} + +/** + * @brief Set GPIO port mask value for GPIO masked read and write + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : port Number + * @param mask : Mask value for read and write (only low bits are enabled) + * @return Nothing + * @note Controls which bits are set or unset when using the masked + * GPIO read and write functions. A low state indicates the pin is settable + * and readable via the masked write and read functions. + */ +STATIC INLINE void Chip_GPIO_SetPortMask(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t mask) +{ + pGPIO->MASK[port] = mask; +} + +/** + * @brief Get GPIO port mask value used for GPIO masked read and write + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : port Number + * @return Returns value set with the Chip_GPIO_SetPortMask() function. + * @note A high bit in the return value indicates that that GPIO pin for the + * port cannot be set using the masked write function. + */ +STATIC INLINE uint32_t Chip_GPIO_GetPortMask(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO->MASK[port]; +} + +/** + * @brief Set all GPIO raw pin states (regardless of masking) + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param value : Value to set all GPIO pin states (0..n) to + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetPortValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t value) +{ + pGPIO->PIN[port] = value; +} + +/** + * @brief Get all GPIO raw pin states (regardless of masking) + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @return Current (raw) state of all GPIO pins + */ +STATIC INLINE uint32_t Chip_GPIO_GetPortValue(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO->PIN[port]; +} + +/** + * @brief Set all GPIO pin states, but mask via the MASKP0 register + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param value : Value to set all GPIO pin states (0..n) to + * @return Nothing + */ +STATIC INLINE void Chip_GPIO_SetMaskedPortValue(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t value) +{ + pGPIO->MPIN[port] = value; +} + +/** + * @brief Get all GPIO pin statesm but mask via the MASKP0 register + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @return Current (masked) state of all GPIO pins + */ +STATIC INLINE uint32_t Chip_GPIO_GetMaskedPortValue(LPC_GPIO_T *pGPIO, uint8_t port) +{ + return pGPIO->MPIN[port]; +} + +/** + * @brief Set a GPIO port/bit to the high state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param portNum : port number + * @param bitValue : bit(s) in the port to set high + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. It is recommended to use the + * Chip_GPIO_SetPortOutHigh() function instead. + */ +STATIC INLINE void Chip_GPIO_SetValue(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue) +{ + pGPIO->SET[portNum] = bitValue; +} + +/** + * @brief Set selected GPIO output pins to the high state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pins : pins (0..n) to set high + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPortOutHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins) +{ + pGPIO->SET[port] = pins; +} + +/** + * @brief Set an individual GPIO output pin to the high state + * @param pGPIO : The base of GPIO peripheral on the chip' + * @param port : GPIO Port number where @a pin is located + * @param pin : pin number (0..n) to set high + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPinOutHigh(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO->SET[port] = (1 << pin); +} + +/** + * @brief Set a GPIO port/bit to the low state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param portNum : port number + * @param bitValue : bit(s) in the port to set low + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_ClearValue(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue) +{ + pGPIO->CLR[portNum] = bitValue; +} + +/** + * @brief Set selected GPIO output pins to the low state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pins : pins (0..n) to set low + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPortOutLow(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins) +{ + pGPIO->CLR[port] = pins; +} + +/** + * @brief Set an individual GPIO output pin to the low state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : pin number (0..n) to set low + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPinOutLow(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO->CLR[port] = (1 << pin); +} + +/** + * @brief Toggle selected GPIO output pins to the opposite state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pins : pins (0..n) to toggle + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPortToggle(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pins) +{ + pGPIO->NOT[port] = pins; +} + +/** + * @brief Toggle an individual GPIO output pin to the opposite state + * @param pGPIO : The base of GPIO peripheral on the chip + * @param port : GPIO Port number where @a pin is located + * @param pin : pin number (0..n) to toggle + * @return None + * @note Any bit set as a '0' will not have it's state changed. This only + * applies to ports configured as an output. + */ +STATIC INLINE void Chip_GPIO_SetPinToggle(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin) +{ + pGPIO->NOT[port] = (1 << pin); +} + +/** + * @brief Read current bit states for the selected port + * @param pGPIO : The base of GPIO peripheral on the chip + * @param portNum : port number to read + * @return Current value of GPIO port + * @note The current states of the bits for the port are read, regardless of + * whether the GPIO port bits are input or output. + */ +STATIC INLINE uint32_t Chip_GPIO_ReadValue(LPC_GPIO_T *pGPIO, uint8_t portNum) +{ + return pGPIO->PIN[portNum]; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __GPIO_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/gpiogroup_11u6x.h b/source/lpc_chip_11u6x/inc/gpiogroup_11u6x.h new file mode 100644 index 0000000..6a42612 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/gpiogroup_11u6x.h @@ -0,0 +1,205 @@ +/* + * @brief LPC11U6x GPIO group driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __GPIOGROUP_11U6X_H_ +#define __GPIOGROUP_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup GPIOGP_11U6X CHIP: LPC11u6x GPIO group driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief GPIO grouped interrupt register block structure + */ +typedef struct { /*!< GPIO_GROUP_INTn Structure */ + __IO uint32_t CTRL; /*!< GPIO grouped interrupt control register */ + __I uint32_t RESERVED0[7]; + __IO uint32_t PORT_POL[8]; /*!< GPIO grouped interrupt port polarity register */ + __IO uint32_t PORT_ENA[8]; /*!< GPIO grouped interrupt port m enable register */ + uint32_t RESERVED1[4072]; +} LPC_GPIOGROUPINT_T; + +/** + * LPC11u6x GPIO group bit definitions + */ +#define GPIOGR_INT (1 << 0) /*!< GPIO interrupt pending/clear bit */ +#define GPIOGR_COMB (1 << 1) /*!< GPIO interrupt OR(0)/AND(1) mode bit */ +#define GPIOGR_TRIG (1 << 2) /*!< GPIO interrupt edge(0)/level(1) mode bit */ + +/** + * @brief Clear interrupt pending status for the selected group + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_ClearIntStatus(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + uint32_t temp; + + temp = pGPIOGPINT[group].CTRL; + pGPIOGPINT[group].CTRL = temp | GPIOGR_INT; +} + +/** + * @brief Returns current GPIO group inetrrupt pending status + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return true if the group interrupt is pending, otherwise false. + */ +STATIC INLINE bool Chip_GPIOGP_GetIntStatus(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + return (bool) ((pGPIOGPINT[group].CTRL & GPIOGR_INT) != 0); +} + +/** + * @brief Selected GPIO group functionality for trigger on any pin in group (OR mode) + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectOrMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL &= ~GPIOGR_COMB; +} + +/** + * @brief Selected GPIO group functionality for trigger on all matching pins in group (AND mode) + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectAndMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL |= GPIOGR_COMB; +} + +/** + * @brief Selected GPIO group functionality edge trigger mode + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectEdgeMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL &= ~GPIOGR_TRIG; +} + +/** + * @brief Selected GPIO group functionality level trigger mode + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectLevelMode(LPC_GPIOGROUPINT_T *pGPIOGPINT, uint8_t group) +{ + pGPIOGPINT[group].CTRL |= GPIOGR_TRIG; +} + +/** + * @brief Set selected pins for the group and port to low level trigger + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to select for low level (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectLowLevel(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_POL[port] &= ~pinMask; +} + +/** + * @brief Set selected pins for the group and port to high level trigger + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to select for high level (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + */ +STATIC INLINE void Chip_GPIOGP_SelectHighLevel(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_POL[port] |= pinMask; +} + +/** + * @brief Disabled selected pins for the group interrupt + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to disable interrupt for (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + * @note Disabled pins do not contribute to the group interrupt. + */ +STATIC INLINE void Chip_GPIOGP_DisableGroupPins(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_ENA[port] &= ~pinMask; +} + +/** + * @brief Enable selected pins for the group interrupt + * @param pGPIOGPINT : Pointer to GPIO group register block + * @param group : GPIO group number + * @param port : GPIO port number + * @param pinMask : Or'ed value of pins to enable interrupt for (bit 0 = pin 0, 1 = pin1, etc.) + * @return None + * @note Enabled pins contribute to the group interrupt. + */ +STATIC INLINE void Chip_GPIOGP_EnableGroupPins(LPC_GPIOGROUPINT_T *pGPIOGPINT, + uint8_t group, + uint8_t port, + uint32_t pinMask) +{ + pGPIOGPINT[group].PORT_ENA[port] |= pinMask; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __GPIOGROUP_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/i2c_11u6x.h b/source/lpc_chip_11u6x/inc/i2c_11u6x.h new file mode 100644 index 0000000..add6834 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/i2c_11u6x.h @@ -0,0 +1,400 @@ +/* + * @brief LPC11u6x I2C driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __I2C_11U6X_H_ +#define __I2C_11U6X_H_ + +#include "i2c_common_11u6x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @ingroup I2C_11U6X + * @{ + */ + +/** + * @brief Return values for SLAVE handler + * @note + * Chip drivers will usally be designed to match their events with this value + */ +#define RET_SLAVE_TX 6 /**< Return value, when 1 byte TX'd successfully */ +#define RET_SLAVE_RX 5 /**< Return value, when 1 byte RX'd successfully */ +#define RET_SLAVE_IDLE 2 /**< Return value, when slave enter idle mode */ +#define RET_SLAVE_BUSY 0 /**< Return value, when slave is busy */ + +/** + * @brief I2C state handle return values + */ +#define I2C_STA_STO_RECV 0x20 + +/* + * @brief I2C return status code definitions + */ +#define I2C_I2STAT_NO_INF ((0xF8))/*!< No relevant information */ +#define I2C_I2STAT_BUS_ERROR ((0x00))/*!< Bus Error */ + +/* + * @brief I2C status values + */ +#define I2C_SETUP_STATUS_ARBF (1 << 8) /**< Arbitration false */ +#define I2C_SETUP_STATUS_NOACKF (1 << 9) /**< No ACK returned */ +#define I2C_SETUP_STATUS_DONE (1 << 10) /**< Status DONE */ + +/* + * @brief I2C state handle return values + */ +#define I2C_OK 0x00 +#define I2C_BYTE_SENT 0x01 +#define I2C_BYTE_RECV 0x02 +#define I2C_LAST_BYTE_RECV 0x04 +#define I2C_SEND_END 0x08 +#define I2C_RECV_END 0x10 +#define I2C_STA_STO_RECV 0x20 + +#define I2C_ERR (0x10000000) +#define I2C_NAK_RECV (0x10000000 | 0x01) + +#define I2C_CheckError(ErrorCode) (ErrorCode & 0x10000000) + +/* + * @brief I2C monitor control configuration defines + */ +#define I2C_MONITOR_CFG_SCL_OUTPUT I2C_I2MMCTRL_ENA_SCL /**< SCL output enable */ +#define I2C_MONITOR_CFG_MATCHALL I2C_I2MMCTRL_MATCH_ALL /**< Select interrupt register match */ + +/** + * @brief I2C Slave Identifiers + */ +typedef enum { + I2C_SLAVE_GENERAL, /**< Slave ID for general calls */ + I2C_SLAVE_0, /**< Slave ID fo Slave Address 0 */ + I2C_SLAVE_1, /**< Slave ID fo Slave Address 1 */ + I2C_SLAVE_2, /**< Slave ID fo Slave Address 2 */ + I2C_SLAVE_3, /**< Slave ID fo Slave Address 3 */ + I2C_SLAVE_NUM_INTERFACE /**< Number of slave interfaces */ +} I2C_SLAVE_ID; + +/** + * @brief I2C transfer status + */ +typedef enum { + I2C_STATUS_DONE, /**< Transfer done successfully */ + I2C_STATUS_NAK, /**< NAK received during transfer */ + I2C_STATUS_ARBLOST, /**< Aribitration lost during transfer */ + I2C_STATUS_BUSERR, /**< Bus error in I2C transfer */ + I2C_STATUS_BUSY, /**< I2C is busy doing transfer */ + I2C_STATUS_SLAVENAK,/**< NAK received after SLA+W or SLA+R */ +} I2C_STATUS_T; + +/** + * @brief Master transfer data structure definitions + */ +typedef struct { + uint8_t slaveAddr; /**< 7-bit I2C Slave address */ + const uint8_t *txBuff; /**< Pointer to array of bytes to be transmitted */ + int txSz; /**< Number of bytes in transmit array, + if 0 only receive transfer will be carried on */ + uint8_t *rxBuff; /**< Pointer memory where bytes received from I2C be stored */ + int rxSz; /**< Number of bytes to received, + if 0 only transmission we be carried on */ + I2C_STATUS_T status; /**< Status of the current I2C transfer */ +} I2C_XFER_T; + +/** + * @brief I2C interface IDs + * @note + * All Chip functions will take this as the first parameter, + * I2C_NUM_INTERFACE must never be used for calling any Chip + * functions, it is only used to find the number of interfaces + * available in the Chip. + */ +typedef enum I2C_ID { + I2C0, /**< ID I2C0 */ + I2C1, /**< ID I2C1 */ + I2C_NUM_INTERFACE /**< Number of I2C interfaces in the chip */ +} I2C_ID_T; + +/** + * @brief I2C master events + */ +typedef enum { + I2C_EVENT_WAIT = 1, /**< I2C Wait event */ + I2C_EVENT_DONE, /**< Done event that wakes up Wait event */ + I2C_EVENT_LOCK, /**< Re-entrency lock event for I2C transfer */ + I2C_EVENT_UNLOCK, /**< Re-entrency unlock event for I2C transfer */ + I2C_EVENT_SLAVE_RX, /**< Slave receive event */ + I2C_EVENT_SLAVE_TX, /**< Slave transmit event */ +} I2C_EVENT_T; + +/** + * @brief Event handler function type + */ +typedef void (*I2C_EVENTHANDLER_T)(I2C_ID_T, I2C_EVENT_T); + +/** + * @brief Initializes the LPC_I2C peripheral with specified parameter. + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_Init(I2C_ID_T id); + +/** + * @brief De-initializes the I2C peripheral registers to their default reset values + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_DeInit(I2C_ID_T id); + +/** + * @brief Set up clock rate for LPC_I2C peripheral. + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param clockrate : Target clock rate value to initialized I2C peripheral (Hz) + * @return Nothing + * @note + * Parameter @a clockrate for I2C0 should be from 1000 up to 1000000 + * (1 KHz to 1 MHz), as I2C0 support Fast Mode Plus. If the @a clockrate + * is more than 400 KHz (Fast Plus Mode) Board_I2C_EnableFastPlus() + * must be called prior to calling this function. + */ +void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate); + +/** + * @brief Get current clock rate for LPC_I2C peripheral. + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return The current I2C peripheral clock rate + */ +uint32_t Chip_I2C_GetClockRate(I2C_ID_T id); + +/** + * @brief Transmit and Receive data in master mode + * @param id : I2C peripheral selected (I2C0, I2C1 etc) + * @param xfer : Pointer to a I2C_XFER_T structure see notes below + * @return + * Any of #I2C_STATUS_T values, xfer->txSz will have number of bytes + * not sent due to error, xfer->rxSz will have the number of bytes yet + * to be received. + * @note + * The parameter @a xfer should have its member @a slaveAddr initialized + * to the 7-Bit slave address to which the master will do the xfer, Bit0 + * to bit6 should have the address and Bit8 is ignored. During the transfer + * no code (like event handler) must change the content of the memory + * pointed to by @a xfer. The member of @a xfer, @a txBuff and @a txSz be + * initialized to the memory from which the I2C must pick the data to be + * transfered to slave and the number of bytes to send respectively, similarly + * @a rxBuff and @a rxSz must have pointer to memroy where data received + * from slave be stored and the number of data to get from slave respectilvely. + */ +int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer); + +/** + * @brief Transmit data to I2C slave using I2C Master mode + * @param id : I2C peripheral ID (I2C0, I2C1 .. etc) + * @param slaveAddr : Slave address to which the data be written + * @param buff : Pointer to buffer having the array of data + * @param len : Number of bytes to be transfered from @a buff + * @return Number of bytes successfully transfered + */ +int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len); + +/** + * @brief Transfer a command to slave and receive data from slave after a repeated start + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param slaveAddr : Slave address of the I2C device + * @param cmd : Command (Address/Register) to be written + * @param buff : Pointer to memory that will hold the data received + * @param len : Number of bytes to receive + * @return Number of bytes successfully received + */ +int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len); + +/** + * @brief Get pointer to current function handling the events + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Pointer to function handing events of I2C + */ +I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id); + +/** + * @brief Set function that must handle I2C events + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param event : Pointer to function that will handle the event (Should not be NULL) + * @return 1 when successful, 0 when a transfer is on going with its own event handler + */ +int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event); + +/** + * @brief Set function that must handle I2C events + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param slaveAddr : Slave address from which data be read + * @param buff : Pointer to memory where data read be stored + * @param len : Number of bytes to read from slave + * @return Number of bytes read successfully + */ +int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len); + +/** + * @brief Default event handler for polling operation + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param event : Event ID of the event that called the function + * @return Nothing + */ +void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event); + +/** + * @brief Default event handler for interrupt base operation + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param event : Event ID of the event that called the function + * @return Nothing + */ +void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event); + +/** + * @brief I2C Master transfer state change handler + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + * @note Usually called from the appropriate Interrupt handler + */ +void Chip_I2C_MasterStateHandler(I2C_ID_T id); + +/** + * @brief Disable I2C peripheral's operation + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_Disable(I2C_ID_T id); + +/** + * @brief Checks if master xfer in progress + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return 1 if master xfer in progress 0 otherwise + * @note + * This API is generally used in interrupt handler + * of the application to decide whether to call + * master state handler or to call slave state handler + */ +int Chip_I2C_IsMasterActive(I2C_ID_T id); + +/** + * @brief Setup a slave I2C device + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @param sid : I2C Slave peripheral ID (I2C_SLAVE_0, I2C_SLAVE_1 etc) + * @param xfer : Pointer to transfer structure (see note below for more info) + * @param event : Event handler for slave transfers + * @param addrMask : Address mask to use along with slave address (see notes below for more info) + * @return Nothing + * @note + * Parameter @a xfer should point to a valid I2C_XFER_T structure object + * and must have @a slaveAddr initialized with 7bit Slave address (From Bit1 to Bit7), + * Bit0 when set enables general call handling, @a slaveAddr along with @a addrMask will + * be used to match the slave address. @a rxBuff and @a txBuff must point to valid buffers + * where slave can receive or send the data from, size of which will be provided by + * @a rxSz and @a txSz respectively. Function pointed to by @a event will be called + * for the following events #I2C_EVENT_SLAVE_RX (One byte of data received successfully + * from the master and stored inside memory pointed by xfer->rxBuff, incremented + * the pointer and decremented the @a xfer->rxSz), #I2C_EVENT_SLAVE_TX (One byte of + * data from xfer->txBuff was sent to master successfully, incremented the pointer + * and decremented xfer->txSz), #I2C_EVENT_DONE (Master is done doing its transfers + * with the slave).
+ *
Bit-0 of the parameter @a addrMask is reserved and should always be 0. Any bit (BIT1 + * to BIT7) set in @a addrMask will make the corresponding bit in *xfer->slaveAddr* as + * don't care. Thit is, if *xfer->slaveAddr* is (0x10 << 1) and @a addrMask is (0x03 << 1) then + * 0x10, 0x11, 0x12, 0x13 will all be considered as valid slave addresses for the registered + * slave. Upon receving any event *xfer->slaveAddr* (BIT1 to BIT7) will hold the actual + * address which was received from master.
+ *
General Call Handling
+ * Slave can receive data from master using general call address (0x00). General call + * handling must be setup as given below + * - Call Chip_I2C_SlaveSetup() with argument @a sid as I2C_SLAVE_GENERAL + * - xfer->slaveAddr ignored, argument @a addrMask ignored + * - function provided by @a event will registered to be called when slave received data using addr 0x00 + * - xfer->rxBuff and xfer->rxSz should be valid in argument @a xfer + * - To handle General Call only (No other slaves are configured) + * - Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3) + * - setup @a xfer with slaveAddr member set to 0, @a event is ignored hence can be NULL + * - provide @a addrMask (typically 0, if not you better be knowing what you are doing) + * - To handler General Call when other slave is active + * - Call Chip_I2C_SlaveSetup() with sid as I2C_SLAVE_X (X=0,1,2,3) + * - setup @a xfer with slaveAddr member set to 7-Bit Slave address [from Bit1 to 7] + * - Set Bit0 of @a xfer->slaveAddr as 1 + * - Provide appropriate @a addrMask + * - Argument @a event must point to function, that handles events from actual slaveAddress and not the GC + * @warning + * If the slave has only one byte in its txBuff, once that byte is transfered to master the event handler + * will be called for event #I2C_EVENT_DONE. If the master attempts to read more bytes in the same transfer + * then the slave hardware will send 0xFF to master till the end of transfer, event handler will not be + * called to notify this. For more info see section below
+ *
Last data handling in slave
+ * If the user wants to implement a slave which will read a byte from a specific location over and over + * again whenever master reads the slave. If the user initializes the xfer->txBuff as the location to read + * the byte from and xfer->txSz as 1, then say, if master reads one byte; slave will send the byte read from + * xfer->txBuff and will call the event handler with #I2C_EVENT_DONE. If the master attempts to read another + * byte instead of sending the byte read from xfer->txBuff the slave hardware will send 0xFF and no event will + * occur. To handle this issue, slave should set xfer->txSz to 2, in which case when master reads the byte + * event handler will be called with #I2C_EVENT_SLAVE_TX, in which the slave implementation can reset the buffer + * and size back to original location (i.e, xfer->txBuff--, xfer->txSz++), if the master reads another byte + * in the same transfer, byte read from xfer->txBuff will be sent and #I2C_EVENT_SLAVE_TX will be called again, and + * the process repeats. + */ +void Chip_I2C_SlaveSetup(I2C_ID_T id, + I2C_SLAVE_ID sid, + I2C_XFER_T *xfer, + I2C_EVENTHANDLER_T event, + uint8_t addrMask); + +/** + * @brief I2C Slave event handler + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return Nothing + */ +void Chip_I2C_SlaveStateHandler(I2C_ID_T id); + +/** + * @brief I2C peripheral state change checking + * @param id : I2C peripheral ID (I2C0, I2C1 ... etc) + * @return 1 if I2C peripheral @a id has changed its state, + * 0 if there is no state change + * @note + * This function must be used by the application when + * the polling has to be done based on state change. + */ +int Chip_I2C_IsStateChanged(I2C_ID_T id); + +/** + * @} + */ + + #ifdef __cplusplus +} +#endif + +#endif /* __I2C_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/i2c_common_11u6x.h b/source/lpc_chip_11u6x/inc/i2c_common_11u6x.h new file mode 100644 index 0000000..36a2a1b --- /dev/null +++ b/source/lpc_chip_11u6x/inc/i2c_common_11u6x.h @@ -0,0 +1,200 @@ +/* + * @brief LPC11u6x I2C driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __I2C_COMMON_11U6X_H_ +#define __I2C_COMMON_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup I2C_11U6X CHIP: LPC11u6x I2C driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief I2C register block structure + */ +typedef struct { /* I2C0 Structure */ + __IO uint32_t CONSET; /*!< I2C Control Set Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is set. Writing a zero has no effect on the corresponding bit in the I2C control register. */ + __I uint32_t STAT; /*!< I2C Status Register. During I2C operation, this register provides detailed status codes that allow software to determine the next action needed. */ + __IO uint32_t DAT; /*!< I2C Data Register. During master or slave transmit mode, data to be transmitted is written to this register. During master or slave receive mode, data that has been received may be read from this register. */ + __IO uint32_t ADR0; /*!< I2C Slave Address Register 0. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t SCLH; /*!< SCH Duty Cycle Register High Half Word. Determines the high time of the I2C clock. */ + __IO uint32_t SCLL; /*!< SCL Duty Cycle Register Low Half Word. Determines the low time of the I2C clock. SCLL and SCLH together determine the clock frequency generated by an I2C master and certain times used in slave mode. */ + __O uint32_t CONCLR; /*!< I2C Control Clear Register. When a one is written to a bit of this register, the corresponding bit in the I2C control register is cleared. Writing a zero has no effect on the corresponding bit in the I2C control register. */ + __IO uint32_t MMCTRL; /*!< Monitor mode control register. */ + __IO uint32_t ADR1; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t ADR2; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __IO uint32_t ADR3; /*!< I2C Slave Address Register. Contains the 7-bit slave address for operation of the I2C interface in slave mode, and is not used in master mode. The least significant bit determines whether a slave responds to the General Call address. */ + __I uint32_t DATA_BUFFER; /*!< Data buffer register. The contents of the 8 MSBs of the DAT shift register will be transferred to the DATA_BUFFER automatically after every nine bits (8 bits of data plus ACK or NACK) has been received on the bus. */ + __IO uint32_t MASK[4]; /*!< I2C Slave address mask register */ +} LPC_I2C_T; + +/* + * @brief I2C Control Set register description + */ +#define I2C_I2CONSET_AA ((0x04))/*!< Assert acknowledge flag */ +#define I2C_I2CONSET_SI ((0x08))/*!< I2C interrupt flag */ +#define I2C_I2CONSET_STO ((0x10))/*!< STOP flag */ +#define I2C_I2CONSET_STA ((0x20))/*!< START flag */ +#define I2C_I2CONSET_I2EN ((0x40))/*!< I2C interface enable */ + +/* + * @brief I2C Control Clear register description + */ +#define I2C_I2CONCLR_AAC ((1 << 2)) /*!< Assert acknowledge Clear bit */ +#define I2C_I2CONCLR_SIC ((1 << 3)) /*!< I2C interrupt Clear bit */ +#define I2C_I2CONCLR_STOC ((1 << 4)) /*!< I2C STOP Clear bit */ +#define I2C_I2CONCLR_STAC ((1 << 5)) /*!< START flag Clear bit */ +#define I2C_I2CONCLR_I2ENC ((1 << 6)) /*!< I2C interface Disable bit */ + +/* + * @brief I2C Common Control register description + */ +#define I2C_CON_AA (1UL << 2) /*!< Assert acknowledge bit */ +#define I2C_CON_SI (1UL << 3) /*!< I2C interrupt bit */ +#define I2C_CON_STO (1UL << 4) /*!< I2C STOP bit */ +#define I2C_CON_STA (1UL << 5) /*!< START flag bit */ +#define I2C_CON_I2EN (1UL << 6) /*!< I2C interface bit */ + +/* + * @brief I2C Status Code definition (I2C Status register) + */ +#define I2C_STAT_CODE_BITMASK ((0xF8))/*!< Return Code mask in I2C status register */ +#define I2C_STAT_CODE_ERROR ((0xFF))/*!< Return Code error mask in I2C status register */ + +/* + * @brief I2C Master transmit mode + */ +#define I2C_I2STAT_M_TX_START ((0x08))/*!< A start condition has been transmitted */ +#define I2C_I2STAT_M_TX_RESTART ((0x10))/*!< A repeat start condition has been transmitted */ +#define I2C_I2STAT_M_TX_SLAW_ACK ((0x18))/*!< SLA+W has been transmitted, ACK has been received */ +#define I2C_I2STAT_M_TX_SLAW_NACK ((0x20))/*!< SLA+W has been transmitted, NACK has been received */ +#define I2C_I2STAT_M_TX_DAT_ACK ((0x28))/*!< Data has been transmitted, ACK has been received */ +#define I2C_I2STAT_M_TX_DAT_NACK ((0x30))/*!< Data has been transmitted, NACK has been received */ +#define I2C_I2STAT_M_TX_ARB_LOST ((0x38))/*!< Arbitration lost in SLA+R/W or Data bytes */ + +/* + * @brief I2C Master receive mode + */ +#define I2C_I2STAT_M_RX_START ((0x08))/*!< A start condition has been transmitted */ +#define I2C_I2STAT_M_RX_RESTART ((0x10))/*!< A repeat start condition has been transmitted */ +#define I2C_I2STAT_M_RX_ARB_LOST ((0x38))/*!< Arbitration lost */ +#define I2C_I2STAT_M_RX_SLAR_ACK ((0x40))/*!< SLA+R has been transmitted, ACK has been received */ +#define I2C_I2STAT_M_RX_SLAR_NACK ((0x48))/*!< SLA+R has been transmitted, NACK has been received */ +#define I2C_I2STAT_M_RX_DAT_ACK ((0x50))/*!< Data has been received, ACK has been returned */ +#define I2C_I2STAT_M_RX_DAT_NACK ((0x58))/*!< Data has been received, NACK has been returned */ + +/* + * @brief I2C Slave receive mode + */ +#define I2C_I2STAT_S_RX_SLAW_ACK ((0x60))/*!< Own slave address has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_ARB_LOST_M_SLA ((0x68))/*!< Arbitration lost in SLA+R/W as master */ +// #define I2C_I2STAT_S_RX_SLAW_ACK ((0x68)) /*!< Own SLA+W has been received, ACK returned */ +#define I2C_I2STAT_S_RX_GENCALL_ACK ((0x70))/*!< General call address has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_ARB_LOST_M_GENCALL ((0x78))/*!< Arbitration lost in SLA+R/W (GENERAL CALL) as master */ +// #define I2C_I2STAT_S_RX_GENCALL_ACK ((0x78)) /*!< General call address has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_SLA_DAT_ACK ((0x80))/*!< Previously addressed with own SLA; Data has been received, ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_SLA_DAT_NACK ((0x88))/*!< Previously addressed with own SLA;Data has been received and NOT ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_GENCALL_DAT_ACK ((0x90))/*!< Previously addressed with General Call; Data has been received and ACK has been returned */ +#define I2C_I2STAT_S_RX_PRE_GENCALL_DAT_NACK ((0x98))/*!< Previously addressed with General Call; Data has been received and NOT ACK has been returned */ +#define I2C_I2STAT_S_RX_STA_STO_SLVREC_SLVTRX ((0xA0))/*!< A STOP condition or repeated START condition has been received while still addressed as SLV/REC (Slave Receive) or + SLV/TRX (Slave Transmit) */ + +/* + * @brief I2C Slave transmit mode + */ +#define I2C_I2STAT_S_TX_SLAR_ACK ((0xA8))/*!< Own SLA+R has been received, ACK has been returned */ +#define I2C_I2STAT_S_TX_ARB_LOST_M_SLA ((0xB0))/*!< Arbitration lost in SLA+R/W as master */ +// #define I2C_I2STAT_S_TX_SLAR_ACK ((0xB0)) /*!< Own SLA+R has been received, ACK has been returned */ +#define I2C_I2STAT_S_TX_DAT_ACK ((0xB8))/*!< Data has been transmitted, ACK has been received */ +#define I2C_I2STAT_S_TX_DAT_NACK ((0xC0))/*!< Data has been transmitted, NACK has been received */ +#define I2C_I2STAT_S_TX_LAST_DAT_ACK ((0xC8))/*!< Last data byte in I2DAT has been transmitted (AA = 0); ACK has been received */ +#define I2C_SLAVE_TIME_OUT 0x10000000UL/*!< Time out in case of using I2C slave mode */ + +/* + * @brief I2C Data register definition + */ +#define I2C_I2DAT_BITMASK ((0xFF))/*!< Mask for I2DAT register */ +#define I2C_I2DAT_IDLE_CHAR (0xFF) /*!< Idle data value will be send out in slave mode in case of the actual expecting data requested from the master is greater than + its sending data length that can be supported */ + +/* + * @brief I2C Monitor mode control register description + */ +#define I2C_I2MMCTRL_MM_ENA ((1 << 0)) /**< Monitor mode enable */ +#define I2C_I2MMCTRL_ENA_SCL ((1 << 1)) /**< SCL output enable */ +#define I2C_I2MMCTRL_MATCH_ALL ((1 << 2)) /**< Select interrupt register match */ +#define I2C_I2MMCTRL_BITMASK ((0x07)) /**< Mask for I2MMCTRL register */ + +/* + * @brief I2C Data buffer register description + */ +#define I2DATA_BUFFER_BITMASK ((0xFF))/*!< I2C Data buffer register bit mask */ + +/* + * @brief I2C Slave Address registers definition + */ +#define I2C_I2ADR_GC ((1 << 0)) /*!< General Call enable bit */ +#define I2C_I2ADR_BITMASK ((0xFF))/*!< I2C Slave Address registers bit mask */ + +/* + * @brief I2C Mask Register definition + */ +#define I2C_I2MASK_MASK(n) ((n & 0xFE))/*!< I2C Mask Register mask field */ + +/* + * @brief I2C SCL HIGH duty cycle Register definition + */ +#define I2C_I2SCLH_BITMASK ((0xFFFF)) /*!< I2C SCL HIGH duty cycle Register bit mask */ + +/* + * @brief I2C SCL LOW duty cycle Register definition + */ +#define I2C_I2SCLL_BITMASK ((0xFFFF)) /*!< I2C SCL LOW duty cycle Register bit mask */ + +/* + * @brief I2C monitor control configuration defines + */ +#define I2C_MONITOR_CFG_SCL_OUTPUT I2C_I2MMCTRL_ENA_SCL /**< SCL output enable */ +#define I2C_MONITOR_CFG_MATCHALL I2C_I2MMCTRL_MATCH_ALL /**< Select interrupt register match */ + +/** + * @} + */ + + #ifdef __cplusplus +} +#endif + +#endif /* __I2C_COMMON_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/i2cm_11u6x.h b/source/lpc_chip_11u6x/inc/i2cm_11u6x.h new file mode 100644 index 0000000..4b3d0e7 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/i2cm_11u6x.h @@ -0,0 +1,418 @@ +/* + * @brief LPC11u6x I2C driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __I2CM_11U6X_H_ +#define __I2CM_11U6X_H_ + +#include "i2c_common_11u6x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup I2CM_11U6X CHIP: LPC11u6x I2C master-only driver + * @ingroup I2C_11U6X + * This driver only works in master mode. To describe the I2C transactions + * following symbols are used in driver documentation. + * + * Key to symbols + * ============== + * S (1 bit) : Start bit + * P (1 bit) : Stop bit + * Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. + * A, NA (1 bit) : Acknowledge and Not-Acknowledge bit. + * Addr (7 bits): I2C 7 bit address. Note that this can be expanded as usual to + * get a 10 bit I2C address. + * Data (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh + * for 16 bit data. + * [..]: Data sent by I2C device, as opposed to data sent by the host adapter. + * @{ + */ + +/** I2CM_11U6X_OPTIONS_TYPES I2C master transfer options + * @{ + */ + +/** Ignore NACK during data transfer. By default transfer is aborted. */ +#define I2CM_XFER_OPTION_IGNORE_NACK 0x01 +/** ACK last byte received. By default we NACK last byte we receive per I2C spec. */ +#define I2CM_XFER_OPTION_LAST_RX_ACK 0x02 + +/** + * @} + */ + +/** I2CM_11U6X_STATUS_TYPES I2C master transfer status types + * @{ + */ + +#define I2CM_STATUS_OK 0x00 /*!< Requested Request was executed successfully. */ +#define I2CM_STATUS_ERROR 0x01 /*!< Unknown error condition. */ +#define I2CM_STATUS_NAK 0x02 /*!< No acknowledgement received from slave. */ +#define I2CM_STATUS_BUS_ERROR 0x03 /*!< I2C bus error */ +#define I2CM_STATUS_SLAVE_NAK 0x04 /*!< No device responded for given slave address during SLA+W or SLA+R */ +#define I2CM_STATUS_ARBLOST 0x05 /*!< Arbitration lost. */ +#define I2CM_STATUS_BUSY 0xFF /*!< I2C transmistter is busy. */ + +/** + * @} + */ + +/** + * @brief Master transfer data structure definitions + */ +typedef struct { + uint8_t slaveAddr; /*!< 7-bit I2C Slave address */ + uint8_t options; /*!< Options for transfer*/ + uint16_t status; /*!< Status of the current I2C transfer */ + uint16_t txSz; /*!< Number of bytes in transmit array, + if 0 only receive transfer will be carried on */ + uint16_t rxSz; /*!< Number of bytes to received, + if 0 only transmission we be carried on */ + const uint8_t *txBuff; /*!< Pointer to array of bytes to be transmitted */ + uint8_t *rxBuff; /*!< Pointer memory where bytes received from I2C be stored */ +} I2CM_XFER_T; + +/** + * @brief Initialize I2C Interface + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function enables the I2C clock. + */ +void Chip_I2CM_Init(LPC_I2C_T *pI2C); + +/** + * @brief Shutdown I2C Interface + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function disables the I2C clock. + */ +void Chip_I2CM_DeInit(LPC_I2C_T *pI2C); + +/** + * @brief Sets HIGH and LOW duty cycle registers + * @param pI2C : Pointer to selected I2C peripheral + * @param sclH : Number of I2C_PCLK cycles for the SCL HIGH time. + * @param sclL : Number of I2C_PCLK cycles for the SCL LOW time. + * @return Nothing + * @note The frequency is determined by the following formula (I2C_PCLK + * is the frequency of the peripheral I2C clock):
+ * I2C_bitFrequency = (I2C_PCLK)/(sclH + sclL); + */ +static INLINE void Chip_I2CM_SetDutyCycle(LPC_I2C_T *pI2C, uint16_t sclH, uint16_t sclL) +{ + pI2C->SCLH = (uint32_t) sclH; + pI2C->SCLL = (uint32_t) sclL; +} + +/** + * @brief Set up bus speed for LPC_I2C controller + * @param pI2C : Pointer to selected I2C peripheral + * @param busSpeed : I2C bus clock rate + * @return Nothing + * @note Per I2C specification the busSpeed should be + * @li 100000 for Standard mode + * @li 400000 for Fast mode + * @li 1000000 for Fast mode plus + * IOCON registers corresponding to I2C pads should be updated + * according to the bus mode. + */ +void Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed); + +/** + * @brief Transmit START or Repeat-START signal on I2C bus + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function sets the controller to transmit START condition when + * the bus becomes free. + */ +static INLINE void Chip_I2CM_SendStart(LPC_I2C_T *pI2C) +{ + pI2C->CONSET = I2C_CON_I2EN | I2C_CON_STA; +} + +/** + * @brief Reset I2C controller state + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function clears all control/status flags. + */ +static INLINE void Chip_I2CM_ResetControl(LPC_I2C_T *pI2C) +{ + /* Reset STA, STO, SI */ + pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA; + +} + +/** + * @brief Transmit a single data byte through the I2C peripheral + * @param pI2C : Pointer to selected I2C peripheral + * @param data : Byte to transmit + * @return Nothing + * @note This function attempts to place a byte into the UART transmit + * FIFO or transmit hold register regard regardless of UART state + * + */ +static INLINE void Chip_I2CM_WriteByte(LPC_I2C_T *pI2C, uint8_t data) +{ + pI2C->DAT = (uint32_t) data; +} + +/** + * @brief Read a single byte data from the I2C peripheral + * @param pI2C : Pointer to selected I2C peripheral + * @return A single byte of data read + * @note This function reads a byte from the I2C receive hold register + * regardless of I2C state. The I2C status should be read first prior + * to using this function. + */ +static INLINE uint8_t Chip_I2CM_ReadByte(LPC_I2C_T *pI2C) +{ + return (uint8_t) (pI2C->DAT & I2C_I2DAT_BITMASK); +} + +/** + * @brief Generate NACK after receiving next byte + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function sets the controller to NACK after receiving next + * byte from slave transmitter. Used before receiving last byte. + */ +static INLINE void Chip_I2CM_NackNextByte(LPC_I2C_T *pI2C) +{ + pI2C->CONCLR = I2C_CON_AA; +} + +/** + * @brief Transmit STOP signal on I2C bus + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function sets the controller to transmit STOP condition. + */ +static INLINE void Chip_I2CM_SendStop(LPC_I2C_T *pI2C) +{ + pI2C->CONSET = I2C_CON_STO; +} + +/** + * @brief Force start I2C transmit + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function force I2C state machine to start transmitting. + * If an uncontrolled source generates a superfluous START or masks + * a STOP condition, then the I2C-bus stays busy indefinitely. If + * the STA flag is set and bus access is not obtained within a + * reasonable amount of time, then a forced access to the I2C-bus is + * possible. This is achieved by setting the STO flag while the STA + * flag is still set. No STOP condition is transmitted. + */ +static INLINE void Chip_I2CM_ForceStart(LPC_I2C_T *pI2C) +{ + /* check if we are pending on start */ + if (pI2C->CONSET & I2C_CON_STA) { + pI2C->CONSET = I2C_CON_STO; + } + else { + Chip_I2CM_SendStart(pI2C); + } +} + +/** + * @brief Transmit STOP+START signal on I2C bus + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note This function sets the controller to transmit STOP condition + * followed by a START condition. + */ +static INLINE void Chip_I2CM_SendStartAfterStop(LPC_I2C_T *pI2C) +{ + pI2C->CONSET = I2C_CON_STO | I2C_CON_STA; +} + +/** + * @brief Check if I2C controller state changed + * @param pI2C : Pointer to selected I2C peripheral + * @return Returns 0 if state didn't change + * @note + */ +static INLINE uint32_t Chip_I2CM_StateChanged(LPC_I2C_T *pI2C) +{ + return pI2C->CONSET & I2C_CON_SI; +} + +/** + * @brief Clear state change interrupt flag + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note + */ +static INLINE void Chip_I2CM_ClearSI(LPC_I2C_T *pI2C) +{ + pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA; +} + +/** + * @brief Check if I2C bus is free per our controller + * @param pI2C : Pointer to selected I2C peripheral + * @return Returns 0 if busy else a non-zero value. + * @note I2C controller clears STO bit when it sees STOP + * condition after a START condition on the bus. + */ +static INLINE uint32_t Chip_I2CM_BusFree(LPC_I2C_T *pI2C) +{ + return !(pI2C->CONSET & I2C_CON_STO); +} + +/** + * @brief Get current state of the I2C controller + * @param pI2C : Pointer to selected I2C peripheral + * @return Returns 0 if busy else a non-zero value. + * @note I2C controller clears STO bit when it sees STOP + * condition after a START condition on the bus. + */ +static INLINE uint32_t Chip_I2CM_GetCurState(LPC_I2C_T *pI2C) +{ + return pI2C->STAT & I2C_STAT_CODE_BITMASK; +} + +/** + * @brief Disable I2C interface + * @param pI2C : Pointer to selected I2C peripheral + * @return Nothing + * @note + */ +static INLINE void Chip_I2CM_Disable(LPC_I2C_T *pI2C) +{ + pI2C->CONCLR = I2C_CON_I2EN; +} + +/** + * @brief Transfer state change handler handler + * @param pI2C : Pointer to selected I2C peripheral + * @param xfer : Pointer to a I2CM_XFER_T structure see notes below + * @return Returns non-zero value on completion of transfer. The @a status + * member of @a xfer structure contains the current status of the + * transfer at the end of the call. + * @note + * The parameter @a xfer should be same as the one passed to Chip_I2CM_Xfer() + * routine. + */ +uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer); + +/** + * @brief Transmit and Receive data in master mode + * @param pI2C : Pointer to selected I2C peripheral + * @param xfer : Pointer to a I2CM_XFER_T structure see notes below + * @return Nothing. + * @note + * The parameter @a xfer should have its member @a slaveAddr initialized + * to the 7-Bit slave address to which the master will do the xfer, Bit0 + * to bit6 should have the address and Bit8 is ignored. During the transfer + * no code (like event handler) must change the content of the memory + * pointed to by @a xfer. The member of @a xfer, @a txBuff and @a txSz be + * initialized to the memory from which the I2C must pick the data to be + * transfered to slave and the number of bytes to send respectively, similarly + * @a rxBuff and @a rxSz must have pointer to memroy where data received + * from slave be stored and the number of data to get from slave respectilvely. + * Following types of transfers are possible: + * - Write-only transfer: When @a rxSz member of @a xfer is set to 0. + * + * S Addr Wr [A] txBuff0 [A] txBuff1 [A] ... txBuffN [A] P + * + * - If I2CM_XFER_OPTION_IGNORE_NACK is set in @a options memeber + * + * S Addr Wr [A] txBuff0 [A or NA] ... txBuffN [A or NA] P + * + * - Read-only transfer: When @a txSz member of @a xfer is set to 0. + * + * S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] NA P + * + * - If I2CM_XFER_OPTION_LAST_RX_ACK is set in @a options memeber + * + * S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] A P + * + * - Read-Write transfer: When @a rxSz and @ txSz members of @a xfer are non-zero. + * + * S Addr Wr [A] txBuff0 [A] txBuff1 [A] ... txBuffN [A] + * S Addr Rd [A] [rxBuff0] A [rxBuff1] A ... [rxBuffN] NA P + * + */ +void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer); + +/** + * @brief Transmit and Receive data in master mode + * @param pI2C : Pointer to selected I2C peripheral + * @param xfer : Pointer to a I2CM_XFER_T structure see notes below + * @return Returns non-zero value on succesful completion of transfer. + * @note + * This function operates same as Chip_I2CM_Xfer(), but is a blocking call. + */ +uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer); + +/** + * @brief Write given buffer of data to I2C interface + * @param pI2C : Pointer to selected I2C peripheral + * @param buff : Pointer to buffer to be transmitted + * @param len : Length of the buffer + * @return Returns number of bytes written. + * @note This function is a blocking call. The function generates + * START/repeat-START condition on bus and starts transmitting + * data untill transfer finishes or a NACK is received. No + * STOP condition is transmitted on the bus. + * + * S Data0 [A] Data1 [A] ... DataN [A] + */ +uint32_t Chip_I2CM_Write(LPC_I2C_T *pI2C, const uint8_t *buff, uint32_t len); + +/** + * @brief Read data from I2C slave to given buffer + * @param pI2C : Pointer to selected I2C peripheral + * @param buff : Pointer to buffer for data received from I2C slave + * @param len : Length of the buffer + * @return Returns number of bytes read. + * @note This function is a blocking call. The function generates + * START/repeat-START condition on bus and starts reading + * data untill requested number of bytes are read. No + * STOP condition is transmitted on the bus. + * + * S [Data0] A [Data1] A ... [DataN] A + */ +uint32_t Chip_I2CM_Read(LPC_I2C_T *pI2C, uint8_t *buff, uint32_t len); + +/** + * @} + */ + + #ifdef __cplusplus +} +#endif + +#endif /* __I2C_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/iap.h b/source/lpc_chip_11u6x/inc/iap.h new file mode 100644 index 0000000..e04ec83 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/iap.h @@ -0,0 +1,91 @@ +/* + * @brief Common IAP support functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __IAP_H_ +#define __IAP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup COMMON_IAP CHIP: Common Chip ISP/IAP commands and return codes + * @ingroup CHIP_Common + * @{ + */ + +/* IAP command definitions */ +#define IAP_PREWRRITE_CMD 50 /*!< Prepare sector for write operation command */ +#define IAP_WRISECTOR_CMD 51 /*!< Write Sector command */ +#define IAP_ERSSECTOR_CMD 52 /*!< Erase Sector command */ +#define IAP_BLANK_CHECK_SECTOR_CMD 53 /*!< Blank check sector */ +#define IAP_REPID_CMD 54 /*!< Read PartID command */ +#define IAP_READ_BOOT_CODE_CMD 55 /*!< Read Boot code version */ +#define IAP_COMPARE_CMD 56 /*!< Compare two RAM address locations */ +#define IAP_REINVOKE_ISP_CMD 57 /*!< Reinvoke ISP */ +#define IAP_READ_UID_CMD 58 /*!< Read UID */ +#define IAP_ERASE_PAGE_CMD 59 /*!< Erase page */ +#define IAP_EEPROM_WRITE 61 /*!< EEPROM Write command */ +#define IAP_EEPROM_READ 62 /*!< EEPROM READ command */ + +/* IAP response definitions */ +#define IAP_CMD_SUCCESS 0 /*!< Command is executed successfully */ +#define IAP_INVALID_COMMAND 1 /*!< Invalid command */ +#define IAP_SRC_ADDR_ERROR 2 /*!< Source address is not on word boundary */ +#define IAP_DST_ADDR_ERROR 3 /*!< Destination address is not on a correct boundary */ +#define IAP_SRC_ADDR_NOT_MAPPED 4 /*!< Source address is not mapped in the memory map */ +#define IAP_DST_ADDR_NOT_MAPPED 5 /*!< Destination address is not mapped in the memory map */ +#define IAP_COUNT_ERROR 6 /*!< Byte count is not multiple of 4 or is not a permitted value */ +#define IAP_INVALID_SECTOR 7 /*!< Sector number is invalid or end sector number is greater than start sector number */ +#define IAP_SECTOR_NOT_BLANK 8 /*!< Sector is not blank */ +#define IAP_SECTOR_NOT_PREPARED 9 /*!< Command to prepare sector for write operation was not executed */ +#define IAP_COMPARE_ERROR 10 /*!< Source and destination data not equal */ +#define IAP_BUSY 11 /*!< Flash programming hardware interface is busy */ +#define IAP_PARAM_ERROR 12 /*!< nsufficient number of parameters or invalid parameter */ +#define IAP_ADDR_ERROR 13 /*!< Address is not on word boundary */ +#define IAP_ADDR_NOT_MAPPED 14 /*!< Address is not mapped in the memory map */ +#define IAP_CMD_LOCKED 15 /*!< Command is locked */ +#define IAP_INVALID_CODE 16 /*!< Unlock code is invalid */ +#define IAP_INVALID_BAUD_RATE 17 /*!< Invalid baud rate setting */ +#define IAP_INVALID_STOP_BIT 18 /*!< Invalid stop bit setting */ +#define IAP_CRP_ENABLED 19 /*!< Code read protection enabled */ + +/* IAP_ENTRY API function type */ +typedef void (*IAP_ENTRY_T)(unsigned int[5], unsigned int[4]); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __IAP_H_ */ diff --git a/source/lpc_chip_11u6x/inc/iocon_11u6x.h b/source/lpc_chip_11u6x/inc/iocon_11u6x.h new file mode 100644 index 0000000..2bc00de --- /dev/null +++ b/source/lpc_chip_11u6x/inc/iocon_11u6x.h @@ -0,0 +1,139 @@ +/* + * @brief LPC11u6x IOCON driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __IOCON_11U6X_H_ +#define __IOCON_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup IOCON_11U6X CHIP: LPC11u6x IO Control driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief LPC11u6x IO Configuration Unit register block structure + */ +typedef struct { /*!< LPC11U6X IOCON Structure */ + __IO uint32_t PIO0[24]; + __IO uint32_t PIO1[32]; + __I uint32_t reserved[4]; + __IO uint32_t PIO2A[2];/* PIO2_0/1 only */ + __I uint32_t reserved1[1]; + __IO uint32_t PIO2B[22]; /* PIO2_2 to PIO_2_23 */ +} LPC_IOCON_T; + +/** + * @brief Array of IOCON pin definitions passed to Chip_IOCON_SetPinMuxing() must be in this format + */ +typedef struct { + uint32_t port : 8; /* Pin port */ + uint32_t pin : 8; /* Pin number */ + uint32_t modefunc : 16; /* Function and mode */ +} PINMUX_GRP_T; + +/** + * IOCON function and mode selection definitions + * See the User Manual for specific modes and functions supported by the + * various LPC11u6x pins. + */ +#define IOCON_FUNC0 0x0 /*!< Selects pin function 0 */ +#define IOCON_FUNC1 0x1 /*!< Selects pin function 1 */ +#define IOCON_FUNC2 0x2 /*!< Selects pin function 2 */ +#define IOCON_FUNC3 0x3 /*!< Selects pin function 3 */ +#define IOCON_FUNC4 0x4 /*!< Selects pin function 4 */ +#define IOCON_FUNC5 0x5 /*!< Selects pin function 5 */ +#define IOCON_FUNC6 0x6 /*!< Selects pin function 6 */ +#define IOCON_FUNC7 0x7 /*!< Selects pin function 7 */ +#define IOCON_MODE_INACT (0x0 << 3) /*!< No addition pin function */ +#define IOCON_MODE_PULLDOWN (0x1 << 3) /*!< Selects pull-down function */ +#define IOCON_MODE_PULLUP (0x2 << 3) /*!< Selects pull-up function */ +#define IOCON_MODE_REPEATER (0x3 << 3) /*!< Selects pin repeater function */ +#define IOCON_HYS_EN (0x1 << 5) /*!< Enables hysteresis */ +#define IOCON_INV_EN (0x1 << 6) /*!< Enables invert function on input */ +#define IOCON_ADMODE_EN (0x0 << 7) /*!< Enables analog input function (analog pins only) */ +#define IOCON_DIGMODE_EN (0x1 << 7) /*!< Enables digital function (analog pins only) */ +#define IOCON_SFI2C_EN (0x0 << 8) /*!< I2C standard mode/fast-mode */ +#define IOCON_STDI2C_EN (0x1 << 8) /*!< I2C standard I/O functionality */ +#define IOCON_FASTI2C_EN (0x2 << 8) /*!< I2C Fast-mode Plus */ +#define IOCON_FILT_DIS (0x1 << 8) /*!< Disables noise pulses filtering (10nS glitch filter) */ +#define IOCON_OPENDRAIN_EN (0x1 << 10) /*!< Enables open-drain function */ +#define IOCON_S_MODE_0CLK (0x0 << 11) /*!< Bypass input filter */ +#define IOCON_S_MODE_1CLK (0x1 << 11) /*!< Input pulses shorter than 1 filter clock are rejected */ +#define IOCON_S_MODE_2CLK (0x2 << 11) /*!< Input pulses shorter than 2 filter clock2 are rejected */ +#define IOCON_S_MODE_3CLK (0x3 << 11) /*!< Input pulses shorter than 3 filter clock2 are rejected */ +#define IOCON_S_MODE(clks) ((clks) << 11) /*!< Select clocks for digital input filter mode */ +#define IOCON_CLKDIV(div) ((div) << 13) /*!< Select peripheral clock divider for input filter sampling clock, 0 -6 */ + +/** + * @brief Sets I/O Control pin mux + * @param pIOCON : The base of IOCON peripheral on the chip + * @param port : GPIO port to mux + * @param pin : GPIO pin to mux + * @param modefunc : OR'ed values or type IOCON_* + * @return Nothing + */ +void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc); + +/** + * @brief I/O Control pin mux + * @param pIOCON : The base of IOCON peripheral on the chip + * @param port : GPIO port to mux + * @param pin : GPIO pin to mux + * @param mode : OR'ed values or type IOCON_* + * @param func : Pin function, value of type IOCON_FUNC? + * @return Nothing + */ +STATIC INLINE void Chip_IOCON_PinMux(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint16_t mode, uint8_t func) +{ + Chip_IOCON_PinMuxSet(pIOCON, port, pin, (uint32_t) (mode | func)); +} + +/** + * @brief Set all I/O Control pin muxing + * @param pIOCON : The base of IOCON peripheral on the chip + * @param pinArray : Pointer to array of pin mux selections + * @param arrayLength : Number of entries in pinArray + * @return Nothing + */ +void Chip_IOCON_SetPinMuxing(LPC_IOCON_T *pIOCON, const PINMUX_GRP_T* pinArray, uint32_t arrayLength); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __IOCON_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/lpc_types.h b/source/lpc_chip_11u6x/inc/lpc_types.h new file mode 100644 index 0000000..14c7b60 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/lpc_types.h @@ -0,0 +1,216 @@ +/* + * @brief Common types used in LPC functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __LPC_TYPES_H_ +#define __LPC_TYPES_H_ + +#include +#include + +/** @defgroup LPC_Types CHIP: LPC Common Types + * @ingroup CHIP_Common + * @{ + */ + +/** @defgroup LPC_Types_Public_Types LPC Public Types + * @{ + */ + +/** + * @brief Boolean Type definition + */ +typedef enum {FALSE = 0, TRUE = !FALSE} Bool; + +/** + * @brief Boolean Type definition + */ +#if !defined(__cplusplus) +// typedef enum {false = 0, true = !false} bool; +#endif + +/** + * @brief Flag Status and Interrupt Flag Status type definition + */ +typedef enum {RESET = 0, SET = !RESET} FlagStatus, IntStatus, SetState; +#define PARAM_SETSTATE(State) ((State == RESET) || (State == SET)) + +/** + * @brief Functional State Definition + */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +#define PARAM_FUNCTIONALSTATE(State) ((State == DISABLE) || (State == ENABLE)) + +/** + * @ Status type definition + */ +typedef enum {ERROR = 0, SUCCESS = !ERROR} Status; + +/** + * Read/Write transfer type mode (Block or non-block) + */ +typedef enum { + NONE_BLOCKING = 0, /**< None Blocking type */ + BLOCKING, /**< Blocking type */ +} TRANSFER_BLOCK_T; + +/** Pointer to Function returning Void (any number of parameters) */ +typedef void (*PFV)(); + +/** Pointer to Function returning int32_t (any number of parameters) */ +typedef int32_t (*PFI)(); + +/** + * @} + */ + +/** @defgroup LPC_Types_Public_Macros LPC Public Macros + * @{ + */ + +/* _BIT(n) sets the bit at position "n" + * _BIT(n) is intended to be used in "OR" and "AND" expressions: + * e.g., "(_BIT(3) | _BIT(7))". + */ +#undef _BIT +/* Set bit macro */ +#define _BIT(n) (1 << (n)) + +/* _SBF(f,v) sets the bit field starting at position "f" to value "v". + * _SBF(f,v) is intended to be used in "OR" and "AND" expressions: + * e.g., "((_SBF(5,7) | _SBF(12,0xF)) & 0xFFFF)" + */ +#undef _SBF +/* Set bit field macro */ +#define _SBF(f, v) ((v) << (f)) + +/* _BITMASK constructs a symbol with 'field_width' least significant + * bits set. + * e.g., _BITMASK(5) constructs '0x1F', _BITMASK(16) == 0xFFFF + * The symbol is intended to be used to limit the bit field width + * thusly: + * = (any_expression) & _BITMASK(x), where 0 < x <= 32. + * If "any_expression" results in a value that is larger than can be + * contained in 'x' bits, the bits above 'x - 1' are masked off. When + * used with the _SBF example above, the example would be written: + * a_reg = ((_SBF(5,7) | _SBF(12,0xF)) & _BITMASK(16)) + * This ensures that the value written to a_reg is no wider than + * 16 bits, and makes the code easier to read and understand. + */ +#undef _BITMASK +/* Bitmask creation macro */ +#define _BITMASK(field_width) ( _BIT(field_width) - 1) + +/* NULL pointer */ +#ifndef NULL +#define NULL ((void *) 0) +#endif + +/* Number of elements in an array */ +#define NELEMENTS(array) (sizeof(array) / sizeof(array[0])) + +/* Static data/function define */ +#define STATIC static +/* External data/function define */ +#define EXTERN extern + +#if !defined(MAX) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#if !defined(MIN) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/** + * @} + */ + +/* Old Type Definition compatibility */ +/** @addtogroup LPC_Types_Public_Types + * @{ + */ + +/** LPC type for character type */ +typedef char CHAR; + +/** LPC type for 8 bit unsigned value */ +typedef uint8_t UNS_8; + +/** LPC type for 8 bit signed value */ +typedef int8_t INT_8; + +/** LPC type for 16 bit unsigned value */ +typedef uint16_t UNS_16; + +/** LPC type for 16 bit signed value */ +typedef int16_t INT_16; + +/** LPC type for 32 bit unsigned value */ +typedef uint32_t UNS_32; + +/** LPC type for 32 bit signed value */ +typedef int32_t INT_32; + +/** LPC type for 64 bit signed value */ +typedef int64_t INT_64; + +/** LPC type for 64 bit unsigned value */ +typedef uint64_t UNS_64; + +#ifdef __CODE_RED +#define BOOL_32 bool +#define BOOL_16 bool +#define BOOL_8 bool +#else +/** 32 bit boolean type */ +typedef bool BOOL_32; + +/** 16 bit boolean type */ +typedef bool BOOL_16; + +/** 8 bit boolean type */ +typedef bool BOOL_8; +#endif + +#ifdef __CC_ARM +#define INLINE __inline +#else +#define INLINE inline +#endif + +/** + * @} + */ + +/** + * @} + */ + +#endif /* __LPC_TYPES_H_ */ diff --git a/source/lpc_chip_11u6x/inc/pinint_11u6x.h b/source/lpc_chip_11u6x/inc/pinint_11u6x.h new file mode 100644 index 0000000..660ba0e --- /dev/null +++ b/source/lpc_chip_11u6x/inc/pinint_11u6x.h @@ -0,0 +1,358 @@ +/* + * @brief LPC11u6x Pin Interrupt and Pattern Match Registers and driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __PININT_11U6X_H_ +#define __PININT_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup PININT_11U6X CHIP: LPC11u6x Pin Interrupt and Pattern Match driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief LPC11u6x Pin Interrupt and Pattern Match register block structure + */ +typedef struct { /*!< PIN_INT Structure */ + __IO uint32_t ISEL; /*!< Pin Interrupt Mode register */ + __IO uint32_t IENR; /*!< Pin Interrupt Enable (Rising) register */ + __IO uint32_t SIENR; /*!< Set Pin Interrupt Enable (Rising) register */ + __IO uint32_t CIENR; /*!< Clear Pin Interrupt Enable (Rising) register */ + __IO uint32_t IENF; /*!< Pin Interrupt Enable Falling Edge / Active Level register */ + __IO uint32_t SIENF; /*!< Set Pin Interrupt Enable Falling Edge / Active Level register */ + __IO uint32_t CIENF; /*!< Clear Pin Interrupt Enable Falling Edge / Active Level address */ + __IO uint32_t RISE; /*!< Pin Interrupt Rising Edge register */ + __IO uint32_t FALL; /*!< Pin Interrupt Falling Edge register */ + __IO uint32_t IST; /*!< Pin Interrupt Status register */ + __IO uint32_t PMCTRL; /*!< GPIO pattern match interrupt control register */ + __IO uint32_t PMSRC; /*!< GPIO pattern match interrupt bit-slice source register */ + __IO uint32_t PMCFG; /*!< GPIO pattern match interrupt bit slice configuration register */ +} LPC_PIN_INT_T; + +/** + * LPC11u6x Pin Interrupt and Pattern match engine register + * bit fields and macros + */ +/* PININT interrupt control register */ +#define PININT_PMCTRL_PMATCH_SEL (1 << 0) +#define PININT_PMCTRL_RXEV_ENA (1 << 1) + +/* PININT Bit slice source register bits */ +#define PININT_SRC_BITSOURCE_START 8 +#define PININT_SRC_BITSOURCE_MASK 7 + +/* PININT Bit slice configuration register bits */ +#define PININT_SRC_BITCFG_START 8 +#define PININT_SRC_BITCFG_MASK 7 + +/** + * LPC11u6x Pin Interrupt channel values + */ +#define PININTCH0 (1 << 0) +#define PININTCH1 (1 << 1) +#define PININTCH2 (1 << 2) +#define PININTCH3 (1 << 3) +#define PININTCH4 (1 << 4) +#define PININTCH5 (1 << 5) +#define PININTCH6 (1 << 6) +#define PININTCH7 (1 << 7) +#define PININTCH(ch) (1 << (ch)) + +/** + * LPC11u6x Pin Matching Interrupt bit slice enum values + */ +typedef enum Chip_PININT_BITSLICE { + PININTBITSLICE0 = 0, /*!< PININT Bit slice 0 */ + PININTBITSLICE1 = 1, /*!< PININT Bit slice 1 */ + PININTBITSLICE2 = 2, /*!< PININT Bit slice 2 */ + PININTBITSLICE3 = 3, /*!< PININT Bit slice 3 */ + PININTBITSLICE4 = 4, /*!< PININT Bit slice 4 */ + PININTBITSLICE5 = 5, /*!< PININT Bit slice 5 */ + PININTBITSLICE6 = 6, /*!< PININT Bit slice 6 */ + PININTBITSLICE7 = 7 /*!< PININT Bit slice 7 */ +} Chip_PININT_BITSLICE_T; + +/** + * LPC11u6x Pin Matching Interrupt bit slice configuration enum values + */ +typedef enum Chip_PININT_BITSLICE_CFG { + PININT_PATTERNCONST1 = 0x0, /*!< Contributes to product term match */ + PININT_PATTERNRISING = 0x1, /*!< Rising edge */ + PININT_PATTERNFALLING = 0x2, /*!< Falling edge */ + PININT_PATTERNRISINGRFALLING = 0x3, /*!< Rising or Falling edge */ + PININT_PATTERNHIGH = 0x4, /*!< High level */ + PININT_PATTERNLOW = 0x5, /*!< Low level */ + PININT_PATTERCONST0 = 0x6, /*!< Never contributes for match */ + PININT_PATTEREVENT = 0x7 /*!< Match occurs on event */ +} Chip_PININT_BITSLICE_CFG_T; + +/** + * @brief Initialize Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + * @note This function should be used after the Chip_GPIO_Init() function. + */ +STATIC INLINE void Chip_PININT_Init(LPC_PIN_INT_T *pPININT) {} + +/** + * @brief De-Initialize Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DeInit(LPC_PIN_INT_T *pPININT) {} + +/** + * @brief Configure the pins as edge sensitive in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_SetPinModeEdge(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->ISEL &= ~pins; +} + +/** + * @brief Configure the pins as level sensitive in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_SetPinModeLevel(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->ISEL |= pins; +} + +/** + * @brief Return current PININT rising edge or high level interrupt enable state + * @param pPININT : The base address of Pin interrupt block + * @return A bifield containing the high edge/level interrupt enables for each + * interrupt. Bit 0 = PININT0, 1 = PININT1, etc. + * For each bit, a 0 means the high edge/level interrupt is disabled, while a 1 + * means it's enabled. + */ +STATIC INLINE uint32_t Chip_PININT_GetHighEnabled(LPC_PIN_INT_T *pPININT) +{ + return pPININT->IENR; +} + +/** + * @brief Enable high edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to enable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_EnableIntHigh(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->SIENR = pins; +} + +/** + * @brief Disable high edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to disable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DisableIntHigh(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->CIENR = pins; +} + +/** + * @brief Return current PININT falling edge or low level interrupt enable state + * @param pPININT : The base address of Pin interrupt block + * @return A bifield containing the low edge/level interrupt enables for each + * interrupt. Bit 0 = PININT0, 1 = PININT1, etc. + * For each bit, a 0 means the low edge/level interrupt is disabled, while a 1 + * means it's enabled. + */ +STATIC INLINE uint32_t Chip_PININT_GetLowEnabled(LPC_PIN_INT_T *pPININT) +{ + return pPININT->IENF; +} + +/** + * @brief Enable low edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to enable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_EnableIntLow(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->SIENF = pins; +} + +/** + * @brief Disable low edge/level PININT interrupts for pins + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins to disable (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DisableIntLow(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->CIENF = pins; +} + +/** + * @brief Return pin states that have a detected latched high edge (RISE) state + * @param pPININT : The base address of Pin interrupt block + * @return PININT states (bit n = high) with a latched rise state detected + */ +STATIC INLINE uint32_t Chip_PININT_GetRiseStates(LPC_PIN_INT_T *pPININT) +{ + return pPININT->RISE; +} + +/** + * @brief Clears pin states that had a latched high edge (RISE) state + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins with latched states to clear + * @return Nothing + */ +STATIC INLINE void Chip_PININT_ClearRiseStates(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->RISE = pins; +} + +/** + * @brief Return pin states that have a detected latched falling edge (FALL) state + * @param pPININT : The base address of Pin interrupt block + * @return PININT states (bit n = high) with a latched rise state detected + */ +STATIC INLINE uint32_t Chip_PININT_GetFallStates(LPC_PIN_INT_T *pPININT) +{ + return pPININT->FALL; +} + +/** + * @brief Clears pin states that had a latched falling edge (FALL) state + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pins with latched states to clear + * @return Nothing + */ +STATIC INLINE void Chip_PININT_ClearFallStates(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->FALL = pins; +} + +/** + * @brief Get interrupt status from Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Interrupt status (bit n for PININTn = high means interrupt ie pending) + */ +STATIC INLINE uint32_t Chip_PININT_GetIntStatus(LPC_PIN_INT_T *pPININT) +{ + return pPININT->IST; +} + +/** + * @brief Clear interrupt status in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param pins : Pin interrupts to clear (ORed value of PININTCH*) + * @return Nothing + */ +STATIC INLINE void Chip_PININT_ClearIntStatus(LPC_PIN_INT_T *pPININT, uint32_t pins) +{ + pPININT->IST = pins; +} + +/** + * @brief Set source for pattern match in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param chan : PININT channel number (From 0 to 7) + * @param slice : PININT slice number + * @return Nothing + */ +void Chip_PININT_SetPatternMatchSrc(LPC_PIN_INT_T *pPININT, uint8_t chan, Chip_PININT_BITSLICE_T slice); + +/** + * @brief Configure the pattern matcch in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @param slice : PININT slice number + * @param slice_cfg : PININT slice configuration value (enum Chip_PININT_BITSLICE_CFG_T) + * @param end_point : If true, current slice is final component + * @return Nothing + */ +void Chip_PININT_SetPatternMatchConfig(LPC_PIN_INT_T *pPININT, Chip_PININT_BITSLICE_T slice, + Chip_PININT_BITSLICE_CFG_T slice_cfg, bool end_point); + +/** + * @brief Enable pattern match interrupts in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + */ +STATIC INLINE void Chip_PININT_EnablePatternMatch(LPC_PIN_INT_T *pPININT) +{ + pPININT->PMCTRL |= PININT_PMCTRL_PMATCH_SEL; +} + +/** + * @brief Disable pattern match interrupts in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DisablePatternMatch(LPC_PIN_INT_T *pPININT) +{ + pPININT->PMCTRL &= ~PININT_PMCTRL_PMATCH_SEL; +} + +/** + * @brief Enable RXEV output in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + */ +STATIC INLINE void Chip_PININT_EnablePatternMatchRxEv(LPC_PIN_INT_T *pPININT) +{ + pPININT->PMCTRL |= PININT_PMCTRL_RXEV_ENA; +} + +/** + * @brief Disable RXEV output in Pin interrupt block + * @param pPININT : The base address of Pin interrupt block + * @return Nothing + */ +STATIC INLINE void Chip_PININT_DisablePatternMatchRxEv(LPC_PIN_INT_T *pPININT) +{ + pPININT->PMCTRL &= ~PININT_PMCTRL_RXEV_ENA; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PININT_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/pmu_11u6x.h b/source/lpc_chip_11u6x/inc/pmu_11u6x.h new file mode 100644 index 0000000..9960783 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/pmu_11u6x.h @@ -0,0 +1,231 @@ +/* + * @brief LPC11U6x PMU chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __PMU_11U6X_H_ +#define __PMU_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup PMU_11U6X CHIP: LPC11u6x Power Management Unit block driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief LPC11u6x Power Management Unit register block structure + */ +typedef struct { + __IO uint32_t PCON; /*!< Offset: 0x000 Power control Register (R/W) */ + __IO uint32_t GPREG[4]; /*!< Offset: 0x004 General purpose Registers 0..3 (R/W) */ + __IO uint32_t DPDCTRL; /*!< Offset: 0x014 Deep power-down control register (R/W) */ +} LPC_PMU_T; + +/** + * @brief LPC11u6x low power mode type definitions + */ +typedef enum CHIP_PMU_MCUPOWER { + PMU_MCU_SLEEP = 0, /*!< Sleep mode */ + PMU_MCU_DEEP_SLEEP, /*!< Deep Sleep mode */ + PMU_MCU_POWER_DOWN, /*!< Power down mode */ + PMU_MCU_DEEP_PWRDOWN /*!< Deep power down mode */ +} CHIP_PMU_MCUPOWER_T; + +/** + * PMU PCON register bit fields & masks + */ +#define PMU_PCON_PM_SLEEP (0x0) /*!< ARM WFI enter sleep mode */ +#define PMU_PCON_PM_DEEPSLEEP (0x1) /*!< ARM WFI enter Deep-sleep mode */ +#define PMU_PCON_PM_POWERDOWN (0x2) /*!< ARM WFI enter Power-down mode */ +#define PMU_PCON_PM_DEEPPOWERDOWN (0x3) /*!< ARM WFI enter Deep Power-down mode */ +#define PMU_PCON_NODPD (1 << 3) /*!< Disable deep power-down mode */ +#define PMU_PCON_SLEEPFLAG (1 << 8) /*!< Sleep mode flag */ +#define PMU_PCON_DPDFLAG (1 << 11) /*!< Deep power-down flag */ + +/** + * PMU DPDCTRL register bit fields & masks + */ +#define PMU_DPDCTRL_WAKEUPPHYS (1 << 10) /** Enable wake-up pin hysteresis */ +#define PMU_DPDCTRL_WAKEPAD (1 << 11) /** Disable the Wake-up function on pin PIO0_16 */ + +/** + * @brief Write a value to a GPREG register + * @param pPMU : Pointer to PMU register block + * @param regIndex : Register index to write to, must be 0..3 + * @param value : Value to write + * @return None + */ +STATIC INLINE void Chip_PMU_WriteGPREG(LPC_PMU_T *pPMU, uint8_t regIndex, uint32_t value) +{ + pPMU->GPREG[regIndex] = value; +} + +/** + * @brief Read a value to a GPREG register + * @param pPMU : Pointer to PMU register block + * @param regIndex : Register index to read from, must be 0..3 + * @return Value read from the GPREG register + */ +STATIC INLINE uint32_t Chip_PMU_ReadGPREG(LPC_PMU_T *pPMU, uint8_t regIndex) +{ + return pPMU->GPREG[regIndex]; +} + +/** + * @brief Enter MCU Sleep mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note The sleep mode affects the ARM Cortex-M0+ core only. Peripherals + * and memories are active. + */ +void Chip_PMU_SleepState(LPC_PMU_T *pPMU); + +/** + * @brief Enter MCU Deep Sleep mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note In Deep-sleep mode, the peripherals receive no internal clocks. + * The flash is in stand-by mode. The SRAM memory and all peripheral registers + * as well as the processor maintain their internal states. The WWDT, WKT, + * and BOD can remain active to wake up the system on an interrupt. + */ +void Chip_PMU_DeepSleepState(LPC_PMU_T *pPMU); + +/** + * @brief Enter MCU Power down mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note In Power-down mode, the peripherals receive no internal clocks. + * The internal SRAM memory and all peripheral registers as well as the + * processor maintain their internal states. The flash memory is powered + * down. The WWDT, WKT, and BOD can remain active to wake up the system + * on an interrupt. + */ +void Chip_PMU_PowerDownState(LPC_PMU_T *pPMU); + +/** + * @brief Enter MCU Deep Power down mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note For maximal power savings, the entire system is shut down + * except for the general purpose registers in the PMU and the self + * wake-up timer. Only the general purpose registers in the PMU maintain + * their internal states. The part can wake up on a pulse on the WAKEUP + * pin or when the self wake-up timer times out. On wake-up, the part + * reboots. + */ +void Chip_PMU_DeepPowerDownState(LPC_PMU_T *pPMU); + +/** + * @brief Place the MCU in a low power state + * @param pPMU : Pointer to PMU register block + * @param SleepMode : Sleep mode + * @return None + */ +void Chip_PMU_Sleep(LPC_PMU_T *pPMU, CHIP_PMU_MCUPOWER_T SleepMode); + +/** + * @brief Disables deep power-down mode + * @param pPMU : Pointer to PMU register block + * @return None + * @note Calling this functions prevents entry to Deep power-down + * mode. Once set, this can only be cleared by power-on reset. + */ +STATIC INLINE void Chip_PMU_DisableDeepPowerDown(LPC_PMU_T *pPMU) +{ + pPMU->PCON |= PMU_PCON_NODPD; +} + +/** + * @brief Returns sleep/power-down flags + * @param pPMU : Pointer to PMU register block + * @return Or'ed values of PMU_PCON_SLEEPFLAG and PMU_PCON_DPDFLAG + * @note These indicate that the PMU is setup for entry into a low + * power state on the next WFI() instruction. + */ +STATIC INLINE uint32_t Chip_PMU_GetSleepFlags(LPC_PMU_T *pPMU) +{ + return pPMU->PCON & (PMU_PCON_SLEEPFLAG | PMU_PCON_DPDFLAG); +} + +/** + * @brief Clears sleep/power-down flags + * @param pPMU : Pointer to PMU register block + * @param flags : Or'ed value of PMU_PCON_SLEEPFLAG and PMU_PCON_DPDFLAG + * @return Nothing + * @note Use this function to clear a low power state prior to calling + * WFI(). + */ +STATIC INLINE void Chip_PMU_ClearSleepFlags(LPC_PMU_T *pPMU, uint32_t flags) +{ + pPMU->PCON &= ~flags; +} + +/** + * @brief Sets deep power-down functions + * @param pPMU : Pointer to PMU register block + * @param flags : Or'ed value of PMU_DPDCTRL_* values + * @return Nothing + * @note Some of these functions may need to be set prior to going + * into a low power mode. Note that some calls to this function enable + * functions while others disable it based on the PMU_DPDCTRL_* + * definitions. + */ +STATIC INLINE void Chip_PMU_SetPowerDownControl(LPC_PMU_T *pPMU, uint32_t flags) +{ + pPMU->DPDCTRL |= flags; +} + +/** + * @brief Cleats deep power-down functions + * @param pPMU : Pointer to PMU register block + * @param flags : Or'ed value of PMU_DPDCTRL_* values + * @return Nothing + * @note Some of these functions may need to be cleared prior to going + * into a low power mode. Note that some calls to this function enable + * functions while others disable it based on the PMU_DPDCTRL_* + * definitions. + */ +STATIC INLINE void Chip_PMU_ClearPowerDownControl(LPC_PMU_T *pPMU, uint32_t flags) +{ + pPMU->DPDCTRL &= ~flags; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PMU_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/ring_buffer.h b/source/lpc_chip_11u6x/inc/ring_buffer.h new file mode 100644 index 0000000..8c205fd --- /dev/null +++ b/source/lpc_chip_11u6x/inc/ring_buffer.h @@ -0,0 +1,188 @@ +/* + * @brief Common ring buffer support functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __RING_BUFFER_H_ +#define __RING_BUFFER_H_ + +#include "lpc_types.h" + +/** @defgroup Ring_Buffer CHIP: Simple ring buffer implementation + * @ingroup CHIP_Common + * @{ + */ + +/** + * @brief Ring buffer structure + */ +typedef struct { + void *data; + int count; + int itemSz; + uint32_t head; + uint32_t tail; +} RINGBUFF_T; + +/** + * @def RB_VHEAD(rb) + * volatile typecasted head index + */ +#define RB_VHEAD(rb) (*(volatile uint32_t *) &(rb)->head) + +/** + * @def RB_VTAIL(rb) + * volatile typecasted tail index + */ +#define RB_VTAIL(rb) (*(volatile uint32_t *) &(rb)->tail) + +/** + * @brief Initialize ring buffer + * @param RingBuff : Pointer to ring buffer to initialize + * @param buffer : Pointer to buffer to associate with RingBuff + * @param itemSize : Size of each buffer item size + * @param count : Size of ring buffer + * @note Memory pointed by @a buffer must have correct alignment of + * @a itemSize, and @a count must be a power of 2 and must at + * least be 2 or greater. + * @return Nothing + */ +int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count); + +/** + * @brief Resets the ring buffer to empty + * @param RingBuff : Pointer to ring buffer + * @return Nothing + */ +STATIC INLINE void RingBuffer_Flush(RINGBUFF_T *RingBuff) +{ + RingBuff->head = RingBuff->tail = 0; +} + +/** + * @brief Return size the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return Size of the ring buffer in bytes + */ +STATIC INLINE int RingBuffer_GetSize(RINGBUFF_T *RingBuff) +{ + return RingBuff->count; +} + +/** + * @brief Return number of items in the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return Number of items in the ring buffer + */ +STATIC INLINE int RingBuffer_GetCount(RINGBUFF_T *RingBuff) +{ + return RB_VHEAD(RingBuff) - RB_VTAIL(RingBuff); +} + +/** + * @brief Return number of free items in the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return Number of free items in the ring buffer + */ +STATIC INLINE int RingBuffer_GetFree(RINGBUFF_T *RingBuff) +{ + return RingBuff->count - RingBuffer_GetCount(RingBuff); +} + +/** + * @brief Return number of items in the ring buffer + * @param RingBuff : Pointer to ring buffer + * @return 1 if the ring buffer is full, otherwise 0 + */ +STATIC INLINE int RingBuffer_IsFull(RINGBUFF_T *RingBuff) +{ + return (RingBuffer_GetCount(RingBuff) >= RingBuff->count); +} + +/** + * @brief Return empty status of ring buffer + * @param RingBuff : Pointer to ring buffer + * @return 1 if the ring buffer is empty, otherwise 0 + */ +STATIC INLINE int RingBuffer_IsEmpty(RINGBUFF_T *RingBuff) +{ + return RB_VHEAD(RingBuff) == RB_VTAIL(RingBuff); +} + +/** + * @brief Insert a single item into ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : pointer to item + * @return 1 when successfully inserted, + * 0 on error (Buffer not initialized using + * RingBuffer_Init() or attempted to insert + * when buffer is full) + */ +int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data); + +/** + * @brief Insert an array of items into ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : Pointer to first element of the item array + * @param num : Number of items in the array + * @return number of items successfully inserted, + * 0 on error (Buffer not initialized using + * RingBuffer_Init() or attempted to insert + * when buffer is full) + */ +int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num); + +/** + * @brief Pop an item from the ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : Pointer to memory where popped item be stored + * @return 1 when item popped successfuly onto @a data, + * 0 When error (Buffer not initialized using + * RingBuffer_Init() or attempted to pop item when + * the buffer is empty) + */ +int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data); + +/** + * @brief Pop an array of items from the ring buffer + * @param RingBuff : Pointer to ring buffer + * @param data : Pointer to memory where popped items be stored + * @param num : Max number of items array @a data can hold + * @return Number of items popped onto @a data, + * 0 on error (Buffer not initialized using RingBuffer_Init() + * or attempted to pop when the buffer is empty) + */ +int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num); + + +/** + * @} + */ + +#endif /* __RING_BUFFER_H_ */ diff --git a/source/lpc_chip_11u6x/inc/rom_dma_11u6x.h b/source/lpc_chip_11u6x/inc/rom_dma_11u6x.h new file mode 100644 index 0000000..66ae98d --- /dev/null +++ b/source/lpc_chip_11u6x/inc/rom_dma_11u6x.h @@ -0,0 +1,140 @@ +/* + * @brief LPC11u6x DMA ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROM_DMA_11U6X_H_ +#define __ROM_DMA_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CHIP_DMAROM_11U6X CHIP: LPC11U6X DMA ROM API declarations and functions + * @ingroup ROMAPI_11U6X + * @{ + */ + +/** + * @brief LPC11U6X DMA ROM driver handle structure + */ +typedef void *DMA_HANDLE_T; + +/** + * @brief LPC11U6X DMA ROM driver callback function + * @param res0 : error code + * @param res1 : 0 = INTA is issued, 1 = INTB is issued + */ +typedef void (*DMA_CALLBK_T)(uint32_t res0, uint32_t res1); + +/** + * @brief LPC11U6X DMA ROM event values + */ +#define DMA_EVENT_SW_REQ 0 +#define DMA_EVENT_PERIPH_REQ 1 +#define DMA_EVENT_HW_REQ 2 + +/** + * @brief LPC11U6X DMA ROM hardware trigger values + */ +#define DMA_HWTRIG_BURST_SIZE(n) (n) /*!< Burst size is 2^n, n <= 15 */ +#define DMA_HWTRIG_SRC_BURST_WRAP (1 << 4) /*!< Source burst wrapping enabled */ +#define DMA_HWTRIG_TRIGGER_BURST (1 << 6) /*!< Hardware trigger cause a burst transfer */ + +/** + * @brief LPC11U6X DMA ROM channel configuration structure + */ +typedef struct DMA_CHANNEL { + uint8_t event; /*!< Event type selection for DMA transfer, a value of DMA_EVENT_* types */ + uint8_t hd_trigger; /*!< In case hardware trigger is enabled, OR'ed values of type DMA_HWTRIG_* */ + uint8_t Priority; /*!< Priority level 0 - 7, 0 = lowest, 7 = highest */ + DMA_CALLBK_T callback_func_pt; /*!< Callback function, only invoked when INTA or INTB is enabled */ +} DMA_CHANNEL_T ; + +/** + * @brief LPC11U6X DMA ROM task configuration values + */ +#define DMA_TASK_PINGPONG (1 << 0) /*!< Linked with previous task for Ping_Pong transfer */ +#define DMA_TASK_SWTRIG (1 << 1) /*!< The trigger for this channel is set immediately */ +#define DMA_TASK_CLEARTRIG (1 << 2) /*!< The trigger is cleared when this task is finished */ +#define DMA_TASK_SELINTA (1 << 3) /*!< The IntA flag for this channel will be set when this task is finished */ +#define DMA_TASK_SELINTB (1 << 4) /*!< The IntB flag for this channel will be set when this task is finished */ + +/** + * @brief LPC11U6X DMA ROM data type values + */ +#define DMA_DATA_SIZE(n) (n) /*!< Data width, 0: 8-bit, 1: 16-bit, 2: 32-bit, 3: reserved */ +/* DMA_DATA_SRCINC = 0 : The source address is not incremented for each transfer */ +/* DMA_DATA_SRCINC = 1 : The source address is incremented by the amount specified by Width for each transfer */ +/* DMA_DATA_SRCINC = 2 : The source address is incremented by 2 times the amount specified by Width for each transfer */ +/* DMA_DATA_SRCINC = 3 : The source address is incremented by 4 times the amount specified by Width for each transfer */ +#define DMA_DATA_SRCINC(n) (n << 2) /*!< Source address incrementation */ +/* DMA_DATA_DSTINC = 0 : The destination address is not incremented for each transfer */ +/* DMA_DATA_DSTINC = 1 : The destination address is incremented by the amount specified by Width for each transfer */ +/* DMA_DATA_DSTINC = 2 : The destination address is incremented by 2 times the amount specified by Width for each transfer */ +/* DMA_DATA_DSTINC = 3 : The destination address is incremented by 4 times the amount specified by Width for each transfer */ +#define DMA_DATA_DSTINC(n) (n << 4) /*!< Destination address incrementation */ + +/** + * @brief LPC11U6X DMA ROM task structure + */ +typedef struct DMA_TASK { + uint8_t ch_num; /*!< DMA channel number */ + uint8_t config; /*!< Configuration of this task, OR'ed values of DMA_TASK_* */ + uint8_t data_type; /*!< Data type, OR'ed values of DMA_DATA_* */ + uint16_t data_length; /*!< 0: 1 transfer, 1: 2 transfer, … 1023: 1024 transfers */ + uint32_t src; /*!< Source data end address */ + uint32_t dst; /*!< Destination end address */ + uint32_t task_addr; /*!< the address of RAM for saving this task. Must be 16 butes and aligned on a 16 byte boundary */ +} DMA_TASK_T ; + +/** + * LPC11U6X DMA ROM driver APIs structure + */ +typedef struct DMAD_API { + void (*dma_isr)(DMA_HANDLE_T* handle); + uint32_t (*dma_get_mem_size)( void); + DMA_HANDLE_T* (*dma_setup)( uint32_t base_addr, uint8_t *ram ); + ErrorCode_t (*dma_init)( DMA_HANDLE_T* handle, DMA_CHANNEL_T *channel, DMA_TASK_T *task); + ErrorCode_t (*dma_link)( DMA_HANDLE_T* handle, DMA_TASK_T *task, uint8_t valid); + ErrorCode_t (*dma_set_valid)( DMA_HANDLE_T* handle, uint8_t chl_num); + ErrorCode_t (*dma_pause)( DMA_HANDLE_T* handle, uint8_t chl_num); + ErrorCode_t (*dma_unpause)( DMA_HANDLE_T* handle, uint8_t chl_num); + ErrorCode_t (*dma_abort)( DMA_HANDLE_T* handle, uint8_t chl_num); +} DMAD_API_T ; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROM_DMA_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/rom_i2c_11u6x.h b/source/lpc_chip_11u6x/inc/rom_i2c_11u6x.h new file mode 100644 index 0000000..ba5d4f9 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/rom_i2c_11u6x.h @@ -0,0 +1,124 @@ +/* + * @brief LPC11u6x I2C ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROM_I2C_11U6X_H_ +#define __ROM_I2C_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup CHIP_I2CROM_11U6X CHIP: LPC11U6X I2C ROM API declarations and functions + * @ingroup ROMAPI_11U6X + * @{ + */ + +/** + * @brief LPC11U6X I2C ROM driver handle structure + */ +typedef void *I2C_HANDLE_T; + +/** + * @brief LPC11U6X I2C ROM driver callback function + */ +typedef void (*I2C_CALLBK_T)(uint32_t err_code, uint32_t n); + +/** + * LPC11U6X I2C ROM driver parameter structure + */ +typedef struct I2C_PARAM { + uint32_t num_bytes_send; /*!< No. of bytes to send */ + uint32_t num_bytes_rec; /*!< No. of bytes to receive */ + uint8_t *buffer_ptr_send; /*!< Pointer to send buffer */ + uint8_t *buffer_ptr_rec; /*!< Pointer to receive buffer */ + I2C_CALLBK_T func_pt; /*!< Callback function */ + uint8_t stop_flag; /*!< Stop flag */ + uint8_t dummy[3]; +} I2C_PARAM_T; + +/** + * LPC11U6X I2C ROM driver result structure + */ +typedef struct I2C_RESULT { + uint32_t n_bytes_sent; /*!< No. of bytes sent */ + uint32_t n_bytes_recd; /*!< No. of bytes received */ +} I2C_RESULT_T; + +/** + * LPC11U6X I2C ROM driver modes enum + */ +typedef enum CHIP_I2C_MODE { + IDLE, /*!< IDLE state */ + MASTER_SEND, /*!< Master send state */ + MASTER_RECEIVE, /*!< Master Receive state */ + SLAVE_SEND, /*!< Slave send state */ + SLAVE_RECEIVE /*!< Slave receive state */ +} CHIP_I2C_MODE_T; + +/** + * LPC11U6X I2C ROM driver APIs structure + */ +typedef struct I2CD_API { + /*!< Interrupt Support Routine */ + void (*i2c_isr_handler)(I2C_HANDLE_T *handle); + + /*!< MASTER functions */ + ErrorCode_t (*i2c_master_transmit_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_master_receive_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_master_tx_rx_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_master_transmit_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_master_receive_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_master_tx_rx_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + + /*!< SLAVE functions */ + ErrorCode_t (*i2c_slave_receive_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_slave_transmit_poll)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_slave_receive_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_slave_transmit_intr)(I2C_HANDLE_T *handle, I2C_PARAM_T *param, I2C_RESULT_T *result); + ErrorCode_t (*i2c_set_slave_addr)(I2C_HANDLE_T *handle, uint32_t slave_addr_0_3, uint32_t slave_mask_0_3); + + /*!< OTHER support functions */ + uint32_t (*i2c_get_mem_size)(void); + I2C_HANDLE_T * (*i2c_setup)( uint32_t i2c_base_addr, uint32_t * start_of_ram); + ErrorCode_t (*i2c_set_bitrate)(I2C_HANDLE_T *handle, uint32_t p_clk_in_hz, uint32_t bitrate_in_bps); + uint32_t (*i2c_get_firmware_version)(void); + CHIP_I2C_MODE_T (*i2c_get_status)(I2C_HANDLE_T *handle); +} I2CD_API_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROM_I2C_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/rom_pwr_11u6x.h b/source/lpc_chip_11u6x/inc/rom_pwr_11u6x.h new file mode 100644 index 0000000..1d41955 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/rom_pwr_11u6x.h @@ -0,0 +1,94 @@ +/* + * @brief LPC11u6x Power ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROM_PWR_11U6X_H_ +#define __ROM_PWR_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup PWRROM_11U6X CHIP: LPC11U6X Power ROM API declarations and functions + * @ingroup ROMAPI_11U6X + * @{ + */ + +/** + * @brief Power ROM APIs - set_pll mode options + */ +#define CPU_FREQ_EQU 0 +#define CPU_FREQ_LTE 1 +#define CPU_FREQ_GTE 2 +#define CPU_FREQ_APPROX 3 + +/** + * @brief Power ROM APIs - set_pll response0 options + */ +#define PLL_CMD_SUCCESS 0 +#define PLL_INVALID_FREQ 1 +#define PLL_INVALID_MODE 2 +#define PLL_FREQ_NOT_FOUND 3 +#define PLL_NOT_LOCKED 4 + +/** + * @brief Power ROM APIs - set_power mode options + */ +#define PWR_DEFAULT 0 +#define PWR_CPU_PERFORMANCE 1 +#define PWR_EFFICIENCY 2 +#define PWR_LOW_CURRENT 3 + +/** + * @brief Power ROM APIs - set_power response0 options + */ +#define PWR_CMD_SUCCESS 0 +#define PWR_INVALID_FREQ 1 +#define PWR_INVALID_MODE 2 + +/** + * @brief Power ROM API structure + * The power profile API provides functions to configure the system clock and optimize the + * system setting for lowest power consumption. + */ +typedef struct PWRD_API { + void (*set_pll)(uint32_t cmd[], uint32_t resp[]); /*!< Set PLL function */ + void (*set_power)(uint32_t cmd[], uint32_t resp[]); /*!< Set power function */ +} PWRD_API_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROM_PWR_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/rom_uart_11u6x.h b/source/lpc_chip_11u6x/inc/rom_uart_11u6x.h new file mode 100644 index 0000000..1647688 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/rom_uart_11u6x.h @@ -0,0 +1,180 @@ +/* + * @brief LPC11U6x UART ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROM_UART_11U6X_H_ +#define __ROM_UART_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup UARTROM_11U6X CHIP: LPC11U6X UART ROM API declarations and functions + * @ingroup ROMAPI_11U6X + * @{ + */ + +/** + * @brief UART ROM driver - UART errors in UART configuration used in uart_init function + */ +#define OVERRUN_ERR_EN (1 << 0) /*!< Bit 0: Enable overrun error */ +#define UNDERRUN_ERR_EN (1 << 1) /*!< Bit 1: Enable underrun error */ +#define FRAME_ERR_EN (1 << 2) /*!< Bit 2: enable frame error */ +#define PARITY_ERR_EN (1 << 3) /*!< Bit 3: enable parity error */ +#define RXNOISE_ERR_EN (1 << 4) /*!< Bit 4: enable receive noise error */ + +/** + * Macros for UART errors + */ +/*!< Enable all the UART errors */ +#define ALL_ERR_EN (OVERRUN_ERR_EN | UNDERRUN_ERR_EN | FRAME_ERR_EN | PARITY_ERR_EN | \ + RXNOISE_ERR_EN) +/*!< Disable all the errors */ +#define NO_ERR_EN (0) + +/** + * Transfer mode values in UART parameter structure. + * Used in uart_get_line & uart_put_line function + */ +/*!< 0x00: uart_get_line: stop transfer when the buffer is full */ +/*!< 0x00: uart_put_line: stop transfer when the buffer is empty */ +#define TX_MODE_BUF_EMPTY (0x00) +#define RX_MODE_BUF_FULL (0x00) +/*!< 0x01: uart_get_line: stop transfer when CRLF are received */ +/*!< 0x01: uart_put_line: transfer stopped after reaching \0 and CRLF is sent out after that */ +#define TX_MODE_SZERO_SEND_CRLF (0x01) +#define RX_MODE_CRLF_RECVD (0x01) +/*!< 0x02: uart_get_line: stop transfer when LF are received */ +/*!< 0x02: uart_put_line: transfer stopped after reaching \0. And LF is sent out after that */ +#define TX_MODE_SZERO_SEND_LF (0x02) +#define RX_MODE_LF_RECVD (0x02) +/*!< 0x03: uart_get_line: RESERVED */ +/*!< 0x03: uart_put_line: transfer stopped after reaching \0 */ +#define TX_MODE_SZERO (0x03) + +/** + * @brief UART ROM driver modes + */ +#define DRIVER_MODE_POLLING (0x00) /*!< Polling mode */ +#define DRIVER_MODE_INTERRUPT (0x01) /*!< Interrupt mode */ +#define DRIVER_MODE_DMA (0x02) /*!< DMA mode */ + +/** + * @brief UART ROM driver UART handle + */ +typedef void UART_HANDLE_T; + +/** + * @brief UART ROM driver UART callback function + */ +typedef void (*UART_CALLBK_T)(uint32_t err_code, uint32_t n); + +/** + * @brief UART ROM driver UART DMA callback function + */ +typedef void (*UART_DMA_REQ_T)(uint32_t src_adr, uint32_t dst_adr, uint32_t size); + +/** + * @brief UART ROM driver configutaion structure + */ +typedef struct { + uint32_t sys_clk_in_hz; /*!< System clock in Hz */ + uint32_t baudrate_in_hz; /*!< Baud rate in Hz */ + uint8_t config; /*!< Configuration value */ + /*!< bit1:0 Data Length: 00: 7 bits length, 01: 8 bits length, others: reserved */ + /*!< bit3:2 Parity: 00: No Parity, 01: reserved, 10: Even, 11: Odd */ + /*!< bit4: Stop Bit(s): 0: 1 Stop bit, 1: 2 Stop bits */ + uint8_t sync_mod; /*!< Sync mode settings */ + /*!< bit0: Mode: 0: Asynchronous mode, 1: Synchronous mode */ + /*!< bit1: 0: Un_RXD is sampled on the falling edge of SCLK */ + /*!< 1: Un_RXD is sampled on the rising edge of SCLK */ + /*!< bit2: 0: Start and stop bits are transmitted as in asynchronous mode) */ + /*!< 1: Start and stop bits are not transmitted) */ + /*!< bit3: 0: The UART is a slave in Synchronous mode */ + /*!< 1: The UART is a master in Synchronous mode */ + uint16_t error_en; /*!< Errors to be enabled */ + /*!< bit0: Overrun Errors Enabled */ + /*!< bit1: Underrun Errors Enabled */ + /*!< bit2: FrameErr Errors Enabled */ + /*!< bit3: ParityErr Errors Enabled */ + /*!< bit4: RxNoise Errors Enabled */ +} UART_CONFIG_T; + +/** + * @brief UART ROM driver parameter structure + */ +typedef struct { + uint8_t *buffer; /*!< Pointer to data buffer */ + uint32_t size; /*!< Size of the buffer */ + uint16_t transfer_mode; /*!< Transfer mode settings */ + /*!< 0x00: uart_get_line: stop transfer when the buffer is full */ + /*!< 0x00: uart_put_line: stop transfer when the buffer is empty */ + /*!< 0x01: uart_get_line: stop transfer when CRLF are received */ + /*!< 0x01: uart_put_line: transfer stopped after reaching \0 and CRLF is sent out after that */ + /*!< 0x02: uart_get_line: stop transfer when LF are received */ + /*!< 0x02: uart_put_line: transfer stopped after reaching \0 and LF is sent out after that */ + /*!< 0x03: uart_get_line: RESERVED */ + /*!< 0x03: uart_put_line: transfer stopped after reaching \0 */ + uint16_t driver_mode; /*!< Driver mode */ + /*!< 0x00: Polling mode, function blocked until transfer completes */ + /*!< 0x01: Interrupt mode, function immediately returns, callback invoked when transfer completes */ + /*!< 0x02: DMA mode, in case DMA block is available, DMA req function is called for UART DMA channel setup, then callback function indicate that transfer completes */ + UART_CALLBK_T callback_func_pt; /*!< callback function pointer */ + UART_DMA_REQ_T dma_req_func_pt; /*!< UART DMA channel setup function pointer, not applicable on LPC8xx */ +} UART_PARAM_T; + +/** + * @brief UART ROM driver APIs structure + */ +typedef struct UARTD_API { + /*!< UART Configuration functions */ + uint32_t (*uart_get_mem_size)(void); /*!< Get the memory size needed by one Min UART instance */ + UART_HANDLE_T * (*uart_setup)(uint32_t base_addr, uint8_t * ram); /*!< Setup Min UART instance with provided memory and return the handle to this instance */ + uint32_t (*uart_init)(UART_HANDLE_T *handle, UART_CONFIG_T *set); /*!< Setup baud rate and operation mode for uart, then enable uart */ + + /*!< UART polling functions block until completed */ + uint8_t (*uart_get_char)(UART_HANDLE_T *handle); /*!< Receive one Char from uart. This functions is only returned after Char is received. In case Echo is enabled, the received data is sent out immediately */ + void (*uart_put_char)(UART_HANDLE_T *handle, uint8_t data); /*!< Send one Char through uart. This function is only returned after data is sent */ + uint32_t (*uart_get_line)(UART_HANDLE_T *handle, UART_PARAM_T *param); /*!< Receive multiple bytes from UART */ + uint32_t (*uart_put_line)(UART_HANDLE_T *handle, UART_PARAM_T *param); /*!< Send string (end with \0) or raw data through UART */ + + /*!< UART interrupt functions return immediately and callback when completed */ + void (*uart_isr)(UART_HANDLE_T *handle); /*!< UART interrupt service routine. To use this routine, the corresponding USART interrupt must be enabled. This function is invoked by the user ISR */ +} UARTD_API_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROM_UART_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/romapi_11u6x.h b/source/lpc_chip_11u6x/inc/romapi_11u6x.h new file mode 100644 index 0000000..ef27fef --- /dev/null +++ b/source/lpc_chip_11u6x/inc/romapi_11u6x.h @@ -0,0 +1,108 @@ +/* + * @brief LPC11xx ROM API declarations and functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROMAPI_11U6X_H_ +#define __ROMAPI_11U6X_H_ + +#include "iap.h" +#include "error.h" +#include "rom_dma_11u6x.h" +#include "rom_i2c_11u6x.h" +#include "rom_pwr_11u6x.h" +#include "rom_uart_11u6x.h" +#include "romdiv_11u6x.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup ROMAPI_11U6X CHIP: LPC11U6X ROM API declarations and functions + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief LPC11U6X High level ROM API structure + */ +typedef struct { + const uint32_t usbdApiBase; /*!< USBD API function table base address */ + const uint32_t reserved0; /*!< Reserved */ + const uint32_t reserved1; /*!< Reserved */ + const PWRD_API_T *pPWRD; /*!< Power API function table base address */ + const ROM_DIV_API_T *divApiBase; /*!< Divider API function table base address */ + const I2CD_API_T *pI2CD; /*!< I2C driver API function table base address */ + const DMAD_API_T *pDMAD; /*!< DMA driver API function table base address */ + const uint32_t reserved2; /*!< Reserved */ + const uint32_t reserved3; /*!< Reserved */ + const UARTD_API_T *pUARTND; /*!< USART 1/2/3/4 driver API function table base address */ + const uint32_t reserved4; /*!< Reserved */ + const UARTD_API_T *pUART0D; /*!< USART 0 driver API function table base address */ +} LPC_ROM_API_T; + +/* Pointer to ROM API function address */ +#define LPC_ROM_API_BASE_LOC 0x1FFF1FF8 +#define LPC_ROM_API (*(LPC_ROM_API_T * *) LPC_ROM_API_BASE_LOC) + +/* Pointer to @ref PWRD_API_T functions in ROM */ +#define LPC_PWRD_API ((LPC_ROM_API)->pPWRD) + +/* Pointer to @ref I2CD_API_T functions in ROM */ +#define LPC_I2CD_API ((LPC_ROM_API)->pI2CD) + +/* Pointer to @ref UARTD_API_T functions in ROM for UART 0 */ +#define LPC_UART0D_API ((LPC_ROM_API)->pUART0D) + +/* Pointer to @ref UARTD_API_T functions in ROM for UARTS 1-4 */ +#define LPC_UARTND_API ((LPC_ROM_API)->pUARTND) + +/* Pointer to @ref DMAD_API_T functions in ROM for DMA */ +#define LPC_DMAD_API ((LPC_ROM_API)->pDMAD) + +/* Pointer to ROM IAP entry functions */ +#define IAP_ENTRY_LOCATION 0X1FFF1FF1 + +/** + * @brief LPC11U6X IAP_ENTRY API function type + */ +static INLINE void iap_entry(unsigned int cmd_param[5], unsigned int status_result[4]) +{ + ((IAP_ENTRY_T) IAP_ENTRY_LOCATION)(cmd_param, status_result); +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROMAPI_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/romdiv_11u6x.h b/source/lpc_chip_11u6x/inc/romdiv_11u6x.h new file mode 100644 index 0000000..11b69d1 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/romdiv_11u6x.h @@ -0,0 +1,81 @@ +/* + * @brief Routines to overload "/" and "%" operator in C using ROM based divider library + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __ROMDIV_11U6X_H_ +#define __ROMDIV_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup ROMAPI_DIV_11U6X ROM divider API declarations + * @ingroup ROMAPI_11U6X + * The ROM-based 32-bit integer division routines are available for all LPC11U6x. + * These routines are performance optimized and reduce application code space. As + * part of chip library these routines overload “/†and “%†operators in C. + * @{ + */ + +/** + * @brief Structure containing signed integer divider return data. + */ +typedef struct { + int quot; /*!< Quotient */ + int rem; /*!< Reminder */ +} IDIV_RETURN_T; + +/** + * @brief Structure containing unsigned integer divider return data. + */ +typedef struct { + unsigned quot; /*!< Quotient */ + unsigned rem; /*!< Reminder */ +} UIDIV_RETURN_T; + +/** + * @brief ROM divider API Structure. + */ +typedef struct { + int (*sidiv)(int numerator, int denominator); /*!< Signed integer division */ + unsigned (*uidiv)(unsigned numerator, unsigned denominator); /*!< Unsigned integer division */ + IDIV_RETURN_T (*sidivmod)(int numerator, int denominator); /*!< Signed integer division with remainder */ + UIDIV_RETURN_T (*uidivmod)(unsigned numerator, unsigned denominator); /*!< Unsigned integer division with remainder */ +} ROM_DIV_API_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ROMDIV_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/rtc_11u6x.h b/source/lpc_chip_11u6x/inc/rtc_11u6x.h new file mode 100644 index 0000000..a208a87 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/rtc_11u6x.h @@ -0,0 +1,302 @@ +/* + * @brief LPC11u6x RTC chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __RTC_11U6X_H_ +#define __RTC_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup RTC_11U6X CHIP: LPC11u6x RTC driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief LPC11u6x RTC register block structure + */ +typedef struct { /*!< RTC */ + __IO uint32_t CTRL; /*!< RTC control register */ + __IO uint32_t MATCH; /*!< PRTC match (alarm) register */ + __IO uint32_t COUNT; /*!< RTC counter register */ + __IO uint32_t WAKE; /*!< RTC high-resolution/wake-up timer control register */ +} LPC_RTC_T; + +/* CTRL register defniitions */ +#define RTC_CTRL_SWRESET (1 << 0) /*!< Apply reset to RTC */ +#define RTC_CTRL_OFD (1 << 1) /*!< Oscillator fail detect status (failed bit) */ +#define RTC_CTRL_ALARM1HZ (1 << 2) /*!< RTC 1 Hz timer alarm flag status (match) bit */ +#define RTC_CTRL_WAKE1KHZ (1 << 3) /*!< RTC 1 kHz timer wake-up flag status (timeout) bit */ +#define RTC_CTRL_ALARMDPD_EN (1 << 4) /*!< RTC 1 Hz timer alarm for Deep power-down enable bit */ +#define RTC_CTRL_WAKEDPD_EN (1 << 5) /*!< RTC 1 kHz timer wake-up for Deep power-down enable bit */ +#define RTC_CTRL_RTC1KHZ_EN (1 << 6) /*!< RTC 1 kHz clock enable bit */ +#define RTC_CTRL_RTC_EN (1 << 7) /*!< RTC enable bit */ + +/** + * @brief Initialize the RTC peripheral + * @param pRTC : RTC peripheral selected + * @return None + */ +void Chip_RTC_Init(LPC_RTC_T *pRTC); + +/** + * @brief De-initialize the RTC peripheral + * @param pRTC : RTC peripheral selected + * @return None + */ +void Chip_RTC_DeInit(LPC_RTC_T *pRTC); + +/** + * @brief Enable RTC options + * @param pRTC : The base address of RTC block + * @param flags : And OR'ed value of RTC_CTRL_* definitions to enable + * @return Nothing + * @note You can enable multiple RTC options at once using this function + * by OR'ing them together. It is recommended to only use the + * RTC_CTRL_ALARMDPD_EN, RTC_CTRL_WAKEDPD_EN, RTC_CTRL_RTC1KHZ_EN, and + * RTC_CTRL_RTC_EN flags with this function. + */ +STATIC INLINE void Chip_RTC_EnableOptions(LPC_RTC_T *pRTC, uint32_t flags) +{ + pRTC->CTRL |= flags; +} + +/** + * @brief Disable RTC options + * @param pRTC : The base address of RTC block + * @param flags : And OR'ed value of RTC_CTRL_* definitions to disable + * @return Nothing + * @note You can enable multiple RTC options at once using this function + * by OR'ing them together. It is recommended to only use the + * RTC_CTRL_ALARMDPD_EN, RTC_CTRL_WAKEDPD_EN, RTC_CTRL_RTC1KHZ_EN, and + * RTC_CTRL_RTC_EN flags with this function. + */ +STATIC INLINE void Chip_RTC_DisableOptions(LPC_RTC_T *pRTC, uint32_t flags) +{ + pRTC->CTRL &= ~flags; +} + +/** + * @brief Reset RTC + * @param pRTC : The base address of RTC block + * @return Nothing + * @note The RTC state will be returned to it's default. + */ +STATIC INLINE void Chip_RTC_Reset(LPC_RTC_T *pRTC) +{ + Chip_RTC_EnableOptions(pRTC, RTC_CTRL_SWRESET); + Chip_RTC_DisableOptions(pRTC, RTC_CTRL_SWRESET); +} + +/** + * @brief Enables the RTC + * @param pRTC : The base address of RTC block + * @return Nothing + * @note You can also use Chip_RTC_EnableOptions() with the + * RTC_CTRL_RTC_EN flag to enable the RTC. + */ +STATIC INLINE void Chip_RTC_Enable(LPC_RTC_T *pRTC) +{ + Chip_RTC_EnableOptions(pRTC, RTC_CTRL_RTC_EN); +} + +/** + * @brief Disables the RTC + * @param pRTC : The base address of RTC block + * @return Nothing + * @note You can also use Chip_RTC_DisableOptions() with the + * RTC_CTRL_RTC_EN flag to enable the RTC. + */ +STATIC INLINE void Chip_RTC_Disable(LPC_RTC_T *pRTC) +{ + Chip_RTC_DisableOptions(pRTC, RTC_CTRL_RTC_EN); +} + +/** + * @brief Enables the RTC 1KHz high resolution timer + * @param pRTC : The base address of RTC block + * @return Nothing + * @note You can also use Chip_RTC_EnableOptions() with the + * RTC_CTRL_RTC1KHZ_EN flag to enable the high resolution + * timer. + */ +STATIC INLINE void Chip_RTC_Enable1KHZ(LPC_RTC_T *pRTC) +{ + Chip_RTC_EnableOptions(pRTC, RTC_CTRL_RTC1KHZ_EN); +} + +/** + * @brief Disables the RTC 1KHz high resolution timer + * @param pRTC : The base address of RTC block + * @return Nothing + * @note You can also use Chip_RTC_DisableOptions() with the + * RTC_CTRL_RTC1KHZ_EN flag to disable the high resolution + * timer. + */ +STATIC INLINE void Chip_RTC_Disable1KHZ(LPC_RTC_T *pRTC) +{ + Chip_RTC_DisableOptions(pRTC, RTC_CTRL_RTC1KHZ_EN); +} + +/** + * @brief Enables selected RTC wakeup events + * @param pRTC : The base address of RTC block + * @param ints : Wakeup events to enable + * @return Nothing + * @note Select either one or both (OR'ed) RTC_CTRL_ALARMDPD_EN + * and RTC_CTRL_WAKEDPD_EN values to enabled. You can also + * use Chip_RTC_EnableOptions() with the flags to enable + * the events. + */ +STATIC INLINE void Chip_RTC_EnableWakeup(LPC_RTC_T *pRTC, uint32_t ints) +{ + Chip_RTC_EnableOptions(pRTC, ints); +} + +/** + * @brief Disables selected RTC wakeup events + * @param pRTC : The base address of RTC block + * @param ints : Wakeup events to disable + * @return Nothing + * @note Select either one or both (OR'ed) RTC_CTRL_ALARMDPD_EN + * and RTC_CTRL_WAKEDPD_EN values to disabled. You can also + * use Chip_RTC_DisableOptions() with the flags to disable + * the events. + */ +STATIC INLINE void Chip_RTC_DisableWakeup(LPC_RTC_T *pRTC, uint32_t ints) +{ + Chip_RTC_DisableOptions(pRTC, ints); +} + +/** + * @brief Clears latched RTC statuses + * @param pRTC : The base address of RTC block + * @param stsMask : OR'ed status bits to clear + * @return Nothing + * @note Use and OR'ed stsMask value of RTC_CTRL_OFD, RTC_CTRL_ALARM1HZ, + * and RTC_CTRL_WAKE1KHZ to clear specific RTC states. + */ +STATIC INLINE uint32_t Chip_RTC_ClearStatus(LPC_RTC_T *pRTC, uint32_t stsMask) +{ + return pRTC->CTRL; +} + +/** + * @brief Return RTC control/status register + * @param pRTC : The base address of RTC block + * @return The current RTC control/status register + * @note Mask the return value with a RTC_CTRL_* definitions to determine + * which bits are set. For example, mask the return value with + * RTC_CTRL_ALARM1HZ to determine if the alarm interrupt is pending. + */ +STATIC INLINE uint32_t Chip_RTC_GetStatus(LPC_RTC_T *pRTC) +{ + return pRTC->CTRL; +} + +/** + * @brief Set RTC match value for alarm status/interrupt + * @param pRTC : The base address of RTC block + * @param count : Alarm event time + * @return Nothing + */ +STATIC INLINE void Chip_RTC_SetAlarm(LPC_RTC_T *pRTC, uint32_t count) +{ + pRTC->MATCH = count; +} + +/** + * @brief Return the RTC match value used for alarm status/interrupt + * @param pRTC : The base address of RTC block + * @return Alarm event time + */ +STATIC INLINE uint32_t Chip_RTC_GetAlarm(LPC_RTC_T *pRTC) +{ + return pRTC->MATCH; +} + +/** + * @brief Set RTC match count for 1 second timer count + * @param pRTC : The base address of RTC block + * @param count : Initial count to set + * @return Nothing + * @note Only write to this register when the RTC_CTRL_RTC_EN bit in + * the CTRL Register is 0. The counter increments one second + * after the RTC_CTRL_RTC_EN bit is set. + */ +STATIC INLINE void Chip_RTC_SetCount(LPC_RTC_T *pRTC, uint32_t count) +{ + pRTC->COUNT = count; +} + +/** + * @brief Get current RTC 1 second timer count + * @param pRTC : The base address of RTC block + * @return current RTC 1 second timer count + */ +STATIC INLINE uint32_t Chip_RTC_GetCount(LPC_RTC_T *pRTC) +{ + return pRTC->COUNT; +} + +/** + * @brief Set RTC wake count countdown value (in mS ticks) + * @param pRTC : The base address of RTC block + * @param count : wakeup time in milliSeconds + * @return Nothing + * @note A write pre-loads a start count value into the wake-up + * timer and initializes a count-down sequence. + */ +STATIC INLINE void Chip_RTC_SetWake(LPC_RTC_T *pRTC, uint16_t count) +{ + pRTC->WAKE = count; +} + +/** + * @brief Get RTC wake count countdown value + * @param pRTC : The base address of RTC block + * @return current RTC wake count countdown value (in mS) + */ +STATIC INLINE uint16_t Chip_RTC_GetWake(LPC_RTC_T *pRTC) +{ + return pRTC->WAKE; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __RTC_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/sct_11u6x.h b/source/lpc_chip_11u6x/inc/sct_11u6x.h new file mode 100644 index 0000000..292bc4e --- /dev/null +++ b/source/lpc_chip_11u6x/inc/sct_11u6x.h @@ -0,0 +1,440 @@ +/* + * @brief LPC11u6x State Configurable Timer (SCT) Chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SCT_11U6X_H_ +#define __SCT_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SCT_11U6X CHIP: LPC11u6x State Configurable Timer driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/* + * @brief SCT Module configuration + */ +#define CONFIG_SCT_nEV (6) /*!< Number of events */ +#define CONFIG_SCT_nRG (5) /*!< Number of match/compare registers */ +#define CONFIG_SCT_nOU (4) /*!< Number of outputs */ + +/** + * @brief State Configurable Timer register block structure + */ +typedef struct { + __IO uint32_t CONFIG; /*!< Configuration Register */ + union { + __IO uint32_t CTRL_U; /*!< Control Register */ + struct { + __IO uint16_t CTRL_L; /*!< Low control register */ + __IO uint16_t CTRL_H; /*!< High control register */ + }; + + }; + + union { + __IO uint32_t LIMIT; /*!< limit Register */ + struct { + __IO uint16_t LIMIT_L; /*!< limit register for counter L */ + __IO uint16_t LIMIT_H; /*!< limit register for counter H */ + }; + + }; + + union { + __IO uint32_t HALT; /*!< Halt Register */ + struct { + __IO uint16_t HALT_L; /*!< halt register for counter L */ + __IO uint16_t HALT_H; /*!< halt register for counter H */ + }; + + }; + + union { + __IO uint32_t STOP; /*!< Stop Register */ + struct { + __IO uint16_t STOP_L; /*!< stop register for counter L */ + __IO uint16_t STOP_H; /*!< stop register for counter H */ + }; + + }; + + union { + __IO uint32_t START; /*!< start Register */ + struct { + __IO uint16_t START_L; /*!< start register for counter L */ + __IO uint16_t START_H; /*!< start register for counter H */ + }; + + }; + + uint32_t RESERVED1[10]; /*!< 0x03C reserved */ + union { + __IO uint32_t COUNT_U; /*!< counter register */ + struct { + __IO uint16_t COUNT_L; /*!< counter register for counter L */ + __IO uint16_t COUNT_H; /*!< counter register for counter H */ + }; + + }; + + union { + __IO uint32_t STATE; /*!< State register */ + struct { + __IO uint16_t STATE_L; /*!< state register for counter L */ + __IO uint16_t STATE_H; /*!< state register for counter H */ + }; + + }; + + __I uint32_t INPUT; /*!< input register */ + union { + __IO uint32_t REGMODE; /*!< RegMode register */ + struct { + __IO uint16_t REGMODE_L; /*!< match - capture registers mode register L */ + __IO uint16_t REGMODE_H; /*!< match - capture registers mode register H */ + }; + + }; + + __IO uint32_t OUTPUT; /*!< output register */ + __IO uint32_t OUTPUTDIRCTRL; /*!< output counter direction Control Register */ + __IO uint32_t RES; /*!< conflict resolution register */ + __IO uint32_t DMA0REQUEST; /*!< DMA0 Request Register */ + __IO uint32_t DMA1REQUEST; /*!< DMA1 Request Register */ + uint32_t RESERVED2[35]; + __IO uint32_t EVEN; /*!< event enable register */ + __IO uint32_t EVFLAG; /*!< event flag register */ + __IO uint32_t CONEN; /*!< conflict enable register */ + __IO uint32_t CONFLAG; /*!< conflict flag register */ + union { + __IO union { /*!< ... Match / Capture value */ + uint32_t U; /*!< SCTMATCH[i].U Unified 32-bit register */ + struct { + uint16_t L; /*!< SCTMATCH[i].L Access to L value */ + uint16_t H; /*!< SCTMATCH[i].H Access to H value */ + }; + + } MATCH[CONFIG_SCT_nRG]; + + __I union { + uint32_t U; /*!< SCTCAP[i].U Unified 32-bit register */ + struct { + uint16_t L; /*!< SCTCAP[i].L Access to L value */ + uint16_t H; /*!< SCTCAP[i].H Access to H value */ + }; + + } CAP[CONFIG_SCT_nRG]; + + }; + + uint32_t RESERVED3[64 - CONFIG_SCT_nRG]; /*!< ...-0x1FC reserved */ + + union { + __IO union { /*!< ... Match reload value */ + uint32_t U; /*!< MATCHREL[i].U Unified 32-bit register */ + struct { + uint16_t L; /*!< MATCHREL[i].L Access to L value */ + uint16_t H; /*!< MATCHREL[i].H Access to H value */ + }; + + } MATCHREL[CONFIG_SCT_nRG]; + + __I union { + uint32_t U; /*!< CAPCTRL[i].U Unified 32-bit register */ + struct { + uint16_t L; /*!< CAPCTRL[i].L Access to L value */ + uint16_t H; /*!< CAPCTRL[i].H Access to H value */ + }; + + } CAPCTRL[CONFIG_SCT_nRG]; + + }; + + uint32_t RESERVED4[64 - CONFIG_SCT_nRG]; /*!< ...-0x2FC reserved */ + + __IO struct { /*!< SCTEVENT[i].STATE / SCTEVENT[i].CTRL*/ + uint32_t STATE; /*!< Event State Register */ + uint32_t CTRL; /*!< Event Control Register */ + } EVENT[CONFIG_SCT_nEV]; + + uint32_t RESERVED9[128 - 2 * CONFIG_SCT_nEV]; /*!< ...-0x4FC reserved */ + __IO struct { /*!< SCTOUT[i].SET / SCTOUT[i].CLR */ + uint32_t SET; /*!< Output n Set Register */ + uint32_t CLR; /*!< Output n Clear Register */ + } OUT[CONFIG_SCT_nOU]; + +} LPC_SCT_T; + +/* + * @brief Macro defines for SCT configuration register + */ +#define SCT_CONFIG_16BIT_COUNTER 0x00000000 /*!< Operate as 2 16-bit counters */ +#define SCT_CONFIG_32BIT_COUNTER 0x00000001 /*!< Operate as 1 32-bit counter */ + +#define SCT_CONFIG_CLKMODE_BUSCLK (0x0 << 1) /*!< Bus clock */ +#define SCT_CONFIG_CLKMODE_SCTCLK (0x1 << 1) /*!< SCT clock */ +#define SCT_CONFIG_CLKMODE_INCLK (0x2 << 1) /*!< Input clock selected in CLKSEL field */ +#define SCT_CONFIG_CLKMODE_INEDGECLK (0x3 << 1) /*!< Input clock edge selected in CLKSEL field */ + +#define SCT_CONFIG_NORELOADL_U (0x1 << 7) /*!< Operate as 1 32-bit counter */ +#define SCT_CONFIG_NORELOADH (0x1 << 8) /*!< Operate as 1 32-bit counter */ + +/* + * @brief Macro defines for SCT control register + */ +#define COUNTUP_TO_LIMIT_THEN_CLEAR_TO_ZERO 0 /*!< Direction for low or unified counter */ +#define COUNTUP_TO LIMIT_THEN_COUNTDOWN_TO_ZERO 1 + +#define SCT_CTRL_STOP_L (1 << 1) /*!< Stop low counter */ +#define SCT_CTRL_HALT_L (1 << 2) /*!< Halt low counter */ +#define SCT_CTRL_CLRCTR_L (1 << 3) /*!< Clear low or unified counter */ +#define SCT_CTRL_BIDIR_L(x) (((x) & 0x01) << 4) /*!< Bidirectional bit */ +#define SCT_CTRL_PRE_L(x) (((x) & 0xFF) << 5) /*!< Prescale clock for low or unified counter */ + +#define COUNTUP_TO_LIMIT_THEN_CLEAR_TO_ZERO 0 /*!< Direction for high counter */ +#define COUNTUP_TO LIMIT_THEN_COUNTDOWN_TO_ZERO 1 +#define SCT_CTRL_STOP_H (1 << 17) /*!< Stop high counter */ +#define SCT_CTRL_HALT_H (1 << 18) /*!< Halt high counter */ +#define SCT_CTRL_CLRCTR_H (1 << 19) /*!< Clear high counter */ +#define SCT_CTRL_BIDIR_H(x) (((x) & 0x01) << 20) +#define SCT_CTRL_PRE_H(x) (((x) & 0xFF) << 21) /*!< Prescale clock for high counter */ + +/* + * @brief Macro defines for SCT Conflict resolution register + */ +#define SCT_RES_NOCHANGE (0) +#define SCT_RES_SET_OUTPUT (1) +#define SCT_RES_CLEAR_OUTPUT (2) +#define SCT_RES_TOGGLE_OUTPUT (3) + +/** + * SCT Match register values enum + */ +typedef enum CHIP_SCT_MATCH_REG { + SCT_MATCH_0 = 0, /*!< SCT Match register 0 */ + SCT_MATCH_1 = 1, /*!< SCT Match register 1 */ + SCT_MATCH_2 = 2, /*!< SCT Match register 2 */ + SCT_MATCH_3 = 3, /*!< SCT Match register 3 */ + SCT_MATCH_4 = 4 /*!< SCT Match register 4 */ +} CHIP_SCT_MATCH_REG_T; + +/** + * SCT Event values enum + */ +typedef enum CHIP_SCT_EVENT { + SCT_EVT_0 = (1 << 0), /*!< Event 0 */ + SCT_EVT_1 = (1 << 1), /*!< Event 1 */ + SCT_EVT_2 = (1 << 2), /*!< Event 2 */ + SCT_EVT_3 = (1 << 3), /*!< Event 3 */ + SCT_EVT_4 = (1 << 4), /*!< Event 4 */ + SCT_EVT_5 = (1 << 5) /*!< Event 5 */ +} CHIP_SCT_EVENT_T; + +/** + * @brief Configures the State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param value : The 32-bit CONFIG register value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_Config(LPC_SCT_T *pSCT, uint32_t value) +{ + pSCT->CONFIG = value; +} + +/** + * @brief Set or Clear the Control register + * @param pSCT : Pointer to SCT register block + * @param value : SCT Control register value + * @param ena : ENABLE - To set the fields specified by value + * : DISABLE - To clear the field specified by value + * @return Nothing + * Set or clear the control register bits as specified by the \a value + * parameter. If \a ena is set to ENABLE, the mentioned register fields + * will be set. If \a ena is set to DISABLE, the mentioned register + * fields will be cleared + */ +void Chip_SCT_SetClrControl(LPC_SCT_T *pSCT, uint32_t value, FunctionalState ena); + +/** + * @brief Set the conflict resolution + * @param pSCT : Pointer to SCT register block + * @param outnum : Output number + * @param value : Output value + * - SCT_RES_NOCHANGE :No change + * - SCT_RES_SET_OUTPUT :Set output + * - SCT_RES_CLEAR_OUTPUT :Clear output + * - SCT_RES_TOGGLE_OUTPUT :Toggle output + * : SCT_RES_NOCHANGE + * : DISABLE - To clear the field specified by value + * @return Nothing + * Set conflict resolution for the output \a outnum + */ +void Chip_SCT_SetConflictResolution(LPC_SCT_T *pSCT, uint8_t outnum, uint8_t value); + +/** + * @brief Set unified count value in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param count : The 32-bit count value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_SetCount(LPC_SCT_T *pSCT, uint32_t count) +{ + pSCT->COUNT_U = count; +} + +/** + * @brief Set lower count value in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param count : The 16-bit count value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_SetCountL(LPC_SCT_T *pSCT, uint16_t count) +{ + pSCT->COUNT_L = count; +} + +/** + * @brief Set higher count value in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param count : The 16-bit count value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_SetCountH(LPC_SCT_T *pSCT, uint16_t count) +{ + pSCT->COUNT_H = count; +} + +/** + * @brief Set unified match count value in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param n : Match register value + * @param value : The 32-bit match count value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_SetMatchCount(LPC_SCT_T *pSCT, CHIP_SCT_MATCH_REG_T n, uint32_t value) +{ + pSCT->MATCH[n].U = value; +} + +/** + * @brief Set unified match reload count value in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param n : Match register value + * @param value : The 32-bit match count reload value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_SetMatchReload(LPC_SCT_T *pSCT, CHIP_SCT_MATCH_REG_T n, uint32_t value) +{ + pSCT->MATCHREL[n].U = value; +} + +/** + * @brief Enable the interrupt for the specified event in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param evt : Event value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_EnableEventInt(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_T evt) +{ + pSCT->EVEN |= evt; +} + +/** + * @brief Disable the interrupt for the specified event in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param evt : Event value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_DisableEventInt(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_T evt) +{ + pSCT->EVEN &= ~(evt); +} + +/** + * @brief Clear the specified event flag in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param evt : Event value + * @return Nothing + */ +STATIC INLINE void Chip_SCT_ClearEventFlag(LPC_SCT_T *pSCT, CHIP_SCT_EVENT_T evt) +{ + pSCT->EVFLAG |= evt; +} + +/** + * @brief Set control register in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param value : Value (ORed value of SCT_CTRL_* bits) + * @return Nothing + */ +STATIC INLINE void Chip_SCT_SetControl(LPC_SCT_T *pSCT, uint32_t value) +{ + pSCT->CTRL_U |= value; +} + +/** + * @brief Clear control register in State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @param value : Value (ORed value of SCT_CTRL_* bits) + * @return Nothing + */ +STATIC INLINE void Chip_SCT_ClearControl(LPC_SCT_T *pSCT, uint32_t value) +{ + pSCT->CTRL_U &= ~(value); +} + +/** + * @brief Initializes the State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @return Nothing + */ +void Chip_SCT_Init(LPC_SCT_T *pSCT); + +/** + * @brief Deinitializes the State Configurable Timer + * @param pSCT : The base of SCT peripheral on the chip + * @return Nothing + */ +void Chip_SCT_DeInit(LPC_SCT_T *pSCT); + +/** + * @} + */ + +#ifdef __cplusplus +} + +#endif + +#endif /* __SCT_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/ssp_11u6x.h b/source/lpc_chip_11u6x/inc/ssp_11u6x.h new file mode 100644 index 0000000..66798b3 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/ssp_11u6x.h @@ -0,0 +1,572 @@ +/* + * @brief LPC11u6x SSP Registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SSP_11U6X_H_ +#define __SSP_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SSP_11U6X CHIP: LPC11u6x SSP register block and driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief SSP register block structure + */ +typedef struct { /*!< SSPn Structure */ + __IO uint32_t CR0; /*!< Control Register 0. Selects the serial clock rate, bus type, and data size. */ + __IO uint32_t CR1; /*!< Control Register 1. Selects master/slave and other modes. */ + __IO uint32_t DR; /*!< Data Register. Writes fill the transmit FIFO, and reads empty the receive FIFO. */ + __I uint32_t SR; /*!< Status Register */ + __IO uint32_t CPSR; /*!< Clock Prescale Register */ + __IO uint32_t IMSC; /*!< Interrupt Mask Set and Clear Register */ + __I uint32_t RIS; /*!< Raw Interrupt Status Register */ + __I uint32_t MIS; /*!< Masked Interrupt Status Register */ + __O uint32_t ICR; /*!< SSPICR Interrupt Clear Register */ + __O uint32_t DMACR; /*!< DMA control Register */ +} LPC_SSP_T; + +/** + * Macro defines for CR0 register + */ + +/** SSP data size select, must be 4 bits to 16 bits */ +#define SSP_CR0_DSS(n) ((uint32_t) ((n) & 0xF)) +/** SSP control 0 Motorola SPI mode */ +#define SSP_CR0_FRF_SPI ((uint32_t) (0 << 4)) +/** SSP control 0 TI synchronous serial mode */ +#define SSP_CR0_FRF_TI ((uint32_t) (1 << 4)) +/** SSP control 0 National Micro-wire mode */ +#define SSP_CR0_FRF_MICROWIRE ((uint32_t) (2 << 4)) +/** SPI clock polarity bit (used in SPI mode only), (1) = maintains the + bus clock high between frames, (0) = low */ +#define SSP_CR0_CPOL_LO ((uint32_t) (0)) +#define SSP_CR0_CPOL_HI ((uint32_t) (1 << 6)) +/** SPI clock out phase bit (used in SPI mode only), (1) = captures data + on the second clock transition of the frame, (0) = first */ +#define SSP_CR0_CPHA_FIRST ((uint32_t) (0)) +#define SSP_CR0_CPHA_SECOND ((uint32_t) (1 << 7)) +/** SSP serial clock rate value load macro, divider rate is + PERIPH_CLK / (cpsr * (SCR + 1)) */ +#define SSP_CR0_SCR(n) ((uint32_t) ((n & 0xFF) << 8)) +/** SSP CR0 bit mask */ +#define SSP_CR0_BITMASK ((uint32_t) (0xFFFF)) +/** SSP CR0 bit mask */ +#define SSP_CR0_BITMASK ((uint32_t) (0xFFFF)) +/** SSP serial clock rate value load macro, divider rate is + PERIPH_CLK / (cpsr * (SCR + 1)) */ +#define SSP_CR0_SCR(n) ((uint32_t) ((n & 0xFF) << 8)) + +/** + * Macro defines for CR1 register + */ + +/** SSP control 1 loopback mode enable bit */ +#define SSP_CR1_LBM_EN ((uint32_t) (1 << 0)) +/** SSP control 1 enable bit */ +#define SSP_CR1_SSP_EN ((uint32_t) (1 << 1)) +/** SSP control 1 slave enable */ +#define SSP_CR1_SLAVE_EN ((uint32_t) (1 << 2)) +#define SSP_CR1_MASTER_EN ((uint32_t) (0)) +/** SSP control 1 slave out disable bit, disables transmit line in slave + mode */ +#define SSP_CR1_SO_DISABLE ((uint32_t) (1 << 3)) +/** SSP CR1 bit mask */ +#define SSP_CR1_BITMASK ((uint32_t) (0x0F)) + +/** SSP CPSR bit mask */ +#define SSP_CPSR_BITMASK ((uint32_t) (0xFF)) +/** + * Macro defines for DR register + */ + +/** SSP data bit mask */ +#define SSP_DR_BITMASK(n) ((n) & 0xFFFF) + +/** + * Macro defines for SR register + */ + +/** SSP SR bit mask */ +#define SSP_SR_BITMASK ((uint32_t) (0x1F)) + +/** ICR bit mask */ +#define SSP_ICR_BITMASK ((uint32_t) (0x03)) + +/** + * @brief SSP Type of Status + */ +typedef enum _SSP_STATUS { + SSP_STAT_TFE = ((uint32_t)(1 << 0)),/**< TX FIFO Empty */ + SSP_STAT_TNF = ((uint32_t)(1 << 1)),/**< TX FIFO not full */ + SSP_STAT_RNE = ((uint32_t)(1 << 2)),/**< RX FIFO not empty */ + SSP_STAT_RFF = ((uint32_t)(1 << 3)),/**< RX FIFO full */ + SSP_STAT_BSY = ((uint32_t)(1 << 4)),/**< SSP Busy */ +} SSP_STATUS_T; + +/** + * @brief SSP Type of Interrupt Mask + */ +typedef enum _SSP_INTMASK { + SSP_RORIM = ((uint32_t)(1 << 0)), /**< Overun */ + SSP_RTIM = ((uint32_t)(1 << 1)),/**< TimeOut */ + SSP_RXIM = ((uint32_t)(1 << 2)),/**< Rx FIFO is at least half full */ + SSP_TXIM = ((uint32_t)(1 << 3)),/**< Tx FIFO is at least half empty */ + SSP_INT_MASK_BITMASK = ((uint32_t)(0xF)), +} SSP_INTMASK_T; + +/** + * @brief SSP Type of Mask Interrupt Status + */ +typedef enum _SSP_MASKINTSTATUS { + SSP_RORMIS = ((uint32_t)(1 << 0)), /**< Overun */ + SSP_RTMIS = ((uint32_t)(1 << 1)), /**< TimeOut */ + SSP_RXMIS = ((uint32_t)(1 << 2)), /**< Rx FIFO is at least half full */ + SSP_TXMIS = ((uint32_t)(1 << 3)), /**< Tx FIFO is at least half empty */ + SSP_MASK_INT_STAT_BITMASK = ((uint32_t)(0xF)), +} SSP_MASKINTSTATUS_T; + +/** + * @brief SSP Type of Raw Interrupt Status + */ +typedef enum _SSP_RAWINTSTATUS { + SSP_RORRIS = ((uint32_t)(1 << 0)), /**< Overun */ + SSP_RTRIS = ((uint32_t)(1 << 1)), /**< TimeOut */ + SSP_RXRIS = ((uint32_t)(1 << 2)), /**< Rx FIFO is at least half full */ + SSP_TXRIS = ((uint32_t)(1 << 3)), /**< Tx FIFO is at least half empty */ + SSP_RAW_INT_STAT_BITMASK = ((uint32_t)(0xF)), +} SSP_RAWINTSTATUS_T; + +typedef enum _SSP_INTCLEAR { + SSP_RORIC = 0x0, + SSP_RTIC = 0x1, + SSP_INT_CLEAR_BITMASK = 0x3, +} SSP_INTCLEAR_T; + +/* + * @brief SSP clock format + */ +typedef enum CHIP_SSP_CLOCK_FORMAT { + SSP_CLOCK_CPHA0_CPOL0 = (0 << 6), /**< CPHA = 0, CPOL = 0 */ + SSP_CLOCK_CPHA0_CPOL1 = (1u << 6), /**< CPHA = 0, CPOL = 1 */ + SSP_CLOCK_CPHA1_CPOL0 = (2u << 6), /**< CPHA = 1, CPOL = 0 */ + SSP_CLOCK_CPHA1_CPOL1 = (3u << 6), /**< CPHA = 1, CPOL = 1 */ + SSP_CLOCK_MODE0 = SSP_CLOCK_CPHA0_CPOL0,/**< alias */ + SSP_CLOCK_MODE1 = SSP_CLOCK_CPHA1_CPOL0,/**< alias */ + SSP_CLOCK_MODE2 = SSP_CLOCK_CPHA0_CPOL1,/**< alias */ + SSP_CLOCK_MODE3 = SSP_CLOCK_CPHA1_CPOL1,/**< alias */ +} CHIP_SSP_CLOCK_MODE_T; + +/* + * @brief SSP frame format + */ +typedef enum CHIP_SSP_FRAME_FORMAT { + SSP_FRAMEFORMAT_SPI = (0 << 4), /**< Frame format: SPI */ + CHIP_SSP_FRAME_FORMAT_TI = (1u << 4), /**< Frame format: TI SSI */ + SSP_FRAMEFORMAT_MICROWIRE = (2u << 4), /**< Frame format: Microwire */ +} CHIP_SSP_FRAME_FORMAT_T; + +/* + * @brief Number of bits per frame + */ +typedef enum CHIP_SSP_BITS { + SSP_BITS_4 = (3u << 0), /*!< 4 bits/frame */ + SSP_BITS_5 = (4u << 0), /*!< 5 bits/frame */ + SSP_BITS_6 = (5u << 0), /*!< 6 bits/frame */ + SSP_BITS_7 = (6u << 0), /*!< 7 bits/frame */ + SSP_BITS_8 = (7u << 0), /*!< 8 bits/frame */ + SSP_BITS_9 = (8u << 0), /*!< 9 bits/frame */ + SSP_BITS_10 = (9u << 0), /*!< 10 bits/frame */ + SSP_BITS_11 = (10u << 0), /*!< 11 bits/frame */ + SSP_BITS_12 = (11u << 0), /*!< 12 bits/frame */ + SSP_BITS_13 = (12u << 0), /*!< 13 bits/frame */ + SSP_BITS_14 = (13u << 0), /*!< 14 bits/frame */ + SSP_BITS_15 = (14u << 0), /*!< 15 bits/frame */ + SSP_BITS_16 = (15u << 0), /*!< 16 bits/frame */ +} CHIP_SSP_BITS_T; + +/* + * @brief SSP config format + */ +typedef struct SSP_ConfigFormat { + CHIP_SSP_BITS_T bits; /*!< Format config: bits/frame */ + CHIP_SSP_CLOCK_MODE_T clockMode; /*!< Format config: clock phase/polarity */ + CHIP_SSP_FRAME_FORMAT_T frameFormat; /*!< Format config: SPI/TI/Microwire */ +} SSP_ConfigFormat; + +/** + * @brief Enable SSP operation + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Enable(LPC_SSP_T *pSSP) +{ + pSSP->CR1 |= SSP_CR1_SSP_EN; +} + +/** + * @brief Disable SSP operation + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Disable(LPC_SSP_T *pSSP) +{ + pSSP->CR1 &= (~SSP_CR1_SSP_EN) & SSP_CR1_BITMASK; +} + +/** + * @brief Enable loopback mode + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + * @note Serial input is taken from the serial output (MOSI or MISO) rather + * than the serial input pin + */ +STATIC INLINE void Chip_SSP_EnableLoopBack(LPC_SSP_T *pSSP) +{ + pSSP->CR1 |= SSP_CR1_LBM_EN; +} + +/** + * @brief Disable loopback mode + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + * @note Serial input is taken from the serial output (MOSI or MISO) rather + * than the serial input pin + */ +STATIC INLINE void Chip_SSP_DisableLoopBack(LPC_SSP_T *pSSP) +{ + pSSP->CR1 &= (~SSP_CR1_LBM_EN) & SSP_CR1_BITMASK; +} + +/** + * @brief Get the current status of SSP controller + * @param pSSP : The base of SSP peripheral on the chip + * @param Stat : Type of status, should be : + * - SSP_STAT_TFE + * - SSP_STAT_TNF + * - SSP_STAT_RNE + * - SSP_STAT_RFF + * - SSP_STAT_BSY + * @return SSP controller status, SET or RESET + */ +STATIC INLINE FlagStatus Chip_SSP_GetStatus(LPC_SSP_T *pSSP, SSP_STATUS_T Stat) +{ + return (pSSP->SR & Stat) ? SET : RESET; +} + +/** + * @brief Get the masked interrupt status + * @param pSSP : The base of SSP peripheral on the chip + * @return SSP Masked Interrupt Status Register value + * @note The return value contains a 1 for each interrupt condition that is asserted and enabled (masked) + */ +STATIC INLINE uint32_t Chip_SSP_GetIntStatus(LPC_SSP_T *pSSP) +{ + return pSSP->MIS; +} + +/** + * @brief Get the raw interrupt status + * @param pSSP : The base of SSP peripheral on the chip + * @param RawInt : Interrupt condition to be get status, shoud be : + * - SSP_RORRIS + * - SSP_RTRIS + * - SSP_RXRIS + * - SSP_TXRIS + * @return Raw interrupt status corresponding to interrupt condition , SET or RESET + * @note Get the status of each interrupt condition ,regardless of whether or not the interrupt is enabled + */ +STATIC INLINE IntStatus Chip_SSP_GetRawIntStatus(LPC_SSP_T *pSSP, SSP_RAWINTSTATUS_T RawInt) +{ + return (pSSP->RIS & RawInt) ? SET : RESET; +} + +/** + * @brief Get the number of bits transferred in each frame + * @param pSSP : The base of SSP peripheral on the chip + * @return the number of bits transferred in each frame minus one + * @note The return value is 0x03 -> 0xF corresponding to 4bit -> 16bit transfer + */ +STATIC INLINE uint8_t Chip_SSP_GetDataSize(LPC_SSP_T *pSSP) +{ + return SSP_CR0_DSS(pSSP->CR0); +} + +/** + * @brief Clear the corresponding interrupt condition(s) in the SSP controller + * @param pSSP : The base of SSP peripheral on the chip + * @param IntClear: Type of cleared interrupt, should be : + * - SSP_RORIC + * - SSP_RTIC + * @return Nothing + * @note Software can clear one or more interrupt condition(s) in the SSP controller + */ +STATIC INLINE void Chip_SSP_ClearIntPending(LPC_SSP_T *pSSP, SSP_INTCLEAR_T IntClear) +{ + pSSP->ICR = IntClear; +} + +/** + * @brief Enable interrupt for the SSP + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Int_Enable(LPC_SSP_T *pSSP) +{ + pSSP->IMSC |= SSP_TXIM; +} + +/** + * @brief Disable interrupt for the SSP + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Int_Disable(LPC_SSP_T *pSSP) +{ + pSSP->IMSC &= (~SSP_TXIM); +} + +/** + * @brief Get received SSP data + * @param pSSP : The base of SSP peripheral on the chip + * @return SSP 16-bit data received + */ +STATIC INLINE uint16_t Chip_SSP_ReceiveFrame(LPC_SSP_T *pSSP) +{ + return (uint16_t) (SSP_DR_BITMASK(pSSP->DR)); +} + +/** + * @brief Send SSP 16-bit data + * @param pSSP : The base of SSP peripheral on the chip + * @param tx_data : SSP 16-bit data to be transmited + * @return Nothing + */ +STATIC INLINE void Chip_SSP_SendFrame(LPC_SSP_T *pSSP, uint16_t tx_data) +{ + pSSP->DR = SSP_DR_BITMASK(tx_data); +} + +/** + * @brief Set up output clocks per bit for SSP bus + * @param pSSP : The base of SSP peripheral on the chip + * @param clk_rate fs: The number of prescaler-output clocks per bit on the bus, minus one + * @param prescale : The factor by which the Prescaler divides the SSP peripheral clock PCLK + * @return Nothing + * @note The bit frequency is PCLK / (prescale x[clk_rate+1]) + */ +void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale); + +/** + * @brief Set up the SSP frame format + * @param pSSP : The base of SSP peripheral on the chip + * @param bits : The number of bits transferred in each frame, should be SSP_BITS_4 to SSP_BITS_16 + * @param frameFormat : Frame format, should be : + * - SSP_FRAMEFORMAT_SPI + * - SSP_FRAME_FORMAT_TI + * - SSP_FRAMEFORMAT_MICROWIRE + * @param clockMode : Select Clock polarity and Clock phase, should be : + * - SSP_CLOCK_CPHA0_CPOL0 + * - SSP_CLOCK_CPHA0_CPOL1 + * - SSP_CLOCK_CPHA1_CPOL0 + * - SSP_CLOCK_CPHA1_CPOL1 + * @return Nothing + * @note Note: The clockFormat is only used in SPI mode + */ +STATIC INLINE void Chip_SSP_SetFormat(LPC_SSP_T *pSSP, uint32_t bits, uint32_t frameFormat, uint32_t clockMode) +{ + pSSP->CR0 = (pSSP->CR0 & ~0xFF) | bits | frameFormat | clockMode; +} + +/** + * @brief Set the SSP working as master or slave mode + * @param pSSP : The base of SSP peripheral on the chip + * @param mode : Operating mode, should be + * - SSP_MODE_MASTER + * - SSP_MODE_SLAVE + * @return Nothing + */ +STATIC INLINE void Chip_SSP_Set_Mode(LPC_SSP_T *pSSP, uint32_t mode) +{ + pSSP->CR1 = (pSSP->CR1 & ~(1 << 2)) | mode; +} + +/* + * @brief SSP mode + */ +typedef enum CHIP_SSP_MODE { + SSP_MODE_MASTER = (0 << 2), /**< Master mode */ + SSP_MODE_SLAVE = (1u << 2), /**< Slave mode */ +} CHIP_SSP_MODE_T; + +/* + * @brief SPI address + */ +typedef struct { + uint8_t port; /*!< Port Number */ + uint8_t pin; /*!< Pin number */ +} SPI_Address_t; + +/* + * @brief SSP data setup structure + */ +typedef struct { + void *tx_data; /*!< Pointer to transmit data */ + uint32_t tx_cnt; /*!< Transmit counter */ + void *rx_data; /*!< Pointer to transmit data */ + uint32_t rx_cnt; /*!< Receive counter */ + uint32_t length; /*!< Length of transfer data */ +} Chip_SSP_DATA_SETUP_T; + +/** SSP configuration parameter defines */ +/** Clock phase control bit */ +#define SSP_CPHA_FIRST SSP_CR0_CPHA_FIRST +#define SSP_CPHA_SECOND SSP_CR0_CPHA_SECOND + +/** Clock polarity control bit */ +/* There's no bug here!!! + * - If bit[6] in SSPnCR0 is 0: SSP controller maintains the bus clock low between frames. + * That means the active clock is in HI state. + * - If bit[6] in SSPnCR0 is 1 (SSP_CR0_CPOL_HI): SSP controller maintains the bus clock + * high between frames. That means the active clock is in LO state. + */ +#define SSP_CPOL_HI SSP_CR0_CPOL_LO +#define SSP_CPOL_LO SSP_CR0_CPOL_HI + +/** SSP master mode enable */ +#define SSP_SLAVE_MODE SSP_CR1_SLAVE_EN +#define SSP_MASTER_MODE SSP_CR1_MASTER_EN + +/** + * @brief Clean all data in RX FIFO of SSP + * @param pSSP : The base SSP peripheral on the chip + * @return Nothing + */ +void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP); + +/** + * @brief SSP Interrupt Read/Write with 8-bit frame width + * @param pSSP : The base SSP peripheral on the chip + * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified + * information about transmit/receive data configuration + * @return SUCCESS or ERROR + */ +Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup); + +/** + * @brief SSP Interrupt Read/Write with 16-bit frame width + * @param pSSP : The base SSP peripheral on the chip + * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified + * information about transmit/receive data configuration + * @return SUCCESS or ERROR + */ +Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup); + +/** + * @brief SSP Polling Read/Write in blocking mode + * @param pSSP : The base SSP peripheral on the chip + * @param xf_setup : Pointer to a SSP_DATA_SETUP_T structure that contains specified + * information about transmit/receive data configuration + * @return Actual data length has been transferred + * @note + * This function can be used in both master and slave mode. It starts with writing phase and after that, + * a reading phase is generated to read any data available in RX_FIFO. All needed information is prepared + * through xf_setup param. + */ +uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup); + +/** + * @brief SSP Polling Write in blocking mode + * @param pSSP : The base SSP peripheral on the chip + * @param buffer : Buffer address + * @param buffer_len : Buffer length + * @return Actual data length has been transferred + * @note + * This function can be used in both master and slave mode. First, a writing operation will send + * the needed data. After that, a dummy reading operation is generated to clear data buffer + */ +uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len); + +/** + * @brief SSP Polling Read in blocking mode + * @param pSSP : The base SSP peripheral on the chip + * @param buffer : Buffer address + * @param buffer_len : The length of buffer + * @return Actual data length has been transferred + * @note + * This function can be used in both master and slave mode. First, a dummy writing operation is generated + * to clear data buffer. After that, a reading operation will receive the needed data + */ +uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len); + +/** + * @brief Initialize the SSP + * @param pSSP : The base SSP peripheral on the chip + * @return Nothing + */ +void Chip_SSP_Init(LPC_SSP_T *pSSP); + +/** + * @brief Deinitialise the SSP + * @param pSSP : The base of SSP peripheral on the chip + * @return Nothing + * @note The SSP controller is disabled + */ +void Chip_SSP_DeInit(LPC_SSP_T *pSSP); + +/** + * @brief Set the SSP operating modes, master or slave + * @param pSSP : The base SSP peripheral on the chip + * @param master : 1 to set master, 0 to set slave + * @return Nothing + */ +void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master); + +/** + * @brief Set the clock frequency for SSP interface + * @param pSSP : The base SSP peripheral on the chip + * @param bitRate : The SSP bit rate + * @return Nothing + */ +void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SSP_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/stopwatch.h b/source/lpc_chip_11u6x/inc/stopwatch.h new file mode 100644 index 0000000..c298735 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/stopwatch.h @@ -0,0 +1,137 @@ +/* + * @brief Common stopwatch support + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __STOPWATCH_H_ +#define __STOPWATCH_H_ + +#include "cmsis.h" + +/** @defgroup Stop_Watch CHIP: Stopwatch primitives. + * @ingroup CHIP_Common + * @{ + */ + +/** + * @brief Initialize stopwatch + * @return Nothing + */ +void StopWatch_Init(void); + +/** + * @brief Start a stopwatch + * @return Current cycle count + */ +uint32_t StopWatch_Start(void); + +/** + * @brief Returns number of ticks elapsed since stopwatch was started + * @param startTime : Time returned by StopWatch_Start(). + * @return Number of ticks elapsed since stopwatch was started + */ +STATIC INLINE uint32_t StopWatch_Elapsed(uint32_t startTime) +{ + return StopWatch_Start() - startTime; +} + +/** + * @brief Returns number of ticks per second of the stopwatch timer + * @return Number of ticks per second of the stopwatch timer + */ +uint32_t StopWatch_TicksPerSecond(void); + +/** + * @brief Converts from stopwatch ticks to mS. + * @param ticks : Duration in ticks to convert to mS. + * @return Number of mS in given number of ticks + */ +uint32_t StopWatch_TicksToMs(uint32_t ticks); + +/** + * @brief Converts from stopwatch ticks to uS. + * @param ticks : Duration in ticks to convert to uS. + * @return Number of uS in given number of ticks + */ +uint32_t StopWatch_TicksToUs(uint32_t ticks); + +/** + * @brief Converts from mS to stopwatch ticks. + * @param mS : Duration in mS to convert to ticks. + * @return Number of ticks in given number of mS + */ +uint32_t StopWatch_MsToTicks(uint32_t mS); + +/** + * @brief Converts from uS to stopwatch ticks. + * @param uS : Duration in uS to convert to ticks. + * @return Number of ticks in given number of uS + */ +uint32_t StopWatch_UsToTicks(uint32_t uS); + +/** + * @brief Delays the given number of ticks using stopwatch primitives + * @param ticks : Number of ticks to delay + * @return Nothing + */ +STATIC INLINE void StopWatch_DelayTicks(uint32_t ticks) +{ + uint32_t startTime = StopWatch_Start(); + while (StopWatch_Elapsed(startTime) < ticks) {} +} + +/** + * @brief Delays the given number of mS using stopwatch primitives + * @param mS : Number of mS to delay + * @return Nothing + */ +STATIC INLINE void StopWatch_DelayMs(uint32_t mS) +{ + uint32_t ticks = StopWatch_MsToTicks(mS); + uint32_t startTime = StopWatch_Start(); + while (StopWatch_Elapsed(startTime) < ticks) {} +} + +/** + * @brief Delays the given number of uS using stopwatch primitives + * @param uS : Number of uS to delay + * @return Nothing + */ +STATIC INLINE void StopWatch_DelayUs(uint32_t uS) +{ + uint32_t ticks = StopWatch_UsToTicks(uS); + uint32_t startTime = StopWatch_Start(); + while (StopWatch_Elapsed(startTime) < ticks) {} +} + +/** + * @} + */ + +#endif /* __STOPWATCH_H_ */ diff --git a/source/lpc_chip_11u6x/inc/sys_config.h b/source/lpc_chip_11u6x/inc/sys_config.h new file mode 100644 index 0000000..47cc449 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/sys_config.h @@ -0,0 +1,36 @@ +/* + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SYS_CONFIG_H_ +#define __SYS_CONFIG_H_ + +/* Required for the LPC11U6x device */ +#define CHIP_LPC11U6X + +#endif /* __SYS_CONFIG_H_ */ diff --git a/source/lpc_chip_11u6x/inc/syscon_11u6x.h b/source/lpc_chip_11u6x/inc/syscon_11u6x.h new file mode 100644 index 0000000..44d90f0 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/syscon_11u6x.h @@ -0,0 +1,569 @@ +/* + * @brief LPC11U6X System Control registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __SYSCTL_11U6X_H_ +#define __SYSCTL_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup SYSCTL_11U6X CHIP: LPC11u6x System Control block driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief LPC11U6X System Control block structure + */ +typedef struct { /*!< SYSCTL Structure */ + __IO uint32_t SYSMEMREMAP; /*!< System Memory remap register */ + __IO uint32_t PRESETCTRL; /*!< Peripheral reset Control register */ + __IO uint32_t SYSPLLCTRL; /*!< System PLL control register */ + __I uint32_t SYSPLLSTAT; /*!< System PLL status register */ + __IO uint32_t USBPLLCTRL; /*!< USB PLL control register */ + __I uint32_t USBPLLSTAT; /*!< USB PLL status register */ + __I uint32_t RESERVED1[1]; + __IO uint32_t RTCOSCCTRL; /*!< RTC Oscillator control register */ + __IO uint32_t SYSOSCCTRL; /*!< System Oscillator control register */ + __IO uint32_t WDTOSCCTRL; /*!< Watchdog Oscillator control register */ + __I uint32_t RESERVED2[2]; + __IO uint32_t SYSRSTSTAT; /*!< System Reset Status register */ + __I uint32_t RESERVED3[3]; + __IO uint32_t SYSPLLCLKSEL; /*!< System PLL clock source select register */ + __IO uint32_t SYSPLLCLKUEN; /*!< System PLL clock source update enable register*/ + __IO uint32_t USBPLLCLKSEL; /*!< USB PLL clock source select register */ + __IO uint32_t USBPLLCLKUEN; /*!< USB PLL clock source update enable register */ + __I uint32_t RESERVED4[8]; + __IO uint32_t MAINCLKSEL; /*!< Main clock source select register */ + __IO uint32_t MAINCLKUEN; /*!< Main clock source update enable register */ + __IO uint32_t SYSAHBCLKDIV; /*!< System Clock divider register */ + __I uint32_t RESERVED5; + __IO uint32_t SYSAHBCLKCTRL; /*!< System clock control register */ + __I uint32_t RESERVED6[4]; + __IO uint32_t SSP0CLKDIV; /*!< SSP0 clock divider register */ + __IO uint32_t USART0CLKDIV; /*!< UART clock divider register */ + __IO uint32_t SSP1CLKDIV; /*!< SSP1 clock divider register */ + __IO uint32_t FRGCLKDIV; /*!< FRG clock divider (USARTS 1 - 4) register */ + __I uint32_t RESERVED7[7]; + __IO uint32_t USBCLKSEL; /*!< USB clock source select register */ + __IO uint32_t USBCLKUEN; /*!< USB clock source update enable register */ + __IO uint32_t USBCLKDIV; /*!< USB clock source divider register */ + __I uint32_t RESERVED8[5]; + __IO uint32_t CLKOUTSEL; /*!< Clock out source select register */ + __IO uint32_t CLKOUTUEN; /*!< Clock out source update enable register */ + __IO uint32_t CLKOUTDIV; /*!< Clock out divider register */ + __I uint32_t RESERVED9; + __IO uint32_t UARTFRGDIV; /*!< USART fractional generator divider (USARTS 1 - 4) register */ + __IO uint32_t UARTFRGMULT; /*!< USART fractional generator multiplier (USARTS 1 - 4) register */ + __I uint32_t RESERVED10; + __IO uint32_t EXTTRACECMD; /*!< External trace buffer command register */ + __I uint32_t PIOPORCAP[3]; /*!< POR captured PIO status registers */ + __I uint32_t RESERVED11[10]; + __IO uint32_t IOCONCLKDIV[7]; /*!< IOCON block for programmable glitch filter divider registers */ + __IO uint32_t BODCTRL; /*!< Brown Out Detect register */ + __IO uint32_t SYSTCKCAL; /*!< System tick counter calibration register */ + __I uint32_t RESERVED12[6]; + __IO uint32_t IRQLATENCY; /*!< IRQ delay register */ + __IO uint32_t NMISRC; /*!< NMI source control register */ + __IO uint32_t PINTSEL[8]; /*!< GPIO pin interrupt select register 0-7 */ + __IO uint32_t USBCLKCTRL; /*!< USB clock control register */ + __I uint32_t USBCLKST; /*!< USB clock status register */ + __I uint32_t RESERVED13[25]; + __IO uint32_t STARTERP0; /*!< Start logic 0 interrupt wake-up enable register */ + __I uint32_t RESERVED14[3]; + __IO uint32_t STARTERP1; /*!< Start logic 1 interrupt wake-up enable register */ + __I uint32_t RESERVED15[6]; + __IO uint32_t PDSLEEPCFG; /*!< Power down states in deep sleep mode register */ + __IO uint32_t PDWAKECFG; /*!< Power down states in wake up from deep sleep register */ + __IO uint32_t PDRUNCFG; /*!< Power configuration register*/ + __I uint32_t RESERVED16[110]; + __I uint32_t DEVICEID; /*!< Device ID register */ +} LPC_SYSCTL_T; + +/** + * System memory remap modes used to remap interrupt vectors + */ +typedef enum CHIP_SYSCTL_BOOT_MODE_REMAP { + REMAP_BOOT_LOADER_MODE, /*!< Interrupt vectors are re-mapped to Boot ROM */ + REMAP_USER_RAM_MODE, /*!< Interrupt vectors are re-mapped to Static RAM */ + REMAP_USER_FLASH_MODE /*!< Interrupt vectors are not re-mapped and reside in Flash */ +} CHIP_SYSCTL_BOOT_MODE_REMAP_T; + +/** + * @brief Re-map interrupt vectors + * @param remap : system memory map value + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_Map(CHIP_SYSCTL_BOOT_MODE_REMAP_T remap) +{ + LPC_SYSCTL->SYSMEMREMAP = (uint32_t) remap; +} + +/** + * Peripheral reset identifiers, not available on all devices + */ +typedef enum { + RESET_SSP0, /*!< SSP0 reset control */ + RESET_I2C0, /*!< I2C0 reset control */ + RESET_SSP1, /*!< SSP1 reset control */ + RESET_I2C1, /*!< I2C1 reset control */ + RESET_FRG, /*!< FRG reset control */ + RESET_USART1, /*!< USART1 reset control */ + RESET_USART2, /*!< USART1 reset control */ + RESET_USART3, /*!< USART1 reset control */ + RESET_USART4, /*!< USART1 reset control */ + RESET_SCT0, /*!< SCT0 reset control */ + RESET_SCT1 /*!< SCT1 reset control */ +} CHIP_SYSCTL_PERIPH_RESET_T; + +/** + * @brief Assert reset for a peripheral + * @param periph : Peripheral to assert reset for + * @return Nothing + * @note The peripheral will stay in reset until reset is de-asserted. Call + * Chip_SYSCTL_DeassertPeriphReset() to de-assert the reset. + */ +STATIC INLINE void Chip_SYSCTL_AssertPeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph) +{ + LPC_SYSCTL->PRESETCTRL &= ~(1 << (uint32_t) periph); +} + +/** + * @brief De-assert reset for a peripheral + * @param periph : Peripheral to de-assert reset for + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DeassertPeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph) +{ + LPC_SYSCTL->PRESETCTRL |= (1 << (uint32_t) periph); +} + +/** + * @brief Resets a peripheral + * @param periph : Peripheral to reset + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_PeriphReset(CHIP_SYSCTL_PERIPH_RESET_T periph) +{ + Chip_SYSCTL_AssertPeriphReset(periph); + Chip_SYSCTL_DeassertPeriphReset(periph); +} + +/** + * System reset status + */ +#define SYSCTL_RST_POR (1 << 0) /*!< POR reset status */ +#define SYSCTL_RST_EXTRST (1 << 1) /*!< External reset status */ +#define SYSCTL_RST_WDT (1 << 2) /*!< Watchdog reset status */ +#define SYSCTL_RST_BOD (1 << 3) /*!< Brown-out detect reset status */ +#define SYSCTL_RST_SYSRST (1 << 4) /*!< software system reset status */ + +/** + * @brief Get system reset status + * @return An Or'ed value of SYSCTL_RST_* + * @note This function returns the detected reset source(s). + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetSystemRSTStatus(void) +{ + return LPC_SYSCTL->SYSRSTSTAT; +} + +/** + * @brief Clear system reset status + * @param reset : An Or'ed value of SYSCTL_RST_* status to clear + * @return Nothing + * @note This function returns the detected reset source(s). + */ +STATIC INLINE void Chip_SYSCTL_ClearSystemRSTStatus(uint32_t reset) +{ + LPC_SYSCTL->SYSRSTSTAT = reset; +} + +/** + * @brief Read POR captured PIO status + * @param index : POR register index, 0 or 1 + * @return captured POR PIO status + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetPORPIOStatus(int index) +{ + return LPC_SYSCTL->PIOPORCAP[index]; +} + +/** + * Brown-out detector reset level + */ +typedef enum CHIP_SYSCTL_BODRSTLVL { + // FIXME - will update with correct voltages + SYSCTL_BODRSTLVL_LEVEL0, /*!< Brown-out reset at TBD volts */ + SYSCTL_BODRSTLVL_LEVEL1, /*!< Brown-out reset at TBD volts */ + SYSCTL_BODRSTLVL_LEVEL2, /*!< Brown-out reset at TBD volts */ + SYSCTL_BODRSTLVL_LEVEL3, /*!< Brown-out reset at TBD volts */ +} CHIP_SYSCTL_BODRSTLVL_T; + +/** + * Brown-out detector interrupt level + */ +typedef enum CHIP_SYSCTL_BODRINTVAL { + // FIXME - will update with correct voltages + SYSCTL_BODINTVAL_RESERVED1, + SYSCTL_BODINTVAL_RESERVED2, + SYSCTL_BODINTVAL_2_LEVEL2, /*!< Brown-out interrupt at TBD volts */ + SYSCTL_BODINTVAL_2_LEVEL3, /*!< Brown-out interrupt at TBD volts */ +} CHIP_SYSCTL_BODRINTVAL_T; + +/** + * @brief Set brown-out detection interrupt and reset levels + * @param rstlvl : Brown-out detector reset level + * @param intlvl : Brown-out interrupt level + * @return Nothing + * @note Brown-out detection reset will be disabled upon exiting this function. + * Use Chip_SYSCTL_EnableBODReset() to re-enable. + */ +STATIC INLINE void Chip_SYSCTL_SetBODLevels(CHIP_SYSCTL_BODRSTLVL_T rstlvl, + CHIP_SYSCTL_BODRINTVAL_T intlvl) +{ + LPC_SYSCTL->BODCTRL = ((uint32_t) rstlvl) | (((uint32_t) intlvl) << 2); +} + +/** + * @brief Enable brown-out detection reset + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_EnableBODReset(void) +{ + LPC_SYSCTL->BODCTRL |= (1 << 4); +} + +/** + * @brief Disable brown-out detection reset + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DisableBODReset(void) +{ + LPC_SYSCTL->BODCTRL &= ~(1 << 4); +} + +/** + * @brief Set System tick timer calibration value + * @param sysCalVal : System tick timer calibration value + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_SetSYSTCKCAL(uint32_t sysCalVal) +{ + LPC_SYSCTL->SYSTCKCAL = sysCalVal; +} + +/** + * @brief Set System IRQ latency + * @param latency : Latency in clock ticks + * @return Nothing + * @note Sets the IRQ latency, a value between 0 and 255 clocks. Lower + * values allow better latency. + */ +STATIC INLINE void Chip_SYSCTL_SetIRQLatency(uint32_t latency) +{ + LPC_SYSCTL->IRQLATENCY = latency; +} + +/** + * @brief Get System IRQ latency + * @return Latency in clock ticks + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetIRQLatency(void) +{ + return LPC_SYSCTL->IRQLATENCY; +} + +/** + * Non-Maskable Interrupt Enable/Disable value + */ +#define SYSCTL_NMISRC_ENABLE ((uint32_t) 1 << 31) /*!< Enable the Non-Maskable Interrupt (NMI) source */ + +/** + * @brief Set source for non-maskable interrupt (NMI) + * @param intsrc : IRQ number to assign to the NMI + * @return Nothing + * @note The NMI source will be disabled upon exiting this function. use the + * Chip_SYSCTL_EnableNMISource() function to enable the NMI source. + */ +STATIC INLINE void Chip_SYSCTL_SetNMISource(uint32_t intsrc) +{ + LPC_SYSCTL->NMISRC = 0; /* Disable first */ + LPC_SYSCTL->NMISRC = intsrc; +} + +/** + * @brief Enable interrupt used for NMI source + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_EnableNMISource(void) +{ + LPC_SYSCTL->NMISRC |= SYSCTL_NMISRC_ENABLE; +} + +/** + * @brief Disable interrupt used for NMI source + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DisableNMISource(void) +{ + LPC_SYSCTL->NMISRC &= ~(SYSCTL_NMISRC_ENABLE); +} + +/** + * @brief Setup a GPIO pin source for a pin interrupt (0-7) + * @param intno : IRQ number + * @param port : port number 0, 1, or 2) + * @param pin : pin number (0-23 for Port 0, 0-31 for Port 1, 0-7 for port 2) + * @return Nothing + */ +void Chip_SYSCTL_SetPinInterrupt(uint32_t intno, uint8_t port, uint8_t pin); + +/** + * @brief Setup USB clock control + * @param ap_clk : USB need_clock signal control (0 or 1) + * @param pol_clk : USB need_clock polarity for triggering the USB wake-up interrupt (0 or 1) + * @return Nothing + * @note See the USBCLKCTRL register in the user manual for these settings. + */ +STATIC INLINE void Chip_SYSCTL_SetUSBCLKCTRL(uint32_t ap_clk, uint32_t pol_clk) +{ + LPC_SYSCTL->USBCLKCTRL = ap_clk | (pol_clk << 1); +} + +/** + * @brief Use the internal pull-up resistor for the the USB_DP/DM pull-up/pull-down resistors + * @return Nothing + * @note See the USBCLKCTRL register in the user manual for more information. + */ +STATIC INLINE void Chip_SYSCTL_UseIntPullup(void) +{ + LPC_SYSCTL->USBCLKCTRL |= (1 << 2); +} + +/** + * @brief Use the external pull-up resistor for the the USB_DP/DM pull-up/pull-down resistors + * @return Nothing + * @note See the USBCLKCTRL register in the user manual for more information. + */ +STATIC INLINE void Chip_SYSCTL_UseExtPullup(void) +{ + LPC_SYSCTL->USBCLKCTRL &= ~(1 << 2); +} + +/** + * @brief Returns the status of the USB need_clock signal + * @return true if USB need_clock status is high, otherwise false + */ +STATIC INLINE bool Chip_SYSCTL_GetUSBCLKStatus(void) +{ + return (bool) ((LPC_SYSCTL->USBCLKST & 0x1) != 0); +} + +/** + * @brief Enable PIO start logic for a PININT pin + * @param pin : PIO pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_EnableStartPin(uint32_t pin) +{ + LPC_SYSCTL->STARTERP0 |= (1 << pin); +} + +/** + * @brief Disable PIO start logic for a PININT pin + * @param pin : PIO pin number + * @return Nothing + * @note Different devices support different pins, see the user manual for supported pins. + */ +STATIC INLINE void Chip_SYSCTL_DisableStartPin(uint32_t pin) +{ + LPC_SYSCTL->STARTERP0 &= ~(1 << pin); +} + +/** + * Peripheral interrupt wakeup events + */ +// FIXME - Need to recheck these bit positions +// FIXME - LPC11U6X user manual shows this as bit 13. This is the bit that works! +#define SYSCTL_WAKEUP_BOD_WDT_INT (1 << 12) /*!< Shared Brown Out Detect (BOD) and WDT interrupt wake-up */ +// FIXME - LPC11U6X user manual shows this as bit 12. This is the bit that works! +#define SYSCTL_WAKEUP_RTCINT (1 << 19) /*!< RTC interrupt wake-up */ +#define SYSCTL_WAKEUP_USB_WAKEUP (1 << 19) /*!< USB need_clock signal wake-up */ +#define SYSCTL_WAKEUP_GPIOINT0 (1 << 20) /*!< GPIO GROUP0 interrupt wake-up */ +#define SYSCTL_WAKEUP_GPIOINT1 (1 << 21) /*!< GPIO GROUP1 interrupt wake-up */ +#define SYSCTL_WAKEUP_USART1_4 (1 << 23) /*!< Combined USART1 and USART4 wake-up */ +#define SYSCTL_WAKEUP_USART2_3 (1 << 24) /*!< Combined USART2 and USART3 interrupt wake-up */ + +/** + * @brief Enables a peripheral's wakeup logic + * @param periphmask : OR'ed values of SYSCTL_WAKEUP_* for wakeup + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_EnablePeriphWakeup(uint32_t periphmask) +{ + LPC_SYSCTL->STARTERP1 |= periphmask; +} + +/** + * @brief Disables a peripheral's wakeup logic + * @param periphmask : OR'ed values of SYSCTL_WAKEUP_* for wakeup + * @return Nothing + */ +STATIC INLINE void Chip_SYSCTL_DisablePeriphWakeup(uint32_t periphmask) +{ + LPC_SYSCTL->STARTERP1 &= ~periphmask; +} + +/** + * Deep sleep setup values + */ +#define SYSCTL_DEEPSLP_BOD_PD (1 << 3) /*!< BOD power-down control in Deep-sleep mode, powered down */ +#define SYSCTL_DEEPSLP_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator power control in Deep-sleep, powered down */ + +/** + * @brief Setup deep sleep behaviour for power down + * @param sleepmask : OR'ed values of SYSCTL_DEEPSLP_* values (high to powerdown on deepsleep) + * @return Nothing + * @note This must be setup prior to using deep sleep. See the user manual + * (PDSLEEPCFG register) for more info on setting this up. This function selects + * which peripherals are powered down on deep sleep. + * This function should only be called once with all options for power-down + * in that call. + */ +void Chip_SYSCTL_SetDeepSleepPD(uint32_t sleepmask); + +/** + * @brief Returns current deep sleep mask + * @return OR'ed values of SYSCTL_DEEPSLP_* values + * @note A high bit indicates the peripheral will power down on deep sleep. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetDeepSleepPD(void) +{ + return LPC_SYSCTL->PDSLEEPCFG; +} + +/** + * Deep sleep to wakeup setup values + */ +#define SYSCTL_SLPWAKE_IRCOUT_PD (1 << 0) /*!< IRC oscillator output wake-up configuration */ +#define SYSCTL_SLPWAKE_IRC_PD (1 << 1) /*!< IRC oscillator power-down wake-up configuration */ +#define SYSCTL_SLPWAKE_FLASH_PD (1 << 2) /*!< Flash wake-up configuration */ +#define SYSCTL_SLPWAKE_BOD_PD (1 << 3) /*!< BOD wake-up configuration */ +#define SYSCTL_SLPWAKE_ADC_PD (1 << 4) /*!< ADC wake-up configuration */ +#define SYSCTL_SLPWAKE_SYSOSC_PD (1 << 5) /*!< System oscillator wake-up configuration */ +#define SYSCTL_SLPWAKE_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator wake-up configuration */ +#define SYSCTL_SLPWAKE_SYSPLL_PD (1 << 7) /*!< System PLL wake-up configuration */ +#define SYSCTL_SLPWAKE_USBPLL_PD (1 << 8) /*!< USB PLL wake-up configuration */ +#define SYSCTL_SLPWAKE_USBPAD_PD (1 << 10) /*!< USB transceiver wake-up configuration */ +#define SYSCTL_SLPWAKE_TS_PD (1 << 13) /*!< Temperature sensor wake-up configuration */ + +/** + * @brief Setup wakeup behaviour from deep sleep + * @param wakeupmask : OR'ed values of SYSCTL_SLPWAKE_* values (high is powered down) + * @return Nothing + * @note This must be setup prior to using deep sleep. See the user manual + * (PDWAKECFG register) for more info on setting this up. This function selects + * which peripherals are powered up on exit from deep sleep. + * This function should only be called once with all options for wakeup + * in that call. + */ +void Chip_SYSCTL_SetWakeup(uint32_t wakeupmask); + +/** + * @brief Return current wakeup mask + * @return OR'ed values of SYSCTL_SLPWAKE_* values + * @note A high state indicates the peripehral will powerup on wakeup. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetWakeup(void) +{ + return LPC_SYSCTL->PDWAKECFG; +} + +/** + * Power down configuration values + */ +#define SYSCTL_POWERDOWN_IRCOUT_PD (1 << 0) /*!< IRC oscillator output power down */ +#define SYSCTL_POWERDOWN_IRC_PD (1 << 1) /*!< IRC oscillator power-down */ +#define SYSCTL_POWERDOWN_FLASH_PD (1 << 2) /*!< Flash power down */ +#define SYSCTL_POWERDOWN_BOD_PD (1 << 3) /*!< BOD power down */ +#define SYSCTL_POWERDOWN_ADC_PD (1 << 4) /*!< ADC power down */ +#define SYSCTL_POWERDOWN_SYSOSC_PD (1 << 5) /*!< System oscillator power down */ +#define SYSCTL_POWERDOWN_WDTOSC_PD (1 << 6) /*!< Watchdog oscillator power down */ +#define SYSCTL_POWERDOWN_SYSPLL_PD (1 << 7) /*!< System PLL power down */ +#define SYSCTL_POWERDOWN_USBPLL_PD (1 << 8) /*!< USB PLL power-down */ +#define SYSCTL_POWERDOWN_USBPAD_PD (1 << 10) /*!< USB transceiver power-down */ +#define SYSCTL_POWERDOWN_TS_PD (1 << 13) /*!< Temperature Sensor power-down */ + +/** + * @brief Power down one or more blocks or peripherals + * @param powerdownmask : OR'ed values of SYSCTL_POWERDOWN_* values + * @return Nothing + */ +void Chip_SYSCTL_PowerDown(uint32_t powerdownmask); + +/** + * @brief Power up one or more blocks or peripherals + * @param powerupmask : OR'ed values of SYSCTL_POWERDOWN_* values + * @return Nothing + */ +void Chip_SYSCTL_PowerUp(uint32_t powerupmask); + +/** + * @brief Get power status + * @return OR'ed values of SYSCTL_POWERDOWN_* values + * @note A high state indicates the peripheral is powered down. + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetPowerStates(void) +{ + return LPC_SYSCTL->PDRUNCFG; +} + +/** + * @brief Return the device ID + * @return the device ID + */ +STATIC INLINE uint32_t Chip_SYSCTL_GetDeviceID(void) +{ + return LPC_SYSCTL->DEVICEID; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*!< __SYSCTL_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/timer_11u6x.h b/source/lpc_chip_11u6x/inc/timer_11u6x.h new file mode 100644 index 0000000..8543340 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/timer_11u6x.h @@ -0,0 +1,493 @@ +/* + * @brief LPC11u6x 16/32-bit Timer/PWM control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __TIMER_11U6X_H_ +#define __TIMER_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup TIMER_11U6X CHIP: LPC11u6x 16/32-bit Timer driver + * @ingroup CHIP_11U6X_Drivers + * IMPORTANT NOTE ABOUT lpc11u6x TIMERS
+ * For timer 0 on both the 16-bit and 32-bit timers, the capture functions + * use index 0 for capture 0 functions and index 2 for capture 1 functions, + * while timer 1 for both the 16-bit and 32-bit timers uses index 0 and + * index 1. Use care when selecting + * The LPC11U6X User manual is inconsistent in it's designation of capture + * channels for each timer. See the comments for each function for special + * handling per timer when dealing with capture channels. + * @{ + */ + +/** + * @brief 32-bit Standard timer register block structure + */ +typedef struct { /*!< TIMERn Structure */ + __IO uint32_t IR; /*!< Interrupt Register. The IR can be written to clear interrupts. The IR can be read to identify which of eight possible interrupt sources are pending. */ + __IO uint32_t TCR; /*!< Timer Control Register. The TCR is used to control the Timer Counter functions. The Timer Counter can be disabled or reset through the TCR. */ + __IO uint32_t TC; /*!< Timer Counter. The 32 bit TC is incremented every PR+1 cycles of PCLK. The TC is controlled through the TCR. */ + __IO uint32_t PR; /*!< Prescale Register. The Prescale Counter (below) is equal to this value, the next clock increments the TC and clears the PC. */ + __IO uint32_t PC; /*!< Prescale Counter. The 32 bit PC is a counter which is incremented to the value stored in PR. When the value in PR is reached, the TC is incremented and the PC is cleared. The PC is observable and controllable through the bus interface. */ + __IO uint32_t MCR; /*!< Match Control Register. The MCR is used to control if an interrupt is generated and if the TC is reset when a Match occurs. */ + __IO uint32_t MR[4]; /*!< Match Register. MR can be enabled through the MCR to reset the TC, stop both the TC and PC, and/or generate an interrupt every time MR matches the TC. */ + __IO uint32_t CCR; /*!< Capture Control Register. The CCR controls which edges of the capture inputs are used to load the Capture Registers and whether or not an interrupt is generated when a capture takes place. */ + __IO uint32_t CR[4]; /*!< Capture Register. CR is loaded with the value of TC when there is an event on the CAPn.0 input. */ + __IO uint32_t EMR; /*!< External Match Register. The EMR controls the external match pins MATn.0-3 (MAT0.0-3 and MAT1.0-3 respectively). */ + __I uint32_t RESERVED0[12]; + __IO uint32_t CTCR; /*!< Count Control Register. The CTCR selects between Timer and Counter mode, and in Counter mode selects the signal and edge(s) for counting. */ + __IO uint32_t PWMC; +} LPC_TIMER_T; + +/** Macro to clear interrupt pending */ +#define TIMER_IR_CLR(n) _BIT(n) + +/** Macro for getting a timer match interrupt bit */ +#define TIMER_MATCH_INT(n) (_BIT((n) & 0x0F)) +/** Macro for getting a capture event interrupt bit */ +#define TIMER_CAP_INT(n) (_BIT((((n) & 0x0F) + 4))) + +/** Timer/counter enable bit */ +#define TIMER_ENABLE ((uint32_t) (1 << 0)) +/** Timer/counter reset bit */ +#define TIMER_RESET ((uint32_t) (1 << 1)) + +/** Bit location for interrupt on MRx match, n = 0 to 3 */ +#define TIMER_INT_ON_MATCH(n) (_BIT(((n) * 3))) +/** Bit location for reset on MRx match, n = 0 to 3 */ +#define TIMER_RESET_ON_MATCH(n) (_BIT((((n) * 3) + 1))) +/** Bit location for stop on MRx match, n = 0 to 3 */ +#define TIMER_STOP_ON_MATCH(n) (_BIT((((n) * 3) + 2))) + +/** Bit location for CAP.n on CRx rising edge, n = 0 to 3 */ +#define TIMER_CAP_RISING(n) (_BIT(((n) * 3))) +/** Bit location for CAP.n on CRx falling edge, n = 0 to 3 */ +#define TIMER_CAP_FALLING(n) (_BIT((((n) * 3) + 1))) +/** Bit location for CAP.n on CRx interrupt enable, n = 0 to 3 */ +#define TIMER_INT_ON_CAP(n) (_BIT((((n) * 3) + 2))) + +/** + * @brief Initialize a timer + * @param pTMR : Pointer to timer IP register address + * @return Nothing + */ +void Chip_TIMER_Init(LPC_TIMER_T *pTMR); + +/** + * @brief Shutdown a timer + * @param pTMR : Pointer to timer IP register address + * @return Nothing + */ +void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR); + +/** + * @brief Determine if a match interrupt is pending + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match interrupt number to check + * @return false if the interrupt is not pending, otherwise true + * @note Determine if the match interrupt for the passed timer and match + * counter is pending.
+ */ +STATIC INLINE bool Chip_TIMER_MatchPending(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + return (bool) ((pTMR->IR & TIMER_MATCH_INT(matchnum)) != 0); +} + +/** + * @brief Determine if a capture interrupt is pending + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture interrupt number to check + * @return false if the interrupt is not pending, otherwise true + * @note Determine if the capture interrupt for the passed capture pin is + * pending.
+ * Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to check the capture + * interrupt status for channel 1. For 16-bit and 32-bit timers 1, select + * channel 1. (User manual designation of channel 1 is capture slot 2 + * for timer 0). + */ +STATIC INLINE bool Chip_TIMER_CapturePending(LPC_TIMER_T *pTMR, int8_t capnum) +{ + return (bool) ((pTMR->IR & TIMER_CAP_INT(capnum)) != 0); +} + +/** + * @brief Clears a (pending) match interrupt + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match interrupt number to clear + * @return Nothing + * @note Clears a pending timer match interrupt.
+ */ +STATIC INLINE void Chip_TIMER_ClearMatch(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->IR = TIMER_IR_CLR(matchnum); +} + +/** + * @brief Clears a (pending) capture interrupt + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture interrupt number to clear + * @return Nothing + * @note Clears a pending timer capture interrupt.
+ * Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to check the capture + * interrupt status for channel 1. For 16-bit and 32-bit timers 1, select + * channel 1. (User manual designation of channel 1 is capture slot 2 + * for timer 0). + */ +STATIC INLINE void Chip_TIMER_ClearCapture(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->IR = (0x10 << capnum); +} + +/** + * @brief Enables the timer (starts count) + * @param pTMR : Pointer to timer IP register address + * @return Nothing + * @note Enables the timer to start counting. + */ +STATIC INLINE void Chip_TIMER_Enable(LPC_TIMER_T *pTMR) +{ + pTMR->TCR |= TIMER_ENABLE; +} + +/** + * @brief Disables the timer (stops count) + * @param pTMR : Pointer to timer IP register address + * @return Nothing + * @note Disables the timer to stop counting. + */ +STATIC INLINE void Chip_TIMER_Disable(LPC_TIMER_T *pTMR) +{ + pTMR->TCR &= ~TIMER_ENABLE; +} + +/** + * @brief Returns the current timer count + * @param pTMR : Pointer to timer IP register address + * @return Current timer terminal count value + * @note Returns the current timer terminal count. + */ +STATIC INLINE uint32_t Chip_TIMER_ReadCount(LPC_TIMER_T *pTMR) +{ + return pTMR->TC; +} + +/** + * @brief Returns the current prescale count + * @param pTMR : Pointer to timer IP register address + * @return Current timer prescale count value + * @note Returns the current prescale count. + */ +STATIC INLINE uint32_t Chip_TIMER_ReadPrescale(LPC_TIMER_T *pTMR) +{ + return pTMR->PC; +} + +/** + * @brief Sets the prescaler value + * @param pTMR : Pointer to timer IP register address + * @param prescale : Prescale value to set the prescale register to + * @return Nothing + * @note Sets the prescale count value. + */ +STATIC INLINE void Chip_TIMER_PrescaleSet(LPC_TIMER_T *pTMR, uint32_t prescale) +{ + pTMR->PR = prescale; +} + +/** + * @brief Sets a timer match value + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer to set match count for + * @param matchval : Match value for the selected match count + * @return Nothing + * @note Sets one of the timer match values. + */ +STATIC INLINE void Chip_TIMER_SetMatch(LPC_TIMER_T *pTMR, int8_t matchnum, uint32_t matchval) +{ + pTMR->MR[matchnum] = matchval; +} + +/** + * @brief Reads a capture register + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture register to read + * @return The selected capture register value + * @note Returns the selected capture register value.
+ * Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to get the capture + * count for channel 1. For 16-bit and 32-bit timers 1, select + * channel 1. (User manual designation of channel 1 is capture slot 2 + * for timer 0). + */ +STATIC INLINE uint32_t Chip_TIMER_ReadCapture(LPC_TIMER_T *pTMR, int8_t capnum) +{ + return pTMR->CR[capnum]; +} + +/** + * @brief Resets the timer terminal and prescale counts to 0 + * @param pTMR : Pointer to timer IP register address + * @return Nothing + */ +void Chip_TIMER_Reset(LPC_TIMER_T *pTMR); + +/** + * @brief Enables a match interrupt that fires when the terminal count + * matches the match counter value. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_MatchEnableInt(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR |= TIMER_INT_ON_MATCH(matchnum); +} + +/** + * @brief Disables a match interrupt for a match counter. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_MatchDisableInt(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR &= ~TIMER_INT_ON_MATCH(matchnum); +} + +/** + * @brief For the specific match counter, enables reset of the terminal count register when a match occurs + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_ResetOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR |= TIMER_RESET_ON_MATCH(matchnum); +} + +/** + * @brief For the specific match counter, disables reset of the terminal count register when a match occurs + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_ResetOnMatchDisable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR &= ~TIMER_RESET_ON_MATCH(matchnum); +} + +/** + * @brief Enable a match timer to stop the terminal count when a + * match count equals the terminal count. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_StopOnMatchEnable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR |= TIMER_STOP_ON_MATCH(matchnum); +} + +/** + * @brief Disable stop on match for a match timer. Disables a match timer + * to stop the terminal count when a match count equals the terminal count. + * @param pTMR : Pointer to timer IP register address + * @param matchnum : Match timer, 0 to 3 + * @return Nothing + */ +STATIC INLINE void Chip_TIMER_StopOnMatchDisable(LPC_TIMER_T *pTMR, int8_t matchnum) +{ + pTMR->MCR &= ~TIMER_STOP_ON_MATCH(matchnum); +} + +/** + * @brief Enables capture on on rising edge of selected CAP signal for the + * selected capture register, enables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a rising edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and + * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture + * slot 2). + */ +STATIC INLINE void Chip_TIMER_CaptureRisingEdgeEnable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR |= TIMER_CAP_RISING(capnum); +} + +/** + * @brief Disables capture on on rising edge of selected CAP signal. For the + * selected capture register, disables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a rising edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and + * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture + * slot 2). + */ +STATIC INLINE void Chip_TIMER_CaptureRisingEdgeDisable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR &= ~TIMER_CAP_RISING(capnum); +} + +/** + * @brief Enables capture on on falling edge of selected CAP signal. For the + * selected capture register, enables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a falling edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and + * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture + * slot 2). + */ +STATIC INLINE void Chip_TIMER_CaptureFallingEdgeEnable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR |= TIMER_CAP_FALLING(capnum); +} + +/** + * @brief Disables capture on on falling edge of selected CAP signal. For the + * selected capture register, disables the selected CAPn.capnum signal to load + * the capture register with the terminal coount on a falling edge. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and + * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture + * slot 2). + */ +STATIC INLINE void Chip_TIMER_CaptureFallingEdgeDisable(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR &= ~TIMER_CAP_FALLING(capnum); +} + +/** + * @brief Enables interrupt on capture of selected CAP signal. For the + * selected capture register, an interrupt will be generated when the enabled + * rising or falling edge on CAPn.capnum is detected. + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and + * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture + * slot 2). + */ +STATIC INLINE void Chip_TIMER_CaptureEnableInt(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR |= TIMER_INT_ON_CAP(capnum); +} + +/** + * @brief Disables interrupt on capture of selected CAP signal + * @param pTMR : Pointer to timer IP register address + * @param capnum : Capture signal/register to use + * @return Nothing + * @note Special handling for timer 0
+ * For 16-bit and 32-bit timers 0, select channel 2 to set channel 1. For 16-bit and + * 32-bit timers 1, select channel 1. (User manual designation of channel 1 is capture + * slot 2). + */ +STATIC INLINE void Chip_TIMER_CaptureDisableInt(LPC_TIMER_T *pTMR, int8_t capnum) +{ + pTMR->CCR &= ~TIMER_INT_ON_CAP(capnum); +} + +/** + * @brief Standard timer initial match pin state and change state + */ +typedef enum IP_TIMER_PIN_MATCH_STATE { + TIMER_EXTMATCH_DO_NOTHING = 0, /*!< Timer match state does nothing on match pin */ + TIMER_EXTMATCH_CLEAR = 1, /*!< Timer match state sets match pin low */ + TIMER_EXTMATCH_SET = 2, /*!< Timer match state sets match pin high */ + TIMER_EXTMATCH_TOGGLE = 3 /*!< Timer match state toggles match pin */ +} TIMER_PIN_MATCH_STATE_T; + +/** + * @brief Sets external match control (MATn.matchnum) pin control. For the pin + * selected with matchnum, sets the function of the pin that occurs on + * a terminal count match for the match count. + * @param pTMR : Pointer to timer IP register address + * @param initial_state : Initial state of the pin, high(1) or low(0) + * @param matchState : Selects the match state for the pin + * @param matchnum : MATn.matchnum signal to use + * @return Nothing + * @note For the pin selected with matchnum, sets the function of the pin that occurs on + * a terminal count match for the match count. + */ +void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state, + TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum); + +/** + * @brief Standard timer clock and edge for count source + */ +typedef enum IP_TIMER_CAP_SRC_STATE { + TIMER_CAPSRC_RISING_PCLK = 0, /*!< Timer ticks on PCLK rising edge */ + TIMER_CAPSRC_RISING_CAPN = 1, /*!< Timer ticks on CAPn.x rising edge */ + TIMER_CAPSRC_FALLING_CAPN = 2, /*!< Timer ticks on CAPn.x falling edge */ + TIMER_CAPSRC_BOTH_CAPN = 3 /*!< Timer ticks on CAPn.x both edges */ +} TIMER_CAP_SRC_STATE_T; + +/** + * @brief Sets timer count source and edge with the selected passed from CapSrc. + * If CapSrc selected a CAPn pin, select the specific CAPn pin with the capnum value. + * @param pTMR : Pointer to timer IP register address + * @param capSrc : timer clock source and edge + * @param capnum : CAPn.capnum pin to use (if used) + * @return Nothing + * @note If CapSrc selected a CAPn pin, select the specific CAPn pin with the capnum value. + */ +STATIC INLINE void Chip_TIMER_TIMER_SetCountClockSrc(LPC_TIMER_T *pTMR, + TIMER_CAP_SRC_STATE_T capSrc, + int8_t capnum) +{ + pTMR->CTCR = (uint32_t) capSrc | ((uint32_t) capnum) << 2; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIMER_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/uart_0_11u6x.h b/source/lpc_chip_11u6x/inc/uart_0_11u6x.h new file mode 100644 index 0000000..ac719ed --- /dev/null +++ b/source/lpc_chip_11u6x/inc/uart_0_11u6x.h @@ -0,0 +1,777 @@ +/* + * @brief LPC11u6x USART0 chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __UART_0_11U6X_H_ +#define __UART_0_11U6X_H_ + +#include "ring_buffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup UART_11U6X CHIP: LPC11u6x UART 0 driver + * @ingroup CHIP_11U6X_Drivers + * This driver only works with USART 0. Do not mix UART0_* and UARTN_* + * macro definitions across UUSART 0 and USART 1-4 drivers. + * @{ + */ + +/** + * @brief USART 0 register block structure + */ +typedef struct { /*!< USARTn Structure */ + + union { + __IO uint32_t DLL; /*!< Divisor Latch LSB. Least significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider (DLAB = 1). */ + __O uint32_t THR; /*!< Transmit Holding Register. The next character to be transmitted is written here (DLAB = 0). */ + __I uint32_t RBR; /*!< Receiver Buffer Register. Contains the next received character to be read (DLAB = 0). */ + }; + + union { + __IO uint32_t IER; /*!< Interrupt Enable Register. Contains individual interrupt enable bits for the 7 potential UART interrupts (DLAB = 0). */ + __IO uint32_t DLM; /*!< Divisor Latch MSB. Most significant byte of the baud rate divisor value. The full divisor is used to generate a baud rate from the fractional rate divider (DLAB = 1). */ + }; + + union { + __O uint32_t FCR; /*!< FIFO Control Register. Controls UART FIFO usage and modes. */ + __I uint32_t IIR; /*!< Interrupt ID Register. Identifies which interrupt(s) are pending. */ + }; + + __IO uint32_t LCR; /*!< Line Control Register. Contains controls for frame formatting and break generation. */ + __IO uint32_t MCR; /*!< Modem Control Register. Only present on USART ports with full modem support. */ + __I uint32_t LSR; /*!< Line Status Register. Contains flags for transmit and receive status, including line errors. */ + __I uint32_t MSR; /*!< Modem Status Register. Only present on USART ports with full modem support. */ + __IO uint32_t SCR; /*!< Scratch Pad Register. Eight-bit temporary storage for software. */ + __IO uint32_t ACR; /*!< Auto-baud Control Register. Contains controls for the auto-baud feature. */ + __IO uint32_t ICR; /*!< IrDA control register (not all UARTS) */ + __IO uint32_t FDR; /*!< Fractional Divider Register. Generates a clock input for the baud rate divider. */ + __IO uint32_t OSR; /*!< Oversampling Register. Controls the degree of oversampling during each bit time. Only on some UARTS. */ + __IO uint32_t TER; /*!< Transmit Enable Register. Turns off USART transmitter for use with software flow control. */ + __I uint32_t RESERVED0[3]; + __IO uint32_t HDEN; /*!< Half-duplex enable Register- only on some UARTs */ + __I uint32_t RESERVED1[1]; + __IO uint32_t SCICTRL; /*!< Smart card interface control register- only on some UARTs */ + __IO uint32_t RS485CTRL; /*!< RS-485/EIA-485 Control. Contains controls to configure various aspects of RS-485/EIA-485 modes. */ + __IO uint32_t RS485ADRMATCH; /*!< RS-485/EIA-485 address match. Contains the address match value for RS-485/EIA-485 mode. */ + __IO uint32_t RS485DLY; /*!< RS-485/EIA-485 direction control delay. */ + __IO uint32_t SYNCCTRL; /*!< Synchronous mode control register. Only on USARTs. */ +} LPC_USART0_T; + +/** + * @brief Macro defines for UART Receive Buffer register + */ +#define UART0_RBR_MASKBIT (0xFF) /*!< UART Received Buffer mask bit (8 bits) */ + +/** + * @brief Macro defines for UART Divisor Latch LSB register + */ +#define UART0_LOAD_DLL(div) ((div) & 0xFF) /*!< Macro for loading LSB of divisor */ +#define UART0_DLL_MASKBIT (0xFF) /*!< Divisor latch LSB bit mask */ + +/** + * @brief Macro defines for UART Divisor Latch MSB register + */ +#define UART0_LOAD_DLM(div) (((div) >> 8) & 0xFF) /*!< Macro for loading MSB of divisors */ +#define UART0_DLM_MASKBIT (0xFF) /*!< Divisor latch MSB bit mask */ + +/** + * @brief Macro defines for UART Interrupt Enable Register + */ +#define UART0_IER_RBRINT (1 << 0) /*!< RBR Interrupt enable */ +#define UART0_IER_THREINT (1 << 1) /*!< THR Interrupt enable */ +#define UART0_IER_RLSINT (1 << 2) /*!< RX line status interrupt enable */ +#define UART0_IER_MSINT (1 << 3) /*!< Modem status interrupt enable - valid for 11xx, 17xx/40xx UART1, 18xx/43xx UART1 only */ +#define UART0_IER_CTSINT (1 << 7) /*!< CTS signal transition interrupt enable - valid for 17xx/40xx UART1, 18xx/43xx UART1 only */ +#define UART0_IER_ABEOINT (1 << 8) /*!< Enables the end of auto-baud interrupt */ +#define UART0_IER_ABTOINT (1 << 9) /*!< Enables the auto-baud time-out interrupt */ +#define UART0_IER_BITMASK (0x307) /*!< UART interrupt enable register bit mask - valid for 13xx, 17xx/40xx UART0/2/3, 18xx/43xx UART0/2/3 only*/ + +/** + * @brief Macro defines for UART Interrupt Identification Register + */ +#define UART0_IIR_INTSTAT_PEND (1 << 0) /*!< Interrupt pending status - Active low */ +#define UART0_IIR_FIFO_EN (3 << 6) /*!< These bits are equivalent to FCR[0] */ +#define UART0_IIR_ABEO_INT (1 << 8) /*!< End of auto-baud interrupt */ +#define UART0_IIR_ABTO_INT (1 << 9) /*!< Auto-baud time-out interrupt */ +#define UART0_IIR_BITMASK (0x3CF) /*!< UART interrupt identification register bit mask */ + +/* Interrupt ID bit definitions */ +#define UART0_IIR_INTID_MASK (7 << 1) /*!< Interrupt identification: Interrupt ID mask */ +#define UART0_IIR_INTID_RLS (3 << 1) /*!< Interrupt identification: Receive line interrupt */ +#define UART0_IIR_INTID_RDA (2 << 1) /*!< Interrupt identification: Receive data available interrupt */ +#define UART0_IIR_INTID_CTI (6 << 1) /*!< Interrupt identification: Character time-out indicator interrupt */ +#define UART0_IIR_INTID_THRE (1 << 1) /*!< Interrupt identification: THRE interrupt */ +#define UART0_IIR_INTID_MODEM (0 << 1) /*!< Interrupt identification: Modem interrupt */ + +/** + * @brief Macro defines for UART FIFO Control Register + */ +#define UART0_FCR_FIFO_EN (1 << 0) /*!< UART FIFO enable */ +#define UART0_FCR_RX_RS (1 << 1) /*!< UART RX FIFO reset */ +#define UART0_FCR_TX_RS (1 << 2) /*!< UART TX FIFO reset */ +#define UART0_FCR_DMAMODE_SEL (1 << 3) /*!< UART DMA mode selection */ +#define UART0_FCR_BITMASK (0xCF) /*!< UART FIFO control bit mask */ + +#define UART0_TX_FIFO_SIZE (16) + +/* FIFO trigger level bit definitions */ +#define UART0_FCR_TRG_LEV0 (0) /*!< UART FIFO trigger level 0: 1 character */ +#define UART0_FCR_TRG_LEV1 (1 << 6) /*!< UART FIFO trigger level 1: 4 character */ +#define UART0_FCR_TRG_LEV2 (2 << 6) /*!< UART FIFO trigger level 2: 8 character */ +#define UART0_FCR_TRG_LEV3 (3 << 6) /*!< UART FIFO trigger level 3: 14 character */ + +/** + * @brief Macro defines for UART Line Control Register + */ +/* UART word length select bit definitions */ +#define UART0_LCR_WLEN_MASK (3 << 0) /*!< UART word length select bit mask */ +#define UART0_LCR_WLEN5 (0 << 0) /*!< UART word length select: 5 bit data mode */ +#define UART0_LCR_WLEN6 (1 << 0) /*!< UART word length select: 6 bit data mode */ +#define UART0_LCR_WLEN7 (2 << 0) /*!< UART word length select: 7 bit data mode */ +#define UART0_LCR_WLEN8 (3 << 0) /*!< UART word length select: 8 bit data mode */ + +/* UART Stop bit select bit definitions */ +#define UART0_LCR_SBS_MASK (1 << 2) /*!< UART stop bit select: bit mask */ +#define UART0_LCR_SBS_1BIT (0 << 2) /*!< UART stop bit select: 1 stop bit */ +#define UART0_LCR_SBS_2BIT (1 << 2) /*!< UART stop bit select: 2 stop bits (in 5 bit data mode, 1.5 stop bits) */ + +/* UART Parity enable bit definitions */ +#define UART0_LCR_PARITY_EN (1 << 3) /*!< UART Parity Enable */ +#define UART0_LCR_PARITY_DIS (0 << 3) /*!< UART Parity Disable */ +#define UART0_LCR_PARITY_ODD (0 << 4) /*!< UART Parity select: Odd parity */ +#define UART0_LCR_PARITY_EVEN (1 << 4) /*!< UART Parity select: Even parity */ +#define UART0_LCR_PARITY_F_1 (2 << 4) /*!< UART Parity select: Forced 1 stick parity */ +#define UART0_LCR_PARITY_F_0 (3 << 4) /*!< UART Parity select: Forced 0 stick parity */ +#define UART0_LCR_BREAK_EN (1 << 6) /*!< UART Break transmission enable */ +#define UART0_LCR_DLAB_EN (1 << 7) /*!< UART Divisor Latches Access bit enable */ +#define UART0_LCR_BITMASK (0xFF) /*!< UART line control bit mask */ + +/** + * @brief Macro defines for UART Modem Control Register + */ +#define UART0_MCR_DTR_CTRL (1 << 0) /*!< Source for modem output pin DTR */ +#define UART0_MCR_RTS_CTRL (1 << 1) /*!< Source for modem output pin RTS */ +#define UART0_MCR_LOOPB_EN (1 << 4) /*!< Loop back mode select */ +#define UART0_MCR_AUTO_RTS_EN (1 << 6) /*!< Enable Auto RTS flow-control */ +#define UART0_MCR_AUTO_CTS_EN (1 << 7) /*!< Enable Auto CTS flow-control */ +#define UART0_MCR_BITMASK (0xD3) /*!< UART bit mask value */ + +/** + * @brief Macro defines for UART Line Status Register + */ +#define UART0_LSR_RDR (1 << 0) /*!< Line status: Receive data ready */ +#define UART0_LSR_OE (1 << 1) /*!< Line status: Overrun error */ +#define UART0_LSR_PE (1 << 2) /*!< Line status: Parity error */ +#define UART0_LSR_FE (1 << 3) /*!< Line status: Framing error */ +#define UART0_LSR_BI (1 << 4) /*!< Line status: Break interrupt */ +#define UART0_LSR_THRE (1 << 5) /*!< Line status: Transmit holding register empty */ +#define UART0_LSR_TEMT (1 << 6) /*!< Line status: Transmitter empty */ +#define UART0_LSR_RXFE (1 << 7) /*!< Line status: Error in RX FIFO */ +#define UART0_LSR_TXFE (1 << 8) /*!< Line status: Error in RX FIFO */ +#define UART0_LSR_BITMASK (0xFF) /*!< UART Line status bit mask */ + +/** + * @brief Macro defines for UART Modem Status Register + */ +#define UART0_MSR_DELTA_CTS (1 << 0) /*!< Modem status: State change of input CTS */ +#define UART0_MSR_DELTA_DSR (1 << 1) /*!< Modem status: State change of input DSR */ +#define UART0_MSR_LO2HI_RI (1 << 2) /*!< Modem status: Low to high transition of input RI */ +#define UART0_MSR_DELTA_DCD (1 << 3) /*!< Modem status: State change of input DCD */ +#define UART0_MSR_CTS (1 << 4) /*!< Modem status: Clear To Send State */ +#define UART0_MSR_DSR (1 << 5) /*!< Modem status: Data Set Ready State */ +#define UART0_MSR_RI (1 << 6) /*!< Modem status: Ring Indicator State */ +#define UART0_MSR_DCD (1 << 7) /*!< Modem status: Data Carrier Detect State */ +#define UART0_MSR_BITMASK (0xFF) /*!< Modem status: MSR register bit-mask value */ + +/** + * @brief Macro defines for UART Auto baudrate control register + */ +#define UART0_ACR_START (1 << 0) /*!< UART Auto-baud start */ +#define UART0_ACR_MODE (1 << 1) /*!< UART Auto baudrate Mode 1 */ +#define UART0_ACR_AUTO_RESTART (1 << 2) /*!< UART Auto baudrate restart */ +#define UART0_ACR_ABEOINT_CLR (1 << 8) /*!< UART End of auto-baud interrupt clear */ +#define UART0_ACR_ABTOINT_CLR (1 << 9) /*!< UART Auto-baud time-out interrupt clear */ +#define UART0_ACR_BITMASK (0x307) /*!< UART Auto Baudrate register bit mask */ + +/** + * @brief Macro defines for UART RS485 Control register + */ +#define UART0_RS485CTRL_NMM_EN (1 << 0) /*!< RS-485/EIA-485 Normal Multi-drop Mode (NMM) is disabled */ +#define UART0_RS485CTRL_RX_DIS (1 << 1) /*!< The receiver is disabled */ +#define UART0_RS485CTRL_AADEN (1 << 2) /*!< Auto Address Detect (AAD) is enabled */ +#define UART0_RS485CTRL_SEL_DTR (1 << 3) /*!< If direction control is enabled (bit DCTRL = 1), pin DTR is + used for direction control */ +#define UART0_RS485CTRL_DCTRL_EN (1 << 4) /*!< Enable Auto Direction Control */ +#define UART0_RS485CTRL_OINV_1 (1 << 5) /*!< This bit reverses the polarity of the direction + control signal on the RTS (or DTR) pin. The direction control pin + will be driven to logic "1" when the transmitter has data to be sent */ +#define UART0_RS485CTRL_BITMASK (0x3F) /*!< RS485 control bit-mask value */ + +/** + * @brief Macro defines for UART IrDA Control Register + */ +#define UART0_ICR_IRDAEN (1 << 0) /*!< IrDA mode enable */ +#define UART0_ICR_IRDAINV (1 << 1) /*!< IrDA serial input inverted */ +#define UART0_ICR_FIXPULSE_EN (1 << 2) /*!< IrDA fixed pulse width mode */ +#define UART0_ICR_PULSEDIV(n) ((n & 0x07) << 3) /*!< PulseDiv - Configures the pulse when FixPulseEn = 1 */ +#define UART0_ICR_BITMASK (0x3F) /*!< UART IRDA bit mask */ + +/** + * @brief Macro defines for UART half duplex register - ???? + */ +#define UART0_HDEN_HDEN ((1 << 0)) /*!< enable half-duplex mode*/ + +/** + * @brief Macro defines for UART Smart card interface Control Register + */ +#define UART0_SCICTRL_SCIEN (1 << 0) /*!< enable asynchronous half-duplex smart card interface*/ +#define UART0_SCICTRL_NACKDIS (1 << 1) /*!< NACK response is inhibited*/ +#define UART0_SCICTRL_PROTSEL_T1 (1 << 2) /*!< ISO7816-3 protocol T1 is selected*/ +#define UART0_SCICTRL_TXRETRY(n) ((n & 0x07) << 5) /*!< number of retransmission*/ +#define UART0_SCICTRL_GUARDTIME(n) ((n & 0xFF) << 8) /*!< Extra guard time*/ + +/** + * @brief Macro defines for UART Fractional Divider Register + */ +#define UART0_FDR_DIVADDVAL(n) (n & 0x0F) /*!< Baud-rate generation pre-scaler divisor */ +#define UART0_FDR_MULVAL(n) ((n << 4) & 0xF0) /*!< Baud-rate pre-scaler multiplier value */ +#define UART0_FDR_BITMASK (0xFF) /*!< UART Fractional Divider register bit mask */ + +/** + * @brief Macro defines for UART Tx Enable Register + */ +#define UART0_TER1_TXEN (1 << 7) /*!< Transmit enable bit */ + +/** + * @brief Macro defines for UART Synchronous Control Register + */ +#define UART0_SYNCCTRL_SYNC (1 << 0) /*!< enable synchronous mode*/ +#define UART0_SYNCCTRL_CSRC_MASTER (1 << 1) /*!< synchronous master mode*/ +#define UART0_SYNCCTRL_FES (1 << 2) /*!< sample on falling edge*/ +#define UART0_SYNCCTRL_TSBYPASS (1 << 3) /*!< to be defined*/ +#define UART0_SYNCCTRL_CSCEN (1 << 4) /*!< Continuous running clock enable (master mode only)*/ +#define UART0_SYNCCTRL_STARTSTOPDISABLE (1 << 5) /*!< Do not send start/stop bit*/ +#define UART0_SYNCCTRL_CCCLR (1 << 6) /*!< stop continuous clock*/ + +/** + * @brief Enable transmission on UART TxD pin + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART0_TXEnable(LPC_USART0_T *pUART) +{ + pUART->TER = UART0_TER1_TXEN; +} + +/** + * @brief Disable transmission on UART TxD pin + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART0_TXDisable(LPC_USART0_T *pUART) +{ + pUART->TER = 0; +} + +/** + * @brief Transmit a single data byte through the UART peripheral + * @param pUART : Pointer to selected UART peripheral + * @param data : Byte to transmit + * @return Nothing + * @note This function attempts to place a byte into the UART transmit + * FIFO or transmit hold register regard regardless of UART state + */ +STATIC INLINE void Chip_UART0_SendByte(LPC_USART0_T *pUART, uint8_t data) +{ + pUART->THR = (uint32_t) data; +} + +/** + * @brief Read a single byte data from the UART peripheral + * @param pUART : Pointer to selected UART peripheral + * @return A single byte of data read + * @note This function reads a byte from the UART receive FIFO or + * receive hold register regard regardless of UART state. The + * FIFO status should be read first prior to using this function + */ +STATIC INLINE uint8_t Chip_UART0_ReadByte(LPC_USART0_T *pUART) +{ + return (uint8_t) (pUART->RBR & UART0_RBR_MASKBIT); +} + +/** + * @brief Enable UART interrupts + * @param pUART : Pointer to selected UART peripheral + * @param intMask : OR'ed Interrupts to enable in the Interrupt Enable Register (IER) + * @return Nothing + * @note Use an OR'ed value of UART0_IER_* definitions with this function + * to enable specific UART interrupts. The Divisor Latch Access Bit + * (DLAB) in LCR must be cleared in order to access the IER register. + * This function doesn't alter the DLAB state + */ +STATIC INLINE void Chip_UART0_IntEnable(LPC_USART0_T *pUART, uint32_t intMask) +{ + pUART->IER |= intMask; +} + +/** + * @brief Disable UART interrupts + * @param pUART : Pointer to selected UART peripheral + * @param intMask : OR'ed Interrupts to disable in the Interrupt Enable Register (IER) + * @return Nothing + * @note Use an OR'ed value of UART0_IER_* definitions with this function + * to disable specific UART interrupts. The Divisor Latch Access Bit + * (DLAB) in LCR must be cleared in order to access the IER register. + * This function doesn't alter the DLAB state + */ +STATIC INLINE void Chip_UART0_IntDisable(LPC_USART0_T *pUART, uint32_t intMask) +{ + pUART->IER &= ~intMask; +} + +/** + * @brief Returns UART interrupts that are enabled + * @param pUART : Pointer to selected UART peripheral + * @return Returns the enabled UART interrupts + * @note Use an OR'ed value of UART0_IER_* definitions with this function + * to determine which interrupts are enabled. You can check + * for multiple enabled bits if needed. + */ +STATIC INLINE uint32_t Chip_UART0_GetIntsEnabled(LPC_USART0_T *pUART) +{ + return pUART->IER; +} + +/** + * @brief Read the Interrupt Identification Register (IIR) + * @param pUART : Pointer to selected UART peripheral + * @return Current pending interrupt status per the IIR register + */ +STATIC INLINE uint32_t Chip_UART0_ReadIntIDReg(LPC_USART0_T *pUART) +{ + return pUART->IIR; +} + +/** + * @brief Setup the UART FIFOs + * @param pUART : Pointer to selected UART peripheral + * @param fcr : FIFO control register setup OR'ed flags + * @return Nothing + * @note Use OR'ed value of UART0_FCR_* definitions with this function + * to select specific options. For example, to enable the FIFOs + * with a RX trip level of 8 characters, use something like + * (UART0_FCR_FIFO_EN | UART0_FCR_TRG_LEV2) + */ +STATIC INLINE void Chip_UART0_SetupFIFOS(LPC_USART0_T *pUART, uint32_t fcr) +{ + pUART->FCR = fcr; +} + +/** + * @brief Configure data width, parity and stop bits + * @param pUART : Pointer to selected pUART peripheral + * @param config : UART configuration, OR'ed values of UART0_LCR_* defines + * @return Nothing + * @note Select OR'ed config options for the UART from the UART0_LCR_* + * definitions. For example, a configuration of 8 data bits, 1 + * stop bit, and even (enabled) parity would be + * (UART0_LCR_WLEN8 | UART0_LCR_SBS_1BIT | UART0_LCR_PARITY_EN | UART0_LCR_PARITY_EVEN) + */ +STATIC INLINE void Chip_UART0_ConfigData(LPC_USART0_T *pUART, uint32_t config) +{ + pUART->LCR = config; +} + +/** + * @brief Enable access to Divisor Latches + * @param pUART : Pointer to selected UART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART0_EnableDivisorAccess(LPC_USART0_T *pUART) +{ + pUART->LCR |= UART0_LCR_DLAB_EN; +} + +/** + * @brief Disable access to Divisor Latches + * @param pUART : Pointer to selected UART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UART0_DisableDivisorAccess(LPC_USART0_T *pUART) +{ + pUART->LCR &= ~UART0_LCR_DLAB_EN; +} + +/** + * @brief Set LSB and MSB divisor latch registers + * @param pUART : Pointer to selected UART peripheral + * @param dll : Divisor Latch LSB value + * @param dlm : Divisor Latch MSB value + * @return Nothing + * @note The Divisor Latch Access Bit (DLAB) in LCR must be set in + * order to access the USART Divisor Latches. This function + * doesn't alter the DLAB state. + */ +STATIC INLINE void Chip_UART0_SetDivisorLatches(LPC_USART0_T *pUART, uint8_t dll, uint8_t dlm) +{ + pUART->DLL = (uint32_t) dll; + pUART->DLM = (uint32_t) dlm; +} + +/** + * @brief Return modem control register/status + * @param pUART : Pointer to selected UART peripheral + * @return Modem control register (status) + * @note Mask bits of the returned status value with UART0_MCR_* + * definitions for specific statuses. + */ +STATIC INLINE uint32_t Chip_UART0_ReadModemControl(LPC_USART0_T *pUART) +{ + return pUART->MCR; +} + +/** + * @brief Set modem control register/status + * @param pUART : Pointer to selected UART peripheral + * @param mcr : Modem control register flags to set + * @return Nothing + * @note Use an Or'ed value of UART0_MCR_* definitions with this + * call to set specific options. + */ +STATIC INLINE void Chip_UART0_SetModemControl(LPC_USART0_T *pUART, uint32_t mcr) +{ + pUART->MCR |= mcr; +} + +/** + * @brief Clear modem control register/status + * @param pUART : Pointer to selected UART peripheral + * @param mcr : Modem control register flags to clear + * @return Nothing + * @note Use an Or'ed value of UART0_MCR_* definitions with this + * call to clear specific options. + */ +STATIC INLINE void Chip_UART0_ClearModemControl(LPC_USART0_T *pUART, uint32_t mcr) +{ + pUART->MCR &= ~mcr; +} + +/** + * @brief Return Line Status register/status (LSR) + * @param pUART : Pointer to selected UART peripheral + * @return Line Status register (status) + * @note Mask bits of the returned status value with UART0_LSR_* + * definitions for specific statuses. + */ +STATIC INLINE uint32_t Chip_UART0_ReadLineStatus(LPC_USART0_T *pUART) +{ + return pUART->LSR; +} + +/** + * @brief Return Modem Status register/status (MSR) + * @param pUART : Pointer to selected UART peripheral + * @return Modem Status register (status) + * @note Mask bits of the returned status value with UART0_MSR_* + * definitions for specific statuses. + */ +STATIC INLINE uint32_t Chip_UART0_ReadModemStatus(LPC_USART0_T *pUART) +{ + return pUART->MSR; +} + +/** + * @brief Write a byte to the scratchpad register + * @param pUART : Pointer to selected UART peripheral + * @param data : Byte value to write + * @return Nothing + */ +STATIC INLINE void Chip_UART0_SetScratch(LPC_USART0_T *pUART, uint8_t data) +{ + pUART->SCR = (uint32_t) data; +} + +/** + * @brief Returns current byte value in the scratchpad register + * @param pUART : Pointer to selected UART peripheral + * @return Byte value read from scratchpad register + */ +STATIC INLINE uint8_t Chip_UART0_ReadScratch(LPC_USART0_T *pUART) +{ + return (uint8_t) (pUART->SCR & 0xFF); +} + +/** + * @brief Set autobaud register options + * @param pUART : Pointer to selected UART peripheral + * @param acr : Or'ed values to set for ACR register + * @return Nothing + * @note Use an Or'ed value of UART0_ACR_* definitions with this + * call to set specific options. + */ +STATIC INLINE void Chip_UART0_SetAutoBaudReg(LPC_USART0_T *pUART, uint32_t acr) +{ + pUART->ACR |= acr; +} + +/** + * @brief Clear autobaud register options + * @param pUART : Pointer to selected UART peripheral + * @param acr : Or'ed values to clear for ACR register + * @return Nothing + * @note Use an Or'ed value of UART0_ACR_* definitions with this + * call to clear specific options. + */ +STATIC INLINE void Chip_UART0_ClearAutoBaudReg(LPC_USART0_T *pUART, uint32_t acr) +{ + pUART->ACR &= ~acr; +} + +/** + * @brief Set RS485 control register options + * @param pUART : Pointer to selected UART peripheral + * @param ctrl : Or'ed values to set for RS485 control register + * @return Nothing + * @note Use an Or'ed value of UART0_RS485CTRL_* definitions with this + * call to set specific options. + */ +STATIC INLINE void Chip_UART0_SetRS485Flags(LPC_USART0_T *pUART, uint32_t ctrl) +{ + pUART->RS485CTRL |= ctrl; +} + +/** + * @brief Clear RS485 control register options + * @param pUART : Pointer to selected UART peripheral + * @param ctrl : Or'ed values to clear for RS485 control register + * @return Nothing + * @note Use an Or'ed value of UART0_RS485CTRL_* definitions with this + * call to clear specific options. + */ +STATIC INLINE void Chip_UART0_ClearRS485Flags(LPC_USART0_T *pUART, uint32_t ctrl) +{ + pUART->RS485CTRL &= ~ctrl; +} + +/** + * @brief Set RS485 address match value + * @param pUART : Pointer to selected UART peripheral + * @param addr : Address match value for RS-485/EIA-485 mode + * @return Nothing + */ +STATIC INLINE void Chip_UART0_SetRS485Addr(LPC_USART0_T *pUART, uint8_t addr) +{ + pUART->RS485ADRMATCH = (uint32_t) addr; +} + +/** + * @brief Read RS485 address match value + * @param pUART : Pointer to selected UART peripheral + * @return Address match value for RS-485/EIA-485 mode + */ +STATIC INLINE uint8_t Chip_UART0_GetRS485Addr(LPC_USART0_T *pUART) +{ + return (uint8_t) (pUART->RS485ADRMATCH & 0xFF); +} + +/** + * @brief Set RS485 direction control (RTS or DTR) delay value + * @param pUART : Pointer to selected UART peripheral + * @param dly : direction control (RTS or DTR) delay value + * @return Nothing + * @note This delay time is in periods of the baud clock. Any delay + * time from 0 to 255 bit times may be programmed. + */ +STATIC INLINE void Chip_UART0_SetRS485Delay(LPC_USART0_T *pUART, uint8_t dly) +{ + pUART->RS485DLY = (uint32_t) dly; +} + +/** + * @brief Read RS485 direction control (RTS or DTR) delay value + * @param pUART : Pointer to selected UART peripheral + * @return direction control (RTS or DTR) delay value + * @note This delay time is in periods of the baud clock. Any delay + * time from 0 to 255 bit times may be programmed. + */ +STATIC INLINE uint8_t Chip_UART0_GetRS485Delay(LPC_USART0_T *pUART) +{ + return (uint8_t) (pUART->RS485DLY & 0xFF); +} + +/** + * @brief Initializes the pUART peripheral + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +void Chip_UART0_Init(LPC_USART0_T *pUART); + +/** + * @brief De-initializes the pUART peripheral. + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +void Chip_UART0_DeInit(LPC_USART0_T *pUART); + +/** + * @brief Transmit a byte array through the UART peripheral (non-blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to bytes to transmit + * @param numBytes : Number of bytes to transmit + * @return The actual number of bytes placed into the FIFO + * @note This function places data into the transmit FIFO until either + * all the data is in the FIFO or the FIFO is full. This function + * will not block in the FIFO is full. The actual number of bytes + * placed into the FIFO is returned. This function ignores errors. + */ +int Chip_UART0_Send(LPC_USART0_T *pUART, const void *data, int numBytes); + +/** + * @brief Read data through the UART peripheral (non-blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to bytes array to fill + * @param numBytes : Size of the passed data array + * @return The actual number of bytes read + * @note This function reads data from the receive FIFO until either + * all the data has been read or the passed buffer is completely full. + * This function will not block. This function ignores errors. + */ +int Chip_UART0_Read(LPC_USART0_T *pUART, void *data, int numBytes); + +/** + * @brief Sets best dividers to get a target bit rate (without fractional divider) + * @param pUART : Pointer to selected UART peripheral + * @param baudrate : Target baud rate (baud rate = bit rate) + * @return The actual baud rate, or 0 if no rate can be found + */ +uint32_t Chip_UART0_SetBaud(LPC_USART0_T *pUART, uint32_t baudrate); + +/** + * @brief Sets best dividers to get a target bit rate (with fractional divider) + * @param pUART : Pointer to selected UART peripheral + * @param baudrate : Target baud rate (baud rate = bit rate) + * @return The actual baud rate, or 0 if no rate can be found + */ +uint32_t Chip_UART0_SetBaudFDR(LPC_USART0_T *pUART, uint32_t baudrate); + +/** + * @brief Transmit a byte array through the UART peripheral (blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to data to transmit + * @param numBytes : Number of bytes to transmit + * @return The number of bytes transmitted + * @note This function will send or place all bytes into the transmit + * FIFO. This function will block until the last bytes are in the FIFO. + */ +int Chip_UART0_SendBlocking(LPC_USART0_T *pUART, const void *data, int numBytes); + +/** + * @brief Read data through the UART peripheral (blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to data array to fill + * @param numBytes : Size of the passed data array + * @return The size of the dat array + * @note This function reads data from the receive FIFO until the passed + * buffer is completely full. The function will block until full. + * This function ignores errors. + */ +int Chip_UART0_ReadBlocking(LPC_USART0_T *pUART, void *data, int numBytes); + +/** + * @brief UART receive-only interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @return Nothing + * @note If ring buffer support is desired for the receive side + * of data transfer, the UART interrupt should call this + * function for a receive based interrupt status. + */ +void Chip_UART0_RXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB); + +/** + * @brief UART transmit-only interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @return Nothing + * @note If ring buffer support is desired for the transmit side + * of data transfer, the UART interrupt should call this + * function for a transmit based interrupt status. + */ +void Chip_UART0_TXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB); + +/** + * @brief Populate a transmit ring buffer and start UART transmit + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @param data : Pointer to buffer to move to ring buffer + * @param bytes : Number of bytes to move + * @return The number of bytes placed into the ring buffer + * @note Will move the data into the TX ring buffer and start the + * transfer. If the number of bytes returned is less than the + * number of bytes to send, the ring buffer is considered full. + */ +uint32_t Chip_UART0_SendRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes); + +/** + * @brief Copy data from a receive ring buffer + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @param data : Pointer to buffer to fill from ring buffer + * @param bytes : Size of the passed buffer in bytes + * @return The number of bytes placed into the ring buffer + * @note Will move the data from the RX ring buffer up to the + * the maximum passed buffer size. Returns 0 if there is + * no data in the ring buffer. + */ +int Chip_UART0_ReadRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, void *data, int bytes); + +/** + * @brief UART receive/transmit interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRXRB : Pointer to transmit ring buffer + * @param pTXRB : Pointer to receive ring buffer + * @return Nothing + * @note This provides a basic implementation of the UART IRQ + * handler for support of a ring buffer implementation for + * transmit and receive. + */ +void Chip_UART0_IRQRBHandler(LPC_USART0_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __UART_0_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/uart_n_11u6x.h b/source/lpc_chip_11u6x/inc/uart_n_11u6x.h new file mode 100644 index 0000000..691c116 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/uart_n_11u6x.h @@ -0,0 +1,440 @@ +/* + * @brief LPC11u6xx USART1/2/3/4 driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __UART_N_11U6X_H_ +#define __UART_N_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ring_buffer.h" + +/** @defgroup UART_11U6X_2 CHIP: LPC11u6x USART N Driver (UARTS 1/2/3/4) + * @ingroup CHIP_11U6X_Drivers + * This driver only works with USARTs 1-4. Do not mix UART0_* and UARTN_* + * macro definitions across UUSART 0 and USART 1-4 drivers. + * @{ + */ + +/** + * @brief UART register block structure + */ +typedef struct { + __IO uint32_t CFG; /*!< Configuration register */ + __IO uint32_t CTRL; /*!< Control register */ + __IO uint32_t STAT; /*!< Status register */ + __IO uint32_t INTENSET; /*!< Interrupt Enable read and set register */ + __O uint32_t INTENCLR; /*!< Interrupt Enable clear register */ + __I uint32_t RXDATA; /*!< Receive Data register */ + __I uint32_t RXDATA_STAT; /*!< Receive Data with status register */ + __IO uint32_t TXDATA; /*!< Transmit data register */ + __IO uint32_t BRG; /*!< Baud Rate Generator register */ + __IO uint32_t INTSTAT; /*!< Interrupt status register */ + __IO uint32_t OSR; /*!< Oversample selection register for asynchronous communication */ + __IO uint32_t ADDR; /*!< Address register for automatic address matching */ +} LPC_USARTN_T; + +/** + * @brief UART CFG register definitions + */ +#define UARTN_CFG_ENABLE (0x01 << 0) +#define UARTN_CFG_DATALEN_7 (0x00 << 2) /*!< UART 7 bit length mode */ +#define UARTN_CFG_DATALEN_8 (0x01 << 2) /*!< UART 8 bit length mode */ +#define UARTN_CFG_DATALEN_9 (0x02 << 2) /*!< UART 9 bit length mode */ +#define UARTN_CFG_PARITY_NONE (0x00 << 4) /*!< No parity */ +#define UARTN_CFG_PARITY_EVEN (0x02 << 4) /*!< Even parity */ +#define UARTN_CFG_PARITY_ODD (0x03 << 4) /*!< Odd parity */ +#define UARTN_CFG_STOPLEN_1 (0x00 << 6) /*!< UART One Stop Bit Select */ +#define UARTN_CFG_STOPLEN_2 (0x01 << 6) /*!< UART Two Stop Bits Select */ +#define UARTN_MODE_32K (0x01 << 7) /*!< Selects the 32 kHz clock from the RTC oscillator as the clock source to the BRG */ +#define UARTN_CFG_CTSEN (0x01 << 9) /*!< CTS enable bit */ +#define UARTN_CFG_SYNCEN (0x01 << 11) /*!< Synchronous mode enable bit */ +#define UARTN_CFG_CLKPOL (0x01 << 12) /*!< Un_RXD rising edge sample enable bit */ +#define UARTN_CFG_SYNCMST (0x01 << 14) /*!< Select master mode (synchronous mode) enable bit */ +#define UARTN_CFG_LOOP (0x01 << 15) /*!< Loopback mode enable bit */ + +/** + * @brief UART CTRL register definitions + */ +#define UARTN_CTRL_TXBRKEN (0x01 << 1) /*!< Continuous break enable bit */ +#define UARTN_CTRL_ADDRDET (0x01 << 2) /*!< Address detect mode enable bit */ +#define UARTN_CTRL_TXDIS (0x01 << 6) /*!< Transmit disable bit */ +#define UARTN_CTRL_CC (0x01 << 8) /*!< Continuous Clock mode enable bit */ +#define UARTN_CTRL_CLRCC (0x01 << 9) /*!< Clear Continuous Clock bit */ + +/** + * @brief UART STAT register definitions + */ +#define UARTN_STAT_RXRDY (0x01 << 0) /*!< Receiver ready */ +#define UARTN_STAT_RXIDLE (0x01 << 1) /*!< Receiver idle */ +#define UARTN_STAT_TXRDY (0x01 << 2) /*!< Transmitter ready for data */ +#define UARTN_STAT_TXIDLE (0x01 << 3) /*!< Transmitter idle */ +#define UARTN_STAT_CTS (0x01 << 4) /*!< Status of CTS signal */ +#define UARTN_STAT_DELTACTS (0x01 << 5) /*!< Change in CTS state */ +#define UARTN_STAT_TXDISINT (0x01 << 6) /*!< Transmitter disabled */ +#define UARTN_STAT_OVERRUNINT (0x01 << 8) /*!< Overrun Error interrupt flag. */ +#define UARTN_STAT_RXBRK (0x01 << 10) /*!< Received break */ +#define UARTN_STAT_DELTARXBRK (0x01 << 11) /*!< Change in receive break detection */ +#define UARTN_STAT_START (0x01 << 12) /*!< Start detected */ +#define UARTN_STAT_FRM_ERRINT (0x01 << 13) /*!< Framing Error interrupt flag */ +#define UARTN_STAT_PAR_ERRINT (0x01 << 14) /*!< Parity Error interrupt flag */ +#define UARTN_STAT_RXNOISEINT (0x01 << 15) /*!< Received Noise interrupt flag */ + +/** + * @brief UART INTENSET/INTENCLR register definitions + */ +#define UARTN_INTEN_RXRDY (0x01 << 0) /*!< Receive Ready interrupt */ +#define UARTN_INTEN_TXRDY (0x01 << 2) /*!< Transmit Ready interrupt */ +#define UARTN_INTEN_DELTACTS (0x01 << 5) /*!< Change in CTS state interrupt */ +#define UARTN_INTEN_TXDIS (0x01 << 6) /*!< Transmitter disable interrupt */ +#define UARTN_INTEN_OVERRUN (0x01 << 8) /*!< Overrun error interrupt */ +#define UARTN_INTEN_DELTARXBRK (0x01 << 11) /*!< Change in receiver break detection interrupt */ +#define UARTN_INTEN_START (0x01 << 12) /*!< Start detect interrupt */ +#define UARTN_INTEN_FRAMERR (0x01 << 13) /*!< Frame error interrupt */ +#define UARTN_INTEN_PARITYERR (0x01 << 14) /*!< Parity error interrupt */ +#define UARTN_INTEN_RXNOISE (0x01 << 15) /*!< Received noise interrupt */ + +/** + * @brief Enable the UART + * @param pUART : Pointer to selected UARTx peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UARTN_Enable(LPC_USARTN_T *pUART) +{ + pUART->CFG |= UARTN_CFG_ENABLE; +} + +/** + * @brief Disable the UART + * @param pUART : Pointer to selected UARTx peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UARTN_Disable(LPC_USARTN_T *pUART) +{ + pUART->CFG &= ~UARTN_CFG_ENABLE; +} + +/** + * @brief Enable transmission on UART TxD pin + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UARTN_TXEnable(LPC_USARTN_T *pUART) +{ + pUART->CTRL &= ~UARTN_CTRL_TXDIS; +} + +/** + * @brief Disable transmission on UART TxD pin + * @param pUART : Pointer to selected pUART peripheral + * @return Nothing + */ +STATIC INLINE void Chip_UARTN_TXDisable(LPC_USARTN_T *pUART) +{ + pUART->CTRL |= UARTN_CTRL_TXDIS; +} + +/** + * @brief Transmit a single data byte through the UART peripheral + * @param pUART : Pointer to selected UART peripheral + * @param data : Byte to transmit + * @return Nothing + * @note This function attempts to place a byte into the UART transmit + * holding register regard regardless of UART state. + */ +STATIC INLINE void Chip_UARTN_SendByte(LPC_USARTN_T *pUART, uint8_t data) +{ + pUART->TXDATA = (uint32_t) data; +} + +/** + * @brief Read a single byte data from the UART peripheral + * @param pUART : Pointer to selected UART peripheral + * @return A single byte of data read + * @note This function reads a byte from the UART receive FIFO or + * receive hold register regard regardless of UART state. The + * FIFO status should be read first prior to using this function + */ +STATIC INLINE uint32_t Chip_UARTN_ReadByte(LPC_USARTN_T *pUART) +{ + /* Strip off undefined reserved bits, keep 9 lower bits */ + return (uint32_t) (pUART->RXDATA & 0x000001FF); +} + +/** + * @brief Enable UART interrupts + * @param pUART : Pointer to selected UART peripheral + * @param intMask : OR'ed Interrupts to enable + * @return Nothing + * @note Use an OR'ed value of UARTN_INTEN_* definitions with this function + * to enable specific UART interrupts. + */ +STATIC INLINE void Chip_UARTN_IntEnable(LPC_USARTN_T *pUART, uint32_t intMask) +{ + pUART->INTENSET = intMask; +} + +/** + * @brief Disable UART interrupts + * @param pUART : Pointer to selected UART peripheral + * @param intMask : OR'ed Interrupts to disable + * @return Nothing + * @note Use an OR'ed value of UARTN_INTEN_* definitions with this function + * to disable specific UART interrupts. + */ +STATIC INLINE void Chip_UARTN_IntDisable(LPC_USARTN_T *pUART, uint32_t intMask) +{ + pUART->INTENCLR = intMask; +} + +/** + * @brief Returns UART interrupts that are enabled + * @param pUART : Pointer to selected UART peripheral + * @return Returns the enabled UART interrupts + * @note Use an OR'ed value of UARTN_INTEN_* definitions with this function + * to determine which interrupts are enabled. You can check + * for multiple enabled bits if needed. + */ +STATIC INLINE uint32_t Chip_UARTN_GetIntsEnabled(LPC_USARTN_T *pUART) +{ + return pUART->INTENSET; +} + +/** + * @brief Get UART interrupt status + * @param pUART : The base of UART peripheral on the chip + * @return The Interrupt status register of UART + * @note Multiple interrupts may be pending. Mask the return value + * with one or more UARTN_INTEN_* definitions to determine + * pending interrupts. + */ +STATIC INLINE uint32_t Chip_UARTN_GetIntStatus(LPC_USARTN_T *pUART) +{ + return pUART->INTSTAT; +} + +/** + * @brief Configure data width, parity and stop bits + * @param pUART : Pointer to selected pUART peripheral + * @param config : UART configuration, OR'ed values of select UARTN_CFG_* defines + * @return Nothing + * @note Select OR'ed config options for the UART from the UARTN_CFG_PARITY_*, + * UARTN_CFG_STOPLEN_*, and UARTN_CFG_DATALEN_* definitions. For example, + * a configuration of 8 data bits, 1 stop bit, and even (enabled) parity would be + * (UARTN_CFG_DATALEN_8 | UARTN_CFG_STOPLEN_1 | UARTN_CFG_PARITY_EVEN). Will not + * alter other bits in the CFG register. + */ +STATIC INLINE void Chip_UARTN_ConfigData(LPC_USARTN_T *pUART, uint32_t config) +{ + uint32_t reg; + + reg = pUART->CFG & ~((0x3 << 2) | (0x3 << 4) | (0x1 << 6)); + pUART->CFG = reg | config; +} + +/** + * @brief Get the UART status register + * @param pUART : Pointer to selected UARTx peripheral + * @return UART status register + * @note Multiple statuses may be pending. Mask the return value + * with one or more UARTN_STAT_* definitions to determine + * statuses. + */ +STATIC INLINE uint32_t Chip_UARTN_GetStatus(LPC_USARTN_T *pUART) +{ + return pUART->STAT; +} + +/** + * @brief Clear the UART status register + * @param pUART : Pointer to selected UARTx peripheral + * @param stsMask : OR'ed statuses to disable + * @return Nothing + * @note Multiple interrupts may be pending. Mask the return value + * with one or more UARTN_INTEN_* definitions to determine + * pending interrupts. + */ +STATIC INLINE void Chip_UARTN_ClearStatus(LPC_USARTN_T *pUART, uint32_t stsMask) +{ + pUART->STAT = stsMask; +} + +/** + * @brief Initialize the UART peripheral + * @param pUART : The base of UART peripheral on the chip + * @return Nothing + */ +void Chip_UARTN_Init(LPC_USARTN_T *pUART); + +/** + * @brief Deinitialize the UART peripheral + * @param pUART : The base of UART peripheral on the chip + * @return Nothing + */ +void Chip_UARTN_DeInit(LPC_USARTN_T *pUART); + +/** + * @brief Transmit a byte array through the UART peripheral (non-blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to bytes to transmit + * @param numBytes : Number of bytes to transmit + * @return The actual number of bytes placed into the FIFO + * @note This function places data into the transmit FIFO until either + * all the data is in the FIFO or the FIFO is full. This function + * will not block in the FIFO is full. The actual number of bytes + * placed into the FIFO is returned. This function ignores errors. + */ +int Chip_UARTN_Send(LPC_USARTN_T *pUART, const void *data, int numBytes); + +/** + * @brief Read data through the UART peripheral (non-blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to bytes array to fill + * @param numBytes : Size of the passed data array + * @return The actual number of bytes read + * @note This function reads data from the receive FIFO until either + * all the data has been read or the passed buffer is completely full. + * This function will not block. This function ignores errors. + */ +int Chip_UARTN_Read(LPC_USARTN_T *pUART, void *data, int numBytes); + +/** + * @brief Set baud rate for UART + * @param pUART : The base of UART peripheral on the chip + * @param baudrate: Baud rate to be set + * @return Nothing + */ +void Chip_UARTN_SetBaud(LPC_USARTN_T *pUART, uint32_t baudrate); + +/** + * @brief Set baud rate for UART using RTC32K oscillator + * @param pUART : The base of UART peripheral on the chip + * @param baudrate: Baud rate to be set + * @return Nothing + * @note Since the baud rate is divided from the 32KHz oscillator, + * this function should only be used with baud rates less + * than or equal to 9600 baud. Don't expect any accuracy. + */ +void Chip_UARTN_SetBaudWithRTC32K(LPC_USARTN_T *pUART, uint32_t baudrate); + +/** + * @brief Transmit a byte array through the UART peripheral (blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to data to transmit + * @param numBytes : Number of bytes to transmit + * @return The number of bytes transmitted + * @note This function will send or place all bytes into the transmit + * FIFO. This function will block until the last bytes are in the FIFO. + */ +int Chip_UARTN_SendBlocking(LPC_USARTN_T *pUART, const void *data, int numBytes); + +/** + * @brief Read data through the UART peripheral (blocking) + * @param pUART : Pointer to selected UART peripheral + * @param data : Pointer to data array to fill + * @param numBytes : Size of the passed data array + * @return The size of the dat array + * @note This function reads data from the receive FIFO until the passed + * buffer is completely full. The function will block until full. + * This function ignores errors. + */ +int Chip_UARTN_ReadBlocking(LPC_USARTN_T *pUART, void *data, int numBytes); + +/** + * @brief UART receive-only interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @return Nothing + * @note If ring buffer support is desired for the receive side + * of data transfer, the UART interrupt should call this + * function for a receive based interrupt status. + */ +void Chip_UARTN_RXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB); + +/** + * @brief UART transmit-only interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @return Nothing + * @note If ring buffer support is desired for the transmit side + * of data transfer, the UART interrupt should call this + * function for a transmit based interrupt status. + */ +void Chip_UARTN_TXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB); + +/** + * @brief Populate a transmit ring buffer and start UART transmit + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @param data : Pointer to buffer to move to ring buffer + * @param count : Number of bytes to move + * @return The number of bytes placed into the ring buffer + * @note Will move the data into the TX ring buffer and start the + * transfer. If the number of bytes returned is less than the + * number of bytes to send, the ring buffer is considered full. + */ +uint32_t Chip_UARTN_SendRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, const void *data, int count); + +/** + * @brief Copy data from a receive ring buffer + * @param pUART : Pointer to selected UART peripheral + * @param pRB : Pointer to ring buffer structure to use + * @param data : Pointer to buffer to fill from ring buffer + * @param bytes : Size of the passed buffer in bytes + * @return The number of bytes placed into the ring buffer + * @note Will move the data from the RX ring buffer up to the + * the maximum passed buffer size. Returns 0 if there is + * no data in the ring buffer. + */ +int Chip_UARTN_ReadRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, void *data, int bytes); + +/** + * @brief UART receive/transmit interrupt handler for ring buffers + * @param pUART : Pointer to selected UART peripheral + * @param pRXRB : Pointer to transmit ring buffer + * @param pTXRB : Pointer to receive ring buffer + * @return Nothing + * @note This provides a basic implementation of the UART IRQ + * handler for support of a ring buffer implementation for + * transmit and receive. + */ +void Chip_UARTN_IRQRBHandler(LPC_USARTN_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __UART_N_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd.h b/source/lpc_chip_11u6x/inc/usbd/usbd.h new file mode 100644 index 0000000..a37775a --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd.h @@ -0,0 +1,704 @@ +/*********************************************************************** +* $Id:: mw_usbd.h 575 2012-11-20 01:35:56Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __USBD_H__ +#define __USBD_H__ + +/** \file + * \brief Common definitions and declarations for the USB stack. + * + * Common definitions and declarations for the USB stack. + * \addtogroup USBD_Core + * @{ + */ + +#include "lpc_types.h" + +#if defined(__GNUC__) +/* As per http://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax, +6.29 Attributes Syntax +"An attribute specifier list may appear as part of a struct, union or +enum specifier. It may go either immediately after the struct, union +or enum keyword, or after the closing brace. The former syntax is +preferred. Where attribute specifiers follow the closing brace, they +are considered to relate to the structure, union or enumerated type +defined, not to any enclosing declaration the type specifier appears +in, and the type defined is not complete until after the attribute +specifiers." +So use POST_PACK immediately after struct keyword +*/ +#define PRE_PACK +#define POST_PACK __attribute__((__packed__)) +#define ALIGNED(n) __attribute__((aligned (n))) + +#elif defined(__arm) +#define PRE_PACK __packed +#define POST_PACK +#define ALIGNED(n) __align(n) + +#elif defined(__ICCARM__) +#define PRE_PACK __packed +#define POST_PACK +#define PRAGMA_ALIGN_4096 _Pragma("data_alignment=4096") +#define PRAGMA_ALIGN_2048 _Pragma("data_alignment=2048") +#define PRAGMA_ALIGN_256 _Pragma("data_alignment=256") +#define PRAGMA_ALIGN_128 _Pragma("data_alignment=128") +#define PRAGMA_ALIGN_64 _Pragma("data_alignment=64") +#define PRAGMA_ALIGN_48 _Pragma("data_alignment=48") +#define PRAGMA_ALIGN_32 _Pragma("data_alignment=32") +#define PRAGMA_ALIGN_4 _Pragma("data_alignment=4") +#define ALIGNED(n) PRAGMA_ALIGN_##n + +#pragma diag_suppress=Pe021 +#endif + +/** Structure to pack lower and upper byte to form 16 bit word. */ +PRE_PACK struct POST_PACK _WB_T +{ + uint8_t L; /**< lower byte */ + uint8_t H; /**< upper byte */ +}; +/** Structure to pack lower and upper byte to form 16 bit word.*/ +typedef struct _WB_T WB_T; + +/** Union of \ref _WB_T struct and 16 bit word.*/ +PRE_PACK union POST_PACK __WORD_BYTE +{ + uint16_t W; /**< data member to do 16 bit access */ + WB_T WB; /**< data member to do 8 bit access */ +} ; +/** Union of \ref _WB_T struct and 16 bit word.*/ +typedef union __WORD_BYTE WORD_BYTE; + +/** bmRequestType.Dir defines + * @{ + */ +/** Request from host to device */ +#define REQUEST_HOST_TO_DEVICE 0 +/** Request from device to host */ +#define REQUEST_DEVICE_TO_HOST 1 +/** @} */ + +/** bmRequestType.Type defines + * @{ + */ +/** Standard Request */ +#define REQUEST_STANDARD 0 +/** Class Request */ +#define REQUEST_CLASS 1 +/** Vendor Request */ +#define REQUEST_VENDOR 2 +/** Reserved Request */ +#define REQUEST_RESERVED 3 +/** @} */ + +/** bmRequestType.Recipient defines + * @{ + */ +/** Request to device */ +#define REQUEST_TO_DEVICE 0 +/** Request to interface */ +#define REQUEST_TO_INTERFACE 1 +/** Request to endpoint */ +#define REQUEST_TO_ENDPOINT 2 +/** Request to other */ +#define REQUEST_TO_OTHER 3 +/** @} */ + +/** Structure to define 8 bit USB request.*/ +PRE_PACK struct POST_PACK _BM_T +{ + uint8_t Recipient : 5; /**< Recipient type. */ + uint8_t Type : 2; /**< Request type. */ + uint8_t Dir : 1; /**< Direction type. */ +}; +/** Structure to define 8 bit USB request.*/ +typedef struct _BM_T BM_T; + +/** Union of \ref _BM_T struct and 8 bit byte.*/ +PRE_PACK union POST_PACK _REQUEST_TYPE +{ + uint8_t B; /**< byte wide access memeber */ + BM_T BM; /**< bitfield structure access memeber */ +} ; +/** Union of \ref _BM_T struct and 8 bit byte.*/ +typedef union _REQUEST_TYPE REQUEST_TYPE; + +/** USB Standard Request Codes + * @{ + */ +/** GET_STATUS request */ +#define USB_REQUEST_GET_STATUS 0 +/** CLEAR_FEATURE request */ +#define USB_REQUEST_CLEAR_FEATURE 1 +/** SET_FEATURE request */ +#define USB_REQUEST_SET_FEATURE 3 +/** SET_ADDRESS request */ +#define USB_REQUEST_SET_ADDRESS 5 +/** GET_DESCRIPTOR request */ +#define USB_REQUEST_GET_DESCRIPTOR 6 +/** SET_DESCRIPTOR request */ +#define USB_REQUEST_SET_DESCRIPTOR 7 +/** GET_CONFIGURATION request */ +#define USB_REQUEST_GET_CONFIGURATION 8 +/** SET_CONFIGURATION request */ +#define USB_REQUEST_SET_CONFIGURATION 9 +/** GET_INTERFACE request */ +#define USB_REQUEST_GET_INTERFACE 10 +/** SET_INTERFACE request */ +#define USB_REQUEST_SET_INTERFACE 11 +/** SYNC_FRAME request */ +#define USB_REQUEST_SYNC_FRAME 12 +/** @} */ + +/** USB GET_STATUS Bit Values + * @{ + */ +/** SELF_POWERED status*/ +#define USB_GETSTATUS_SELF_POWERED 0x01 +/** REMOTE_WAKEUP capable status*/ +#define USB_GETSTATUS_REMOTE_WAKEUP 0x02 +/** ENDPOINT_STALL status*/ +#define USB_GETSTATUS_ENDPOINT_STALL 0x01 +/** @} */ + +/** USB Standard Feature selectors + * @{ + */ +/** ENDPOINT_STALL feature*/ +#define USB_FEATURE_ENDPOINT_STALL 0 +/** REMOTE_WAKEUP feature*/ +#define USB_FEATURE_REMOTE_WAKEUP 1 +/** TEST_MODE feature*/ +#define USB_FEATURE_TEST_MODE 2 +/** @} */ + +/** USB Default Control Pipe Setup Packet*/ +PRE_PACK struct POST_PACK _USB_SETUP_PACKET +{ + REQUEST_TYPE bmRequestType; /**< This bitmapped field identifies the characteristics + of the specific request. \sa _BM_T. + */ + uint8_t bRequest; /**< This field specifies the particular request. The + Type bits in the bmRequestType field modify the meaning + of this field. \sa USBD_REQUEST. + */ + WORD_BYTE wValue; /**< Used to pass a parameter to the device, specific + to the request. + */ + WORD_BYTE wIndex; /**< Used to pass a parameter to the device, specific + to the request. The wIndex field is often used in + requests to specify an endpoint or an interface. + */ + uint16_t wLength; /**< This field specifies the length of the data + transferred during the second phase of the control + transfer. + */ +} ; +/** USB Default Control Pipe Setup Packet*/ +typedef struct _USB_SETUP_PACKET USB_SETUP_PACKET; + + +/** USB Descriptor Types + * @{ + */ +/** Device descriptor type */ +#define USB_DEVICE_DESCRIPTOR_TYPE 1 +/** Configuration descriptor type */ +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 +/** String descriptor type */ +#define USB_STRING_DESCRIPTOR_TYPE 3 +/** Interface descriptor type */ +#define USB_INTERFACE_DESCRIPTOR_TYPE 4 +/** Endpoint descriptor type */ +#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 +/** Device qualifier descriptor type */ +#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6 +/** Other speed configuration descriptor type */ +#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7 +/** Interface power descriptor type */ +#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8 +/** OTG descriptor type */ +#define USB_OTG_DESCRIPTOR_TYPE 9 +/** Debug descriptor type */ +#define USB_DEBUG_DESCRIPTOR_TYPE 10 +/** Interface association descriptor type */ +#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11 +/** @} */ + +/** USB Device Classes + * @{ + */ +/** Reserved device class */ +#define USB_DEVICE_CLASS_RESERVED 0x00 +/** Audio device class */ +#define USB_DEVICE_CLASS_AUDIO 0x01 +/** Communications device class */ +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +/** Human interface device class */ +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +/** monitor device class */ +#define USB_DEVICE_CLASS_MONITOR 0x04 +/** physical interface device class */ +#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05 +/** power device class */ +#define USB_DEVICE_CLASS_POWER 0x06 +/** Printer device class */ +#define USB_DEVICE_CLASS_PRINTER 0x07 +/** Storage device class */ +#define USB_DEVICE_CLASS_STORAGE 0x08 +/** Hub device class */ +#define USB_DEVICE_CLASS_HUB 0x09 +/** miscellaneous device class */ +#define USB_DEVICE_CLASS_MISCELLANEOUS 0xEF +/** Application device class */ +#define USB_DEVICE_CLASS_APP 0xFE +/** Vendor specific device class */ +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF +/** @} */ + +/** bmAttributes in Configuration Descriptor + * @{ + */ +/** Power field mask */ +#define USB_CONFIG_POWERED_MASK 0x40 +/** Bus powered */ +#define USB_CONFIG_BUS_POWERED 0x80 +/** Self powered */ +#define USB_CONFIG_SELF_POWERED 0xC0 +/** remote wakeup */ +#define USB_CONFIG_REMOTE_WAKEUP 0x20 +/** @} */ + +/** bMaxPower in Configuration Descriptor */ +#define USB_CONFIG_POWER_MA(mA) ((mA)/2) + +/** bEndpointAddress in Endpoint Descriptor + * @{ + */ +/** Endopint address mask */ +#define USB_ENDPOINT_DIRECTION_MASK 0x80 +/** Macro to convert OUT endopint number to endpoint address value. */ +#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) +/** Macro to convert IN endopint number to endpoint address value. */ +#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) +/** @} */ + +/** bmAttributes in Endpoint Descriptor + * @{ + */ +/** Endopint type mask */ +#define USB_ENDPOINT_TYPE_MASK 0x03 +/** Control Endopint type */ +#define USB_ENDPOINT_TYPE_CONTROL 0x00 +/** isochronous Endopint type */ +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 +/** bulk Endopint type */ +#define USB_ENDPOINT_TYPE_BULK 0x02 +/** interrupt Endopint type */ +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 +/** Endopint sync type mask */ +#define USB_ENDPOINT_SYNC_MASK 0x0C +/** no synchronization Endopint */ +#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00 +/** Asynchronous sync Endopint */ +#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04 +/** Adaptive sync Endopint */ +#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08 +/** Synchronous sync Endopint */ +#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C +/** Endopint usage type mask */ +#define USB_ENDPOINT_USAGE_MASK 0x30 +/** Endopint data usage type */ +#define USB_ENDPOINT_USAGE_DATA 0x00 +/** Endopint feedback usage type */ +#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 +/** Endopint implicit feedback usage type */ +#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20 +/** Endopint reserved usage type */ +#define USB_ENDPOINT_USAGE_RESERVED 0x30 +/** @} */ + +/** Control endopint EP0's maximum packet size in high-speed mode.*/ +#define USB_ENDPOINT_0_HS_MAXP 64 +/** Control endopint EP0's maximum packet size in low-speed mode.*/ +#define USB_ENDPOINT_0_LS_MAXP 8 +/** Bulk endopint's maximum packet size in high-speed mode.*/ +#define USB_ENDPOINT_BULK_HS_MAXP 512 + +/** USB Standard Device Descriptor */ +PRE_PACK struct POST_PACK _USB_DEVICE_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes. */ + uint8_t bDescriptorType; /**< DEVICE Descriptor Type. */ + uint16_t bcdUSB; /**< BUSB Specification Release Number in + Binary-Coded Decimal (i.e., 2.10 is 210H). + This field identifies the release of the USB + Specification with which the device and its + descriptors are compliant. + */ + uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF). + If this field is reset to zero, each interface + within a configuration specifies its own + class information and the various + interfaces operate independently.\n + If this field is set to a value between 1 and + FEH, the device supports different class + specifications on different interfaces and + the interfaces may not operate + independently. This value identifies the + class definition used for the aggregate + interfaces. \n + If this field is set to FFH, the device class + is vendor-specific. + */ + uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF). + These codes are qualified by the value of + the bDeviceClass field. \n + If the bDeviceClass field is reset to zero, + this field must also be reset to zero. \n + If the bDeviceClass field is not set to FFH, + all values are reserved for assignment by + the USB-IF. + */ + uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF). + These codes are qualified by the value of + the bDeviceClass and the + bDeviceSubClass fields. If a device + supports class-specific protocols on a + device basis as opposed to an interface + basis, this code identifies the protocols + that the device uses as defined by the + specification of the device class. \n + If this field is reset to zero, the device + does not use class-specific protocols on a + device basis. However, it may use classspecific + protocols on an interface basis. \n + If this field is set to FFH, the device uses a + vendor-specific protocol on a device basis. + */ + uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero + (only 8, 16, 32, or 64 are valid). For HS devices + is fixed to 64. + */ + + uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF). */ + uint16_t idProduct; /**< Product ID (assigned by the manufacturer). */ + uint16_t bcdDevice; /**< Device release number in binary-coded decimal. */ + uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer. */ + uint8_t iProduct; /**< Index of string descriptor describing product. */ + uint8_t iSerialNumber; /**< Index of string descriptor describing the device’s + serial number. + */ + uint8_t bNumConfigurations; /**< Number of possible configurations. */ +} ; +/** USB Standard Device Descriptor */ +typedef struct _USB_DEVICE_DESCRIPTOR USB_DEVICE_DESCRIPTOR; + +/** USB 2.0 Device Qualifier Descriptor */ +PRE_PACK struct POST_PACK _USB_DEVICE_QUALIFIER_DESCRIPTOR +{ + uint8_t bLength; /**< Size of descriptor */ + uint8_t bDescriptorType; /**< Device Qualifier Type */ + uint16_t bcdUSB; /**< USB specification version number (e.g., 0200H for V2.00) */ + uint8_t bDeviceClass; /**< Class Code */ + uint8_t bDeviceSubClass; /**< SubClass Code */ + uint8_t bDeviceProtocol; /**< Protocol Code */ + uint8_t bMaxPacketSize0; /**< Maximum packet size for other speed */ + uint8_t bNumConfigurations; /**< Number of Other-speed Configurations */ + uint8_t bReserved; /**< Reserved for future use, must be zero */ +} ; +/** USB 2.0 Device Qualifier Descriptor */ +typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR USB_DEVICE_QUALIFIER_DESCRIPTOR; + +/** USB Standard Configuration Descriptor */ +PRE_PACK struct POST_PACK _USB_CONFIGURATION_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes */ + uint8_t bDescriptorType; /**< CONFIGURATION Descriptor Type*/ + uint16_t wTotalLength; /**< Total length of data returned for this + configuration. Includes the combined length + of all descriptors (configuration, interface, + endpoint, and class- or vendor-specific) + returned for this configuration.*/ + uint8_t bNumInterfaces; /**< Number of interfaces supported by this configuration*/ + uint8_t bConfigurationValue; /**< Value to use as an argument to the + SetConfiguration() request to select this + configuration. */ + uint8_t iConfiguration; /**< Index of string descriptor describing this + configuration*/ + uint8_t bmAttributes; /**< Configuration characteristics \n + D7: Reserved (set to one)\n + D6: Self-powered \n + D5: Remote Wakeup \n + D4...0: Reserved (reset to zero) \n + D7 is reserved and must be set to one for + historical reasons. \n + A device configuration that uses power from + the bus and a local source reports a non-zero + value in bMaxPower to indicate the amount of + bus power required and sets D6. The actual + power source at runtime may be determined + using the GetStatus(DEVICE) request (see + USB 2.0 spec Section 9.4.5). \n + If a device configuration supports remote + wakeup, D5 is set to one.*/ + uint8_t bMaxPower; /**< Maximum power consumption of the USB + device from the bus in this specific + configuration when the device is fully + operational. Expressed in 2 mA units + (i.e., 50 = 100 mA). \n + Note: A device configuration reports whether + the configuration is bus-powered or selfpowered. + Device status reports whether the + device is currently self-powered. If a device is + disconnected from its external power source, it + updates device status to indicate that it is no + longer self-powered. \n + A device may not increase its power draw + from the bus, when it loses its external power + source, beyond the amount reported by its + configuration. \n + If a device can continue to operate when + disconnected from its external power source, it + continues to do so. If the device cannot + continue to operate, it fails operations it can + no longer support. The USB System Software + may determine the cause of the failure by + checking the status and noting the loss of the + device’s power source.*/ +} ; +/** USB Standard Configuration Descriptor */ +typedef struct _USB_CONFIGURATION_DESCRIPTOR USB_CONFIGURATION_DESCRIPTOR; + +/** USB Standard Interface Association Descriptor */ +PRE_PACK struct POST_PACK _USB_IAD_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< INTERFACE ASSOCIATION Descriptor Type*/ + uint8_t bFirstInterface; /**< Interface number of the first interface that is + associated with this function.*/ + uint8_t bInterfaceCount; /**< Number of contiguous interfaces that are + associated with this function. */ + uint8_t bFunctionClass; /**< Class code (assigned by USB-IF). \n + A value of zero is not allowed in this descriptor. + If this field is FFH, the function class is vendorspecific. + All other values are reserved for assignment by + the USB-IF.*/ + uint8_t bFunctionSubClass; /**< Subclass code (assigned by USB-IF). \n + If the bFunctionClass field is not set to FFH all + values are reserved for assignment by the USBIF.*/ + uint8_t bFunctionProtocol; /**< Protocol code (assigned by the USB). \n + These codes are qualified by the values of the + bFunctionClass and bFunctionSubClass fields.*/ + uint8_t iFunction; /**< Index of string descriptor describing this function.*/ +} ; +/** USB Standard Interface Association Descriptor */ +typedef struct _USB_IAD_DESCRIPTOR USB_IAD_DESCRIPTOR; + +/** USB Standard Interface Descriptor */ +PRE_PACK struct POST_PACK _USB_INTERFACE_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< INTERFACE Descriptor Type*/ + uint8_t bInterfaceNumber; /**< Number of this interface. Zero-based + value identifying the index in the array of + concurrent interfaces supported by this + configuration.*/ + uint8_t bAlternateSetting; /**< Value used to select this alternate setting + for the interface identified in the prior field*/ + uint8_t bNumEndpoints; /**< Number of endpoints used by this + interface (excluding endpoint zero). If this + value is zero, this interface only uses the + Default Control Pipe.*/ + uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF). \n + A value of zero is reserved for future + standardization. \n + If this field is set to FFH, the interface + class is vendor-specific. \n + All other values are reserved for + assignment by the USB-IF.*/ + uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF). \n + These codes are qualified by the value of + the bInterfaceClass field. \n + If the bInterfaceClass field is reset to zero, + this field must also be reset to zero. \n + If the bInterfaceClass field is not set to + FFH, all values are reserved for + assignment by the USB-IF.*/ + uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB). \n + These codes are qualified by the value of + the bInterfaceClass and the + bInterfaceSubClass fields. If an interface + supports class-specific requests, this code + identifies the protocols that the device + uses as defined by the specification of the + device class. \n + If this field is reset to zero, the device + does not use a class-specific protocol on + this interface. \n + If this field is set to FFH, the device uses + a vendor-specific protocol for this + interface.*/ + uint8_t iInterface; /**< Index of string descriptor describing this interface*/ +} ; +/** USB Standard Interface Descriptor */ +typedef struct _USB_INTERFACE_DESCRIPTOR USB_INTERFACE_DESCRIPTOR; + +/** USB Standard Endpoint Descriptor */ +PRE_PACK struct POST_PACK _USB_ENDPOINT_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< ENDPOINT Descriptor Type*/ + uint8_t bEndpointAddress; /**< The address of the endpoint on the USB device + described by this descriptor. The address is + encoded as follows: \n + Bit 3...0: The endpoint number \n + Bit 6...4: Reserved, reset to zero \n + Bit 7: Direction, ignored for control endpoints + 0 = OUT endpoint + 1 = IN endpoint. \n \sa USBD_ENDPOINT_ADR_Type*/ + uint8_t bmAttributes; /**< This field describes the endpoint’s attributes when it is + configured using the bConfigurationValue. \n + Bits 1..0: Transfer Type + \li 00 = Control + \li 01 = Isochronous + \li 10 = Bulk + \li 11 = Interrupt \n + If not an isochronous endpoint, bits 5..2 are reserved + and must be set to zero. If isochronous, they are + defined as follows: \n + Bits 3..2: Synchronization Type + \li 00 = No Synchronization + \li 01 = Asynchronous + \li 10 = Adaptive + \li 11 = Synchronous \n + Bits 5..4: Usage Type + \li 00 = Data endpoint + \li 01 = Feedback endpoint + \li 10 = Implicit feedback Data endpoint + \li 11 = Reserved \n + Refer to Chapter 5 of USB 2.0 specification for more information. \n + All other bits are reserved and must be reset to zero. + Reserved bits must be ignored by the host. + \n \sa USBD_EP_ATTR_Type*/ + uint16_t wMaxPacketSize; /**< Maximum packet size this endpoint is capable of + sending or receiving when this configuration is + selected. \n + For isochronous endpoints, this value is used to + reserve the bus time in the schedule, required for the + per-(micro)frame data payloads. The pipe may, on an + ongoing basis, actually use less bandwidth than that + reserved. The device reports, if necessary, the actual + bandwidth used via its normal, non-USB defined + mechanisms. \n + For all endpoints, bits 10..0 specify the maximum + packet size (in bytes). \n + For high-speed isochronous and interrupt endpoints: \n + Bits 12..11 specify the number of additional transaction + opportunities per microframe: \n + \li 00 = None (1 transaction per microframe) + \li 01 = 1 additional (2 per microframe) + \li 10 = 2 additional (3 per microframe) + \li 11 = Reserved \n + Bits 15..13 are reserved and must be set to zero.*/ + uint8_t bInterval; /**< Interval for polling endpoint for data transfers. + Expressed in frames or microframes depending on the + device operating speed (i.e., either 1 millisecond or + 125 µs units). + \li For full-/high-speed isochronous endpoints, this value + must be in the range from 1 to 16. The bInterval value + is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a + bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). + \li For full-/low-speed interrupt endpoints, the value of + this field may be from 1 to 255. + \li For high-speed interrupt endpoints, the bInterval value + is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a + bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value + must be from 1 to 16. + \li For high-speed bulk/control OUT endpoints, the + bInterval must specify the maximum NAK rate of the + endpoint. A value of 0 indicates the endpoint never + NAKs. Other values indicate at most 1 NAK each + bInterval number of microframes. This value must be + in the range from 0 to 255. \n + Refer to Chapter 5 of USB 2.0 specification for more information. + */ +} ; +/** USB Standard Endpoint Descriptor */ +typedef struct _USB_ENDPOINT_DESCRIPTOR USB_ENDPOINT_DESCRIPTOR; + +/** USB String Descriptor */ +PRE_PACK struct POST_PACK _USB_STRING_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< STRING Descriptor Type*/ + uint16_t bString/*[]*/; /**< UNICODE encoded string */ +} ; +/** USB String Descriptor */ +typedef struct _USB_STRING_DESCRIPTOR USB_STRING_DESCRIPTOR; + +/** USB Common Descriptor */ +PRE_PACK struct POST_PACK _USB_COMMON_DESCRIPTOR +{ + uint8_t bLength; /**< Size of this descriptor in bytes*/ + uint8_t bDescriptorType; /**< Descriptor Type*/ +} ; +/** USB Common Descriptor */ +typedef struct _USB_COMMON_DESCRIPTOR USB_COMMON_DESCRIPTOR; + +/** USB Other Speed Configuration */ +PRE_PACK struct POST_PACK _USB_OTHER_SPEED_CONFIGURATION +{ + uint8_t bLength; /**< Size of descriptor*/ + uint8_t bDescriptorType; /**< Other_speed_Configuration Type*/ + uint16_t wTotalLength; /**< Total length of data returned*/ + uint8_t bNumInterfaces; /**< Number of interfaces supported by this speed configuration*/ + uint8_t bConfigurationValue; /**< Value to use to select configuration*/ + uint8_t IConfiguration; /**< Index of string descriptor*/ + uint8_t bmAttributes; /**< Same as Configuration descriptor*/ + uint8_t bMaxPower; /**< Same as Configuration descriptor*/ +} ; +/** USB Other Speed Configuration */ +typedef struct _USB_OTHER_SPEED_CONFIGURATION USB_OTHER_SPEED_CONFIGURATION; + +/** \ingroup USBD_Core + * USB device stack/module handle. + */ +typedef void* USBD_HANDLE_T; + +#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) +#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF) + +#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR)) +#define USB_CONFIGURATION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR)) +#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR)) +#define USB_INTERFACE_ASSOC_DESC_SIZE (sizeof(USB_IAD_DESCRIPTOR)) +#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR)) +#define USB_DEVICE_QUALI_SIZE (sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) +#define USB_OTHER_SPEED_CONF_SIZE (sizeof(USB_OTHER_SPEED_CONFIGURATION)) + +/** @}*/ + +#endif /* __USBD_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_adc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_adc.h new file mode 100644 index 0000000..9d42948 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_adc.h @@ -0,0 +1,377 @@ +/*********************************************************************** +* $Id:: mw_usbd_audio.h 165 2011-04-14 17:41:11Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Audio Device Class Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __AUDIO_H__ +#define __AUDIO_H__ + + +/* Audio Interface Subclass Codes */ +#define AUDIO_SUBCLASS_UNDEFINED 0x00 +#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01 +#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02 +#define AUDIO_SUBCLASS_MIDISTREAMING 0x03 + +/* Audio Interface Protocol Codes */ +#define AUDIO_PROTOCOL_UNDEFINED 0x00 + + +/* Audio Descriptor Types */ +#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20 +#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21 +#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22 +#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23 +#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24 +#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25 + + +/* Audio Control Interface Descriptor Subtypes */ +#define AUDIO_CONTROL_UNDEFINED 0x00 +#define AUDIO_CONTROL_HEADER 0x01 +#define AUDIO_CONTROL_INPUT_TERMINAL 0x02 +#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03 +#define AUDIO_CONTROL_MIXER_UNIT 0x04 +#define AUDIO_CONTROL_SELECTOR_UNIT 0x05 +#define AUDIO_CONTROL_FEATURE_UNIT 0x06 +#define AUDIO_CONTROL_PROCESSING_UNIT 0x07 +#define AUDIO_CONTROL_EXTENSION_UNIT 0x08 + +/* Audio Streaming Interface Descriptor Subtypes */ +#define AUDIO_STREAMING_UNDEFINED 0x00 +#define AUDIO_STREAMING_GENERAL 0x01 +#define AUDIO_STREAMING_FORMAT_TYPE 0x02 +#define AUDIO_STREAMING_FORMAT_SPECIFIC 0x03 + +/* Audio Endpoint Descriptor Subtypes */ +#define AUDIO_ENDPOINT_UNDEFINED 0x00 +#define AUDIO_ENDPOINT_GENERAL 0x01 + + +/* Audio Descriptor Sizes */ +#define AUDIO_CONTROL_INTERFACE_DESC_SZ(n) 0x08+n +#define AUDIO_STREAMING_INTERFACE_DESC_SIZE 0x07 +#define AUDIO_INPUT_TERMINAL_DESC_SIZE 0x0C +#define AUDIO_OUTPUT_TERMINAL_DESC_SIZE 0x09 +#define AUDIO_MIXER_UNIT_DESC_SZ(p,n) 0x0A+p+n +#define AUDIO_SELECTOR_UNIT_DESC_SZ(p) 0x06+p +#define AUDIO_FEATURE_UNIT_DESC_SZ(ch,n) 0x07+(ch+1)*n +#define AUDIO_PROCESSING_UNIT_DESC_SZ(p,n,x) 0x0D+p+n+x +#define AUDIO_EXTENSION_UNIT_DESC_SZ(p,n) 0x0D+p+n +#define AUDIO_STANDARD_ENDPOINT_DESC_SIZE 0x09 +#define AUDIO_STREAMING_ENDPOINT_DESC_SIZE 0x07 + + +/* Audio Processing Unit Process Types */ +#define AUDIO_UNDEFINED_PROCESS 0x00 +#define AUDIO_UP_DOWN_MIX_PROCESS 0x01 +#define AUDIO_DOLBY_PROLOGIC_PROCESS 0x02 +#define AUDIO_3D_STEREO_PROCESS 0x03 +#define AUDIO_REVERBERATION_PROCESS 0x04 +#define AUDIO_CHORUS_PROCESS 0x05 +#define AUDIO_DYN_RANGE_COMP_PROCESS 0x06 + + +/* Audio Request Codes */ +#define AUDIO_REQUEST_UNDEFINED 0x00 +#define AUDIO_REQUEST_SET_CUR 0x01 +#define AUDIO_REQUEST_GET_CUR 0x81 +#define AUDIO_REQUEST_SET_MIN 0x02 +#define AUDIO_REQUEST_GET_MIN 0x82 +#define AUDIO_REQUEST_SET_MAX 0x03 +#define AUDIO_REQUEST_GET_MAX 0x83 +#define AUDIO_REQUEST_SET_RES 0x04 +#define AUDIO_REQUEST_GET_RES 0x84 +#define AUDIO_REQUEST_SET_MEM 0x05 +#define AUDIO_REQUEST_GET_MEM 0x85 +#define AUDIO_REQUEST_GET_STAT 0xFF + + +/* Audio Control Selector Codes */ +#define AUDIO_CONTROL_UNDEFINED 0x00 /* Common Selector */ + +/* Terminal Control Selectors */ +#define AUDIO_COPY_PROTECT_CONTROL 0x01 + +/* Feature Unit Control Selectors */ +#define AUDIO_MUTE_CONTROL 0x01 +#define AUDIO_VOLUME_CONTROL 0x02 +#define AUDIO_BASS_CONTROL 0x03 +#define AUDIO_MID_CONTROL 0x04 +#define AUDIO_TREBLE_CONTROL 0x05 +#define AUDIO_GRAPHIC_EQUALIZER_CONTROL 0x06 +#define AUDIO_AUTOMATIC_GAIN_CONTROL 0x07 +#define AUDIO_DELAY_CONTROL 0x08 +#define AUDIO_BASS_BOOST_CONTROL 0x09 +#define AUDIO_LOUDNESS_CONTROL 0x0A + +/* Processing Unit Control Selectors: */ +#define AUDIO_ENABLE_CONTROL 0x01 /* Common Selector */ +#define AUDIO_MODE_SELECT_CONTROL 0x02 /* Common Selector */ + +/* - Up/Down-mix Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +/* AUDIO_MODE_SELECT_CONTROL 0x02 Common Selector */ + +/* - Dolby Prologic Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +/* AUDIO_MODE_SELECT_CONTROL 0x02 Common Selector */ + +/* - 3D Stereo Extender Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_SPACIOUSNESS_CONTROL 0x02 + +/* - Reverberation Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_REVERB_LEVEL_CONTROL 0x02 +#define AUDIO_REVERB_TIME_CONTROL 0x03 +#define AUDIO_REVERB_FEEDBACK_CONTROL 0x04 + +/* - Chorus Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_CHORUS_LEVEL_CONTROL 0x02 +#define AUDIO_SHORUS_RATE_CONTROL 0x03 +#define AUDIO_CHORUS_DEPTH_CONTROL 0x04 + +/* - Dynamic Range Compressor Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ +#define AUDIO_COMPRESSION_RATE_CONTROL 0x02 +#define AUDIO_MAX_AMPL_CONTROL 0x03 +#define AUDIO_THRESHOLD_CONTROL 0x04 +#define AUDIO_ATTACK_TIME_CONTROL 0x05 +#define AUDIO_RELEASE_TIME_CONTROL 0x06 + +/* Extension Unit Control Selectors */ +/* AUDIO_ENABLE_CONTROL 0x01 Common Selector */ + +/* Endpoint Control Selectors */ +#define AUDIO_SAMPLING_FREQ_CONTROL 0x01 +#define AUDIO_PITCH_CONTROL 0x02 + + +/* Audio Format Specific Control Selectors */ + +/* MPEG Control Selectors */ +#define AUDIO_MPEG_CONTROL_UNDEFINED 0x00 +#define AUDIO_MPEG_DUAL_CHANNEL_CONTROL 0x01 +#define AUDIO_MPEG_SECOND_STEREO_CONTROL 0x02 +#define AUDIO_MPEG_MULTILINGUAL_CONTROL 0x03 +#define AUDIO_MPEG_DYN_RANGE_CONTROL 0x04 +#define AUDIO_MPEG_SCALING_CONTROL 0x05 +#define AUDIO_MPEG_HILO_SCALING_CONTROL 0x06 + +/* AC-3 Control Selectors */ +#define AUDIO_AC3_CONTROL_UNDEFINED 0x00 +#define AUDIO_AC3_MODE_CONTROL 0x01 +#define AUDIO_AC3_DYN_RANGE_CONTROL 0x02 +#define AUDIO_AC3_SCALING_CONTROL 0x03 +#define AUDIO_AC3_HILO_SCALING_CONTROL 0x04 + + +/* Audio Format Types */ +#define AUDIO_FORMAT_TYPE_UNDEFINED 0x00 +#define AUDIO_FORMAT_TYPE_I 0x01 +#define AUDIO_FORMAT_TYPE_II 0x02 +#define AUDIO_FORMAT_TYPE_III 0x03 + + +/* Audio Format Type Descriptor Sizes */ +#define AUDIO_FORMAT_TYPE_I_DESC_SZ(n) 0x08+(n*3) +#define AUDIO_FORMAT_TYPE_II_DESC_SZ(n) 0x09+(n*3) +#define AUDIO_FORMAT_TYPE_III_DESC_SZ(n) 0x08+(n*3) +#define AUDIO_FORMAT_MPEG_DESC_SIZE 0x09 +#define AUDIO_FORMAT_AC3_DESC_SIZE 0x0A + + +/* Audio Data Format Codes */ + +/* Audio Data Format Type I Codes */ +#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000 +#define AUDIO_FORMAT_PCM 0x0001 +#define AUDIO_FORMAT_PCM8 0x0002 +#define AUDIO_FORMAT_IEEE_FLOAT 0x0003 +#define AUDIO_FORMAT_ALAW 0x0004 +#define AUDIO_FORMAT_MULAW 0x0005 + +/* Audio Data Format Type II Codes */ +#define AUDIO_FORMAT_TYPE_II_UNDEFINED 0x1000 +#define AUDIO_FORMAT_MPEG 0x1001 +#define AUDIO_FORMAT_AC3 0x1002 + +/* Audio Data Format Type III Codes */ +#define AUDIO_FORMAT_TYPE_III_UNDEFINED 0x2000 +#define AUDIO_FORMAT_IEC1937_AC3 0x2001 +#define AUDIO_FORMAT_IEC1937_MPEG1_L1 0x2002 +#define AUDIO_FORMAT_IEC1937_MPEG1_L2_3 0x2003 +#define AUDIO_FORMAT_IEC1937_MPEG2_NOEXT 0x2003 +#define AUDIO_FORMAT_IEC1937_MPEG2_EXT 0x2004 +#define AUDIO_FORMAT_IEC1937_MPEG2_L1_LS 0x2005 +#define AUDIO_FORMAT_IEC1937_MPEG2_L2_3 0x2006 + + +/* Predefined Audio Channel Configuration Bits */ +#define AUDIO_CHANNEL_M 0x0000 /* Mono */ +#define AUDIO_CHANNEL_L 0x0001 /* Left Front */ +#define AUDIO_CHANNEL_R 0x0002 /* Right Front */ +#define AUDIO_CHANNEL_C 0x0004 /* Center Front */ +#define AUDIO_CHANNEL_LFE 0x0008 /* Low Freq. Enhance. */ +#define AUDIO_CHANNEL_LS 0x0010 /* Left Surround */ +#define AUDIO_CHANNEL_RS 0x0020 /* Right Surround */ +#define AUDIO_CHANNEL_LC 0x0040 /* Left of Center */ +#define AUDIO_CHANNEL_RC 0x0080 /* Right of Center */ +#define AUDIO_CHANNEL_S 0x0100 /* Surround */ +#define AUDIO_CHANNEL_SL 0x0200 /* Side Left */ +#define AUDIO_CHANNEL_SR 0x0400 /* Side Right */ +#define AUDIO_CHANNEL_T 0x0800 /* Top */ + + +/* Feature Unit Control Bits */ +#define AUDIO_CONTROL_MUTE 0x0001 +#define AUDIO_CONTROL_VOLUME 0x0002 +#define AUDIO_CONTROL_BASS 0x0004 +#define AUDIO_CONTROL_MID 0x0008 +#define AUDIO_CONTROL_TREBLE 0x0010 +#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020 +#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040 +#define AUDIO_CONTROL_DEALY 0x0080 +#define AUDIO_CONTROL_BASS_BOOST 0x0100 +#define AUDIO_CONTROL_LOUDNESS 0x0200 + +/* Processing Unit Control Bits: */ +#define AUDIO_CONTROL_ENABLE 0x0001 /* Common Bit */ +#define AUDIO_CONTROL_MODE_SELECT 0x0002 /* Common Bit */ + +/* - Up/Down-mix Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +/* AUDIO_CONTROL_MODE_SELECT 0x0002 Common Bit */ + +/* - Dolby Prologic Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +/* AUDIO_CONTROL_MODE_SELECT 0x0002 Common Bit */ + +/* - 3D Stereo Extender Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_SPACIOUSNESS 0x0002 + +/* - Reverberation Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_REVERB_TYPE 0x0002 +#define AUDIO_CONTROL_REVERB_LEVEL 0x0004 +#define AUDIO_CONTROL_REVERB_TIME 0x0008 +#define AUDIO_CONTROL_REVERB_FEEDBACK 0x0010 + +/* - Chorus Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_CHORUS_LEVEL 0x0002 +#define AUDIO_CONTROL_SHORUS_RATE 0x0004 +#define AUDIO_CONTROL_CHORUS_DEPTH 0x0008 + +/* - Dynamic Range Compressor Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ +#define AUDIO_CONTROL_COMPRESSION_RATE 0x0002 +#define AUDIO_CONTROL_MAX_AMPL 0x0004 +#define AUDIO_CONTROL_THRESHOLD 0x0008 +#define AUDIO_CONTROL_ATTACK_TIME 0x0010 +#define AUDIO_CONTROL_RELEASE_TIME 0x0020 + +/* Extension Unit Control Bits */ +/* AUDIO_CONTROL_ENABLE 0x0001 Common Bit */ + +/* Endpoint Control Bits */ +#define AUDIO_CONTROL_SAMPLING_FREQ 0x01 +#define AUDIO_CONTROL_PITCH 0x02 +#define AUDIO_MAX_PACKETS_ONLY 0x80 + + +/* Audio Terminal Types */ + +/* USB Terminal Types */ +#define AUDIO_TERMINAL_USB_UNDEFINED 0x0100 +#define AUDIO_TERMINAL_USB_STREAMING 0x0101 +#define AUDIO_TERMINAL_USB_VENDOR_SPECIFIC 0x01FF + +/* Input Terminal Types */ +#define AUDIO_TERMINAL_INPUT_UNDEFINED 0x0200 +#define AUDIO_TERMINAL_MICROPHONE 0x0201 +#define AUDIO_TERMINAL_DESKTOP_MICROPHONE 0x0202 +#define AUDIO_TERMINAL_PERSONAL_MICROPHONE 0x0203 +#define AUDIO_TERMINAL_OMNI_DIR_MICROPHONE 0x0204 +#define AUDIO_TERMINAL_MICROPHONE_ARRAY 0x0205 +#define AUDIO_TERMINAL_PROCESSING_MIC_ARRAY 0x0206 + +/* Output Terminal Types */ +#define AUDIO_TERMINAL_OUTPUT_UNDEFINED 0x0300 +#define AUDIO_TERMINAL_SPEAKER 0x0301 +#define AUDIO_TERMINAL_HEADPHONES 0x0302 +#define AUDIO_TERMINAL_HEAD_MOUNTED_AUDIO 0x0303 +#define AUDIO_TERMINAL_DESKTOP_SPEAKER 0x0304 +#define AUDIO_TERMINAL_ROOM_SPEAKER 0x0305 +#define AUDIO_TERMINAL_COMMUNICATION_SPEAKER 0x0306 +#define AUDIO_TERMINAL_LOW_FREQ_SPEAKER 0x0307 + +/* Bi-directional Terminal Types */ +#define AUDIO_TERMINAL_BIDIRECTIONAL_UNDEFINED 0x0400 +#define AUDIO_TERMINAL_HANDSET 0x0401 +#define AUDIO_TERMINAL_HEAD_MOUNTED_HANDSET 0x0402 +#define AUDIO_TERMINAL_SPEAKERPHONE 0x0403 +#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOSUPRESS 0x0404 +#define AUDIO_TERMINAL_SPEAKERPHONE_ECHOCANCEL 0x0405 + +/* Telephony Terminal Types */ +#define AUDIO_TERMINAL_TELEPHONY_UNDEFINED 0x0500 +#define AUDIO_TERMINAL_PHONE_LINE 0x0501 +#define AUDIO_TERMINAL_TELEPHONE 0x0502 +#define AUDIO_TERMINAL_DOWN_LINE_PHONE 0x0503 + +/* External Terminal Types */ +#define AUDIO_TERMINAL_EXTERNAL_UNDEFINED 0x0600 +#define AUDIO_TERMINAL_ANALOG_CONNECTOR 0x0601 +#define AUDIO_TERMINAL_DIGITAL_AUDIO_INTERFACE 0x0602 +#define AUDIO_TERMINAL_LINE_CONNECTOR 0x0603 +#define AUDIO_TERMINAL_LEGACY_AUDIO_CONNECTOR 0x0604 +#define AUDIO_TERMINAL_SPDIF_INTERFACE 0x0605 +#define AUDIO_TERMINAL_1394_DA_STREAM 0x0606 +#define AUDIO_TERMINAL_1394_DA_STREAM_TRACK 0x0607 + +/* Embedded Function Terminal Types */ +#define AUDIO_TERMINAL_EMBEDDED_UNDEFINED 0x0700 +#define AUDIO_TERMINAL_CALIBRATION_NOISE 0x0701 +#define AUDIO_TERMINAL_EQUALIZATION_NOISE 0x0702 +#define AUDIO_TERMINAL_CD_PLAYER 0x0703 +#define AUDIO_TERMINAL_DAT 0x0704 +#define AUDIO_TERMINAL_DCC 0x0705 +#define AUDIO_TERMINAL_MINI_DISK 0x0706 +#define AUDIO_TERMINAL_ANALOG_TAPE 0x0707 +#define AUDIO_TERMINAL_PHONOGRAPH 0x0708 +#define AUDIO_TERMINAL_VCR_AUDIO 0x0709 +#define AUDIO_TERMINAL_VIDEO_DISC_AUDIO 0x070A +#define AUDIO_TERMINAL_DVD_AUDIO 0x070B +#define AUDIO_TERMINAL_TV_TUNER_AUDIO 0x070C +#define AUDIO_TERMINAL_SATELLITE_RECEIVER_AUDIO 0x070D +#define AUDIO_TERMINAL_CABLE_TUNER_AUDIO 0x070E +#define AUDIO_TERMINAL_DSS_AUDIO 0x070F +#define AUDIO_TERMINAL_RADIO_RECEIVER 0x0710 +#define AUDIO_TERMINAL_RADIO_TRANSMITTER 0x0711 +#define AUDIO_TERMINAL_MULTI_TRACK_RECORDER 0x0712 +#define AUDIO_TERMINAL_SYNTHESIZER 0x0713 + + +#endif /* __AUDIO_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_cdc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_cdc.h new file mode 100644 index 0000000..5703539 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_cdc.h @@ -0,0 +1,249 @@ +/*********************************************************************** +* $Id:: mw_usbd_cdc.h 165 2011-04-14 17:41:11Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Communication Device Class User module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __CDC_H +#define __CDC_H + +#include "usbd.h" + +/*---------------------------------------------------------------------------- + * Definitions based on usbcdc11.pdf (www.usb.org) + *---------------------------------------------------------------------------*/ +/* Communication device class specification version 1.10 */ +#define CDC_V1_10 0x0110 + +/* Communication interface class code */ +/* (usbcdc11.pdf, 4.2, Table 15) */ +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 + +/* Communication interface class subclass codes */ +/* (usbcdc11.pdf, 4.3, Table 16) */ +#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01 +#define CDC_ABSTRACT_CONTROL_MODEL 0x02 +#define CDC_TELEPHONE_CONTROL_MODEL 0x03 +#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04 +#define CDC_CAPI_CONTROL_MODEL 0x05 +#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06 +#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07 + +/* Communication interface class control protocol codes */ +/* (usbcdc11.pdf, 4.4, Table 17) */ +#define CDC_PROTOCOL_COMMON_AT_COMMANDS 0x01 + +/* Data interface class code */ +/* (usbcdc11.pdf, 4.5, Table 18) */ +#define CDC_DATA_INTERFACE_CLASS 0x0A + +/* Data interface class protocol codes */ +/* (usbcdc11.pdf, 4.7, Table 19) */ +#define CDC_PROTOCOL_ISDN_BRI 0x30 +#define CDC_PROTOCOL_HDLC 0x31 +#define CDC_PROTOCOL_TRANSPARENT 0x32 +#define CDC_PROTOCOL_Q921_MANAGEMENT 0x50 +#define CDC_PROTOCOL_Q921_DATA_LINK 0x51 +#define CDC_PROTOCOL_Q921_MULTIPLEXOR 0x52 +#define CDC_PROTOCOL_V42 0x90 +#define CDC_PROTOCOL_EURO_ISDN 0x91 +#define CDC_PROTOCOL_V24_RATE_ADAPTATION 0x92 +#define CDC_PROTOCOL_CAPI 0x93 +#define CDC_PROTOCOL_HOST_BASED_DRIVER 0xFD +#define CDC_PROTOCOL_DESCRIBED_IN_PUFD 0xFE + +/* Type values for bDescriptorType field of functional descriptors */ +/* (usbcdc11.pdf, 5.2.3, Table 24) */ +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 + +/* Type values for bDescriptorSubtype field of functional descriptors */ +/* (usbcdc11.pdf, 5.2.3, Table 25) */ +#define CDC_HEADER 0x00 +#define CDC_CALL_MANAGEMENT 0x01 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_DIRECT_LINE_MANAGEMENT 0x03 +#define CDC_TELEPHONE_RINGER 0x04 +#define CDC_REPORTING_CAPABILITIES 0x05 +#define CDC_UNION 0x06 +#define CDC_COUNTRY_SELECTION 0x07 +#define CDC_TELEPHONE_OPERATIONAL_MODES 0x08 +#define CDC_USB_TERMINAL 0x09 +#define CDC_NETWORK_CHANNEL 0x0A +#define CDC_PROTOCOL_UNIT 0x0B +#define CDC_EXTENSION_UNIT 0x0C +#define CDC_MULTI_CHANNEL_MANAGEMENT 0x0D +#define CDC_CAPI_CONTROL_MANAGEMENT 0x0E +#define CDC_ETHERNET_NETWORKING 0x0F +#define CDC_ATM_NETWORKING 0x10 + +/* CDC class-specific request codes */ +/* (usbcdc11.pdf, 6.2, Table 46) */ +/* see Table 45 for info about the specific requests. */ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_AUX_LINE_STATE 0x10 +#define CDC_SET_HOOK_STATE 0x11 +#define CDC_PULSE_SETUP 0x12 +#define CDC_SEND_PULSE 0x13 +#define CDC_SET_PULSE_TIME 0x14 +#define CDC_RING_AUX_JACK 0x15 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 +#define CDC_SET_RINGER_PARMS 0x30 +#define CDC_GET_RINGER_PARMS 0x31 +#define CDC_SET_OPERATION_PARMS 0x32 +#define CDC_GET_OPERATION_PARMS 0x33 +#define CDC_SET_LINE_PARMS 0x34 +#define CDC_GET_LINE_PARMS 0x35 +#define CDC_DIAL_DIGITS 0x36 +#define CDC_SET_UNIT_PARAMETER 0x37 +#define CDC_GET_UNIT_PARAMETER 0x38 +#define CDC_CLEAR_UNIT_PARAMETER 0x39 +#define CDC_GET_PROFILE 0x3A +#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define CDC_SET_ETHERNET_PMP_FILTER 0x41 +#define CDC_GET_ETHERNET_PMP_FILTER 0x42 +#define CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define CDC_GET_ETHERNET_STATISTIC 0x44 +#define CDC_SET_ATM_DATA_FORMAT 0x50 +#define CDC_GET_ATM_DEVICE_STATISTICS 0x51 +#define CDC_SET_ATM_DEFAULT_VC 0x52 +#define CDC_GET_ATM_VC_STATISTICS 0x53 + +/* Communication feature selector codes */ +/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */ +#define CDC_ABSTRACT_STATE 0x01 +#define CDC_COUNTRY_SETTING 0x02 + +/* Feature Status returned for ABSTRACT_STATE Selector */ +/* (usbcdc11.pdf, 6.2.3, Table 48) */ +#define CDC_IDLE_SETTING (1 << 0) +#define CDC_DATA_MULTPLEXED_STATE (1 << 1) + + +/* Control signal bitmap values for the SetControlLineState request */ +/* (usbcdc11.pdf, 6.2.14, Table 51) */ +#define CDC_DTE_PRESENT (1 << 0) +#define CDC_ACTIVATE_CARRIER (1 << 1) + +/* CDC class-specific notification codes */ +/* (usbcdc11.pdf, 6.3, Table 68) */ +/* see Table 67 for Info about class-specific notifications */ +#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00 +#define CDC_RESPONSE_AVAILABLE 0x01 +#define CDC_AUX_JACK_HOOK_STATE 0x08 +#define CDC_RING_DETECT 0x09 +#define CDC_NOTIFICATION_SERIAL_STATE 0x20 +#define CDC_CALL_STATE_CHANGE 0x28 +#define CDC_LINE_STATE_CHANGE 0x29 +#define CDC_CONNECTION_SPEED_CHANGE 0x2A + +/* UART state bitmap values (Serial state notification). */ +/* (usbcdc11.pdf, 6.3.5, Table 69) */ +#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */ +#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */ +#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */ +#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */ +#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */ +#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */ +#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */ + + +/*---------------------------------------------------------------------------- + * Structures based on usbcdc11.pdf (www.usb.org) + *---------------------------------------------------------------------------*/ + +/* Header functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.1) */ +/* This header must precede any list of class-specific descriptors. */ +PRE_PACK struct POST_PACK _CDC_HEADER_DESCRIPTOR{ + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */ + uint16_t bcdCDC; /* USB CDC specification release version */ +}; +typedef struct _CDC_HEADER_DESCRIPTOR CDC_HEADER_DESCRIPTOR; + +/* Call management functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.2) */ +/* Describes the processing of calls for the communication class interface. */ +PRE_PACK struct POST_PACK _CDC_CALL_MANAGEMENT_DESCRIPTOR { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */ + uint8_t bmCapabilities; /* capabilities that this configuration supports */ + uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */ +}; +typedef struct _CDC_CALL_MANAGEMENT_DESCRIPTOR CDC_CALL_MANAGEMENT_DESCRIPTOR; + +/* Abstract control management functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.3) */ +/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */ +PRE_PACK struct POST_PACK _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */ + uint8_t bmCapabilities; /* capabilities supported by this configuration */ +}; +typedef struct _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR; + +/* Union functional descriptors */ +/* (usbcdc11.pdf, 5.2.3.8) */ +/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */ +PRE_PACK struct POST_PACK _CDC_UNION_DESCRIPTOR { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* union functional descriptor subtype */ + uint8_t bMasterInterface; /* interface number designated as master */ +}; +typedef struct _CDC_UNION_DESCRIPTOR CDC_UNION_DESCRIPTOR; + +/* Union functional descriptors with one slave interface */ +/* (usbcdc11.pdf, 5.2.3.8) */ +PRE_PACK struct POST_PACK _CDC_UNION_1SLAVE_DESCRIPTOR { + CDC_UNION_DESCRIPTOR sUnion; /* Union functional descriptor */ + uint8_t bSlaveInterfaces[1]; /* Slave interface 0 */ +}; +typedef struct _CDC_UNION_1SLAVE_DESCRIPTOR CDC_UNION_1SLAVE_DESCRIPTOR; + +/* Line coding structure */ +/* Format of the data returned when a GetLineCoding request is received */ +/* (usbcdc11.pdf, 6.2.13) */ +PRE_PACK struct POST_PACK _CDC_LINE_CODING { + uint32_t dwDTERate; /* Data terminal rate in bits per second */ + uint8_t bCharFormat; /* Number of stop bits */ + uint8_t bParityType; /* Parity bit type */ + uint8_t bDataBits; /* Number of data bits */ +}; +typedef struct _CDC_LINE_CODING CDC_LINE_CODING; + +/* Notification header */ +/* Data sent on the notification endpoint must follow this header. */ +/* see USB_SETUP_PACKET in file usb.h */ +typedef USB_SETUP_PACKET CDC_NOTIFICATION_HEADER; + +#endif /* __CDC_H */ + diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_cdcuser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_cdcuser.h new file mode 100644 index 0000000..5eef601 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_cdcuser.h @@ -0,0 +1,529 @@ +/*********************************************************************** +* $Id:: mw_usbd_cdcuser.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Communication Device Class User module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __CDCUSER_H__ +#define __CDCUSER_H__ + +#include "error.h" +#include "usbd.h" +#include "usbd_cdc.h" + +/** \file + * \brief Communication Device Class (CDC) API structures and function prototypes. + * + * Definition of functions exported by ROM based CDC function driver. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_CDC Communication Device Class (CDC) Function Driver + * \section Sec_CDCModDescription Module Description + * CDC Class Function Driver module. This module contains an internal implementation of the USB CDC Class. + * + * User applications can use this class driver instead of implementing the CDC-ACM class manually + * via the low-level USBD_HW and USBD_Core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB CDC-ACM Class. + */ + +/*---------------------------------------------------------------------------- + We need a buffer for incoming data on USB port because USB receives + much faster than UART transmits + *---------------------------------------------------------------------------*/ +/* Buffer masks */ +#define CDC_BUF_SIZE (128) /* Output buffer in bytes (power 2) */ + /* large enough for file transfer */ +#define CDC_BUF_MASK (CDC_BUF_SIZE-1ul) + +/** \brief Communication Device Class function driver initialization parameter data structure. + * \ingroup USBD_CDC + * + * \details This data structure is used to pass initialization parameters to the + * Communication Device Class function driver's init function. + * + */ +typedef struct USBD_CDC_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_CDC_API::GetMemSize() routine.*/ + /** Pointer to the control interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. The stack assumes both HS and FS use same BULK endpoints. + */ + uint8_t* cif_intf_desc; + /** Pointer to the data interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. The stack assumes both HS and FS use same BULK endpoints. + */ + uint8_t* dif_intf_desc; + + /* user defined functions */ + + /* required functions */ + /** + * Communication Interface Class specific get request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends CIC management element get requests. + * \note Applications implementing Abstract Control Model subclass can set this + * param to NULL. As the default driver parses ACM requests and calls the + * individual ACM call-back routines defined in this structure. For all other subclasses + * this routine should be provided by the application. + * \n + * The setup packet data (\em pSetup) is passed to the call-back so that application + * can extract the CIC request type and other associated data. By default the stack + * will assign \em pBuffer pointer to \em EP0Buff allocated at init. The application + * code can directly write data into this buffer as long as data is less than 64 byte. + * If more data has to be sent then application code should update \em pBuffer pointer + * and length accordingly. + * + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing request data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in, out] length Amount of data to be sent back to host. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CIC_GetRequest)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + + /** + * Communication Interface Class specific set request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a CIC management element requests. + * \note Applications implementing Abstract Control Model subclass can set this + * param to NULL. As the default driver parses ACM requests and calls the + * individual ACM call-back routines defined in this structure. For all other subclasses + * this routine should be provided by the application. + * \n + * The setup packet data (\em pSetup) is passed to the call-back so that application can + * extract the CIC request type and other associated data. If a set request has data associated, + * then this call-back is called twice. + * -# First when setup request is received, at this time application code could update + * \em pBuffer pointer to point to the intended destination. The length param is set to 0 + * so that application code knows this is first time. By default the stack will + * assign \em pBuffer pointer to \em EP0Buff allocated at init. Note, if data length is + * greater than 64 bytes and application code doesn't update \em pBuffer pointer the + * stack will send STALL condition to host. + * -# Second when the data is received from the host. This time the length param is set + * with number of data bytes received. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing request data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CIC_SetRequest)( USBD_HANDLE_T hCdc, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + + /** + * Communication Device Class specific BULK IN endpoint handler. + * + * The application software should provide the BULK IN endpoint handler. + * Applications should transfer data depending on the communication protocol type set in descriptors. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_BulkIN_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /** + * Communication Device Class specific BULK OUT endpoint handler. + * + * The application software should provide the BULK OUT endpoint handler. + * Applications should transfer data depending on the communication protocol type set in descriptors. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_BulkOUT_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /** + * Abstract control model(ACM) subclass specific SEND_ENCAPSULATED_COMMAND request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SEND_ENCAPSULATED_COMMAND set request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] buffer Pointer to the command buffer. + * \param[in] len Length of the command buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SendEncpsCmd) (USBD_HANDLE_T hCDC, uint8_t* buffer, uint16_t len); + + /** + * Abstract control model(ACM) subclass specific GET_ENCAPSULATED_RESPONSE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a GET_ENCAPSULATED_RESPONSE request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in, out] buffer Pointer to a pointer of data buffer containing response data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in, out] len Amount of data to be sent back to host. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*GetEncpsResp) (USBD_HANDLE_T hCDC, uint8_t** buffer, uint16_t* len); + + /** + * Abstract control model(ACM) subclass specific SET_COMM_FEATURE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SET_COMM_FEATURE set request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47. + * \param[in] buffer Pointer to the settings buffer for the specified communication feature. + * \param[in] len Length of the request buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t* buffer, uint16_t len); + + /** + * Abstract control model(ACM) subclass specific GET_COMM_FEATURE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a GET_ENCAPSULATED_RESPONSE request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47. + * \param[in, out] buffer Pointer to a pointer of data buffer containing current settings + * for the communication feature. + * Pointer-to-pointer is used to implement zero-copy buffers. + * \param[in, out] len Amount of data to be sent back to host. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*GetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t** pBuffer, uint16_t* len); + + /** + * Abstract control model(ACM) subclass specific CLEAR_COMM_FEATURE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a CLEAR_COMM_FEATURE request. In the call-back the application + * should Clears the settings for a particular communication feature. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] feature Communication feature type. See usbcdc11.pdf, section 6.2.4, Table 47. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*ClrCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature); + + /** + * Abstract control model(ACM) subclass specific SET_CONTROL_LINE_STATE request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SET_CONTROL_LINE_STATE request. RS-232 signal used to tell the DCE + * device the DTE device is now present + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] state The state value uses bitmap values defined in usbcdc11.pdf, + * section 6.2.14, Table 51. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SetCtrlLineState) (USBD_HANDLE_T hCDC, uint16_t state); + + /** + * Abstract control model(ACM) subclass specific SEND_BREAK request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SEND_BREAK request. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] mstime Duration of Break signal in milliseconds. If mstime is FFFFh, then + * the application should send break until another SendBreak request is received + * with the wValue of 0000h. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SendBreak) (USBD_HANDLE_T hCDC, uint16_t mstime); + + /** + * Abstract control model(ACM) subclass specific SET_LINE_CODING request call-back function. + * + * This function is provided by the application software. This function gets called + * when host sends a SET_LINE_CODING request. The application should configure the device + * per DTE rate, stop-bits, parity, and number-of-character bits settings provided in + * command buffer. See usbcdc11.pdf, section 6.2.13, table 50 for detail of the command buffer. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] line_coding Pointer to the CDC_LINE_CODING command buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*SetLineCode) (USBD_HANDLE_T hCDC, CDC_LINE_CODING* line_coding); + + /** + * Optional Communication Device Class specific INTERRUPT IN endpoint handler. + * + * The application software should provide the INT IN endpoint handler. + * Applications should transfer data depending on the communication protocol type set in descriptors. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_InterruptEP_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /** + * Optional user override-able function to replace the default CDC class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_CDC_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*CDC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +} USBD_CDC_INIT_PARAM_T; + +/** \brief CDC class API functions structure. + * \ingroup USBD_CDC + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_CDC_API +{ + /** \fn uint32_t GetMemSize(USBD_CDC_INIT_PARAM_T* param) + * Function to determine the memory required by the CDC function driver module. + * + * This function is called by application layer before calling pUsbApi->CDC->Init(), to allocate memory used + * by CDC function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing CDC function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_CDC_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param) + * Function to initialize CDC function driver module. + * + * This function is called by application layer to initialize CDC function driver module. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing CDC function driver module initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte + * aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either CDC_Write() or CDC_Read() or + * CDC_Verify() callbacks are not defined. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param, USBD_HANDLE_T* phCDC); + + /** \fn ErrorCode_t SendNotification(USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data) + * Function to send CDC class notifications to host. + * + * This function is called by application layer to send CDC class notifications to host. + * See usbcdc11.pdf, section 6.3, Table 67 for various notification types the CDC device can send. + * \note The current version of the driver only supports following notifications allowed by ACM subclass: + * CDC_NOTIFICATION_NETWORK_CONNECTION, CDC_RESPONSE_AVAILABLE, CDC_NOTIFICATION_SERIAL_STATE. + * \n + * For all other notifications application should construct the notification buffer appropriately + * and call hw->USB_WriteEP() for interrupt endpoint associated with the interface. + * + * \param[in] hCdc Handle to CDC function driver. + * \param[in] bNotification Notification type allowed by ACM subclass. Should be CDC_NOTIFICATION_NETWORK_CONNECTION, + * CDC_RESPONSE_AVAILABLE or CDC_NOTIFICATION_SERIAL_STATE. For all other types ERR_API_INVALID_PARAM2 + * is returned. See usbcdc11.pdf, section 3.6.2.1, table 5. + * \param[in] data Data associated with notification. + * \n For CDC_NOTIFICATION_NETWORK_CONNECTION a non-zero data value is interpreted as connected state. + * \n For CDC_RESPONSE_AVAILABLE this parameter is ignored. + * \n For CDC_NOTIFICATION_SERIAL_STATE the data should use bitmap values defined in usbcdc11.pdf, + * section 6.3.5, Table 69. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_API_INVALID_PARAM2 If unsupported notification type is passed. + * + */ + ErrorCode_t (*SendNotification)(USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data); + +} USBD_CDC_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _CDC_CTRL_T +{ + USB_CORE_CTRL_T* pUsbCtrl; + /* notification buffer */ + uint8_t notice_buf[12]; + CDC_LINE_CODING line_coding; + uint8_t pad0; + + uint8_t cif_num; /* control interface number */ + uint8_t dif_num; /* data interface number */ + uint8_t epin_num; /* BULK IN endpoint number */ + uint8_t epout_num; /* BULK OUT endpoint number */ + uint8_t epint_num; /* Interrupt IN endpoint number */ + uint8_t pad[3]; + /* user defined functions */ + ErrorCode_t (*SendEncpsCmd) (USBD_HANDLE_T hCDC, uint8_t* buffer, uint16_t len); + ErrorCode_t (*GetEncpsResp) (USBD_HANDLE_T hCDC, uint8_t** buffer, uint16_t* len); + ErrorCode_t (*SetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t* buffer, uint16_t len); + ErrorCode_t (*GetCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature, uint8_t** pBuffer, uint16_t* len); + ErrorCode_t (*ClrCommFeature) (USBD_HANDLE_T hCDC, uint16_t feature); + ErrorCode_t (*SetCtrlLineState) (USBD_HANDLE_T hCDC, uint16_t state); + ErrorCode_t (*SendBreak) (USBD_HANDLE_T hCDC, uint16_t state); + ErrorCode_t (*SetLineCode) (USBD_HANDLE_T hCDC, CDC_LINE_CODING* line_coding); + + /* virtual functions */ + ErrorCode_t (*CIC_GetRequest)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + ErrorCode_t (*CIC_SetRequest)( USBD_HANDLE_T hCdc, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + +} USB_CDC_CTRL_T; + +/* structure used by old ROM drivers, needed for workaround */ +typedef struct _CDC0_CTRL_T { + USB_CORE_CTRL_T *pUsbCtrl; + /* notification buffer */ + uint8_t notice_buf[12]; + CDC_LINE_CODING line_coding; + + uint8_t cif_num; /* control interface number */ + uint8_t dif_num; /* data interface number */ + uint8_t epin_num; /* BULK IN endpoint number */ + uint8_t epout_num; /* BULK OUT endpoint number */ + uint8_t epint_num; /* Interrupt IN endpoint number */ + /* user defined functions */ + ErrorCode_t (*SendEncpsCmd)(USBD_HANDLE_T hCDC, uint8_t *buffer, uint16_t len); + ErrorCode_t (*GetEncpsResp)(USBD_HANDLE_T hCDC, uint8_t * *buffer, uint16_t *len); + ErrorCode_t (*SetCommFeature)(USBD_HANDLE_T hCDC, uint16_t feature, uint8_t *buffer, uint16_t len); + ErrorCode_t (*GetCommFeature)(USBD_HANDLE_T hCDC, uint16_t feature, uint8_t * *pBuffer, uint16_t *len); + ErrorCode_t (*ClrCommFeature)(USBD_HANDLE_T hCDC, uint16_t feature); + ErrorCode_t (*SetCtrlLineState)(USBD_HANDLE_T hCDC, uint16_t state); + ErrorCode_t (*SendBreak)(USBD_HANDLE_T hCDC, uint16_t state); + ErrorCode_t (*SetLineCode)(USBD_HANDLE_T hCDC, CDC_LINE_CODING *line_coding); + + /* virtual functions */ + ErrorCode_t (*CIC_GetRequest)(USBD_HANDLE_T hHid, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t *length); + ErrorCode_t (*CIC_SetRequest)(USBD_HANDLE_T hCdc, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t length); + +} USB_CDC0_CTRL_T; + +typedef ErrorCode_t (*CIC_SetRequest_t)(USBD_HANDLE_T hCdc, USB_SETUP_PACKET *pSetup, uint8_t * *pBuffer, uint16_t length); + +/** @cond DIRECT_API */ +extern uint32_t mwCDC_GetMemSize(USBD_CDC_INIT_PARAM_T* param); +extern ErrorCode_t mwCDC_init(USBD_HANDLE_T hUsb, USBD_CDC_INIT_PARAM_T* param, USBD_HANDLE_T* phCDC); +extern ErrorCode_t mwCDC_SendNotification (USBD_HANDLE_T hCdc, uint8_t bNotification, uint16_t data); +/** @endcond */ + +/** @endcond */ + + + + + +#endif /* __CDCUSER_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_core.h b/source/lpc_chip_11u6x/inc/usbd/usbd_core.h new file mode 100644 index 0000000..dbbbcbe --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_core.h @@ -0,0 +1,585 @@ +/*********************************************************************** +* $Id:: mw_usbd_core.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB core controller structure definitions and function prototypes. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MW_USBD_CORE_H__ +#define __MW_USBD_CORE_H__ + +#include "error.h" +#include "usbd.h" +#include "app_usbd_cfg.h" + +/** \file + * \brief ROM API for USB device stack. + * + * Definition of functions exported by core layer of ROM based USB device stack. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_Core USB Core Layer + * \section Sec_CoreModDescription Module Description + * The USB Core Layer implements the device abstraction defined in the Universal Serial Bus Specification, + * for applications to interact with the USB device interface on the device. The software in this layer responds to + * standard requests and returns standard descriptors. In current stack the Init() routine part of + * \ref USBD_HW_API_T structure initializes both hardware layer and core layer. + */ + + +/* function pointer types */ + +/** \ingroup USBD_Core + * \typedef USB_CB_T + * \brief USB device stack's event callback function type. + * + * The USB device stack exposes several event triggers through callback to application layer. The + * application layer can register methods to be called when such USB event happens. + * + * \param[in] hUsb Handle to the USB device stack. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx Other error conditions. + * + */ +typedef ErrorCode_t (*USB_CB_T) (USBD_HANDLE_T hUsb); + +/** \ingroup USBD_Core + * \typedef USB_PARAM_CB_T + * \brief USB device stack's event callback function type. + * + * The USB device stack exposes several event triggers through callback to application layer. The + * application layer can register methods to be called when such USB event happens. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] param1 Extra information related to the event. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ +typedef ErrorCode_t (*USB_PARAM_CB_T) (USBD_HANDLE_T hUsb, uint32_t param1); + +/** \ingroup USBD_Core + * \typedef USB_EP_HANDLER_T + * \brief USBD setup request and endpoint event handler type. + * + * The application layer should define the custom class's EP0 handler with function signature. + * The stack calls all the registered class handlers on any EP0 event before going through default + * handling of the event. This gives the class handlers to implement class specific request handlers + * and also to override the default stack handling for a particular event targeted to the interface. + * If an event is not handled by the callback the function should return ERR_USBD_UNHANDLED. For all + * other return codes the stack assumes that callback has taken care of the event and hence will not + * process the event any further and issues a STALL condition on EP0 indicating error to the host. + * \n + * For endpoint interrupt handler the return value is ignored by the stack. + * \n + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ +typedef ErrorCode_t (*USB_EP_HANDLER_T)(USBD_HANDLE_T hUsb, void* data, uint32_t event); + + +/** \ingroup USBD_Core + * \brief USB descriptors data structure. + * \ingroup USBD_Core + * + * \details This structure is used as part of USB device stack initialization + * parameter structure \ref USBD_API_INIT_PARAM_T. This structure contains + * pointers to various descriptor arrays needed by the stack. These descriptors + * are reported to USB host as part of enumerations process. + * + * \note All descriptor pointers assigned in this structure should be on 4 byte + * aligned address boundary. + */ +typedef struct _USB_CORE_DESCS_T +{ + uint8_t *device_desc; /**< Pointer to USB device descriptor */ + uint8_t *string_desc; /**< Pointer to array of USB string descriptors */ + uint8_t *full_speed_desc; /**< Pointer to USB device configuration descriptor + * when device is operating in full speed mode. + */ + uint8_t *high_speed_desc; /**< Pointer to USB device configuration descriptor + * when device is operating in high speed mode. For + * full-speed only implementation this pointer should + * be same as full_speed_desc. + */ + uint8_t *device_qualifier; /**< Pointer to USB device qualifier descriptor. For + * full-speed only implementation this pointer should + * be set to null (0). + */ +} USB_CORE_DESCS_T; + +/** \brief USB device stack initialization parameter data structure. + * \ingroup USBD_Core + * + * \details This data structure is used to pass initialization parameters to the + * USB device stack's init function. + * + */ +typedef struct USBD_API_INIT_PARAM +{ + uint32_t usb_reg_base; /**< USB device controller's base register address. */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 2048 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_HW_API::GetMemSize() routine.*/ + uint8_t max_num_ep; /**< max number of endpoints supported by the USB device + controller instance (specified by \em usb_reg_base field) + to which this instance of stack is attached. + */ + uint8_t pad0[3]; + /* USB Device Events Callback Functions */ + /** Event for USB interface reset. This event fires when the USB host requests that the device + * reset its interface. This event fires after the control endpoint has been automatically + * configured by the library. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Reset_Event; + + /** Event for USB suspend. This event fires when the USB host suspends the device by halting its + * transmission of Start Of Frame pulses to the device. This is generally hooked in order to move + * the device over to a low power state until the host wakes up the device. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will cause other system issues. + */ + USB_CB_T USB_Suspend_Event; + + /** Event for USB wake up or resume. This event fires when a the USB device interface is suspended + * and the host wakes up the device by supplying Start Of Frame pulses. This is generally + * hooked to pull the user application out of a low power state and back into normal operating + * mode. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will cause other system issues. + * + */ + USB_CB_T USB_Resume_Event; + + /** Reserved parameter should be set to zero. */ + USB_CB_T reserved_sbz; + + /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB + * frame, once per millisecond in full-speed mode or once per 125 microseconds in high-speed mode, + * and is synchronized to the USB bus. + * + * This event is time-critical; it is run once per millisecond (full-speed mode) and thus long handlers + * will significantly degrade device performance. This event should only be enabled when needed to + * reduce device wake-ups. + * + * \note This event is not normally active - it must be manually enabled and disabled via the USB interrupt + * register. + * \n\n + */ + USB_CB_T USB_SOF_Event; + + /** Event for remote wake-up configuration, when enabled. This event fires when the USB host + * request the device to configure itself for remote wake-up capability. The USB host sends + * this request to device which report remote wake-up capable in their device descriptors, + * before going to low-power state. The application layer should implement this callback if + * they have any special on board circuit to trigger remote wake up event. Also application + * can use this callback to differentiate the following SUSPEND event is caused by cable plug-out + * or host SUSPEND request. The device can wake-up host only after receiving this callback and + * remote wake-up feature is enabled by host. To signal remote wake-up the device has to generate + * resume signaling on bus by calling usapi.hw->WakeUp() routine. + * + * \n\n + * \param[in] hUsb Handle to the USB device stack. + * \param[in] param1 When 0 - Clear the wake-up configuration, 1 - Enable the wake-up configuration. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + */ + USB_PARAM_CB_T USB_WakeUpCfg; + + /** Reserved parameter should be set to zero. */ + USB_PARAM_CB_T USB_Power_Event; + + /** Event for error condition. This event fires when USB device controller detect + * an error condition in the system. + * + * \n\n + * \param[in] hUsb Handle to the USB device stack. + * \param[in] param1 USB device interrupt status register. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + */ + USB_PARAM_CB_T USB_Error_Event; + + /* USB Core Events Callback Functions */ + /** Event for USB configuration number changed. This event fires when a the USB host changes the + * selected configuration number. On receiving configuration change request from host, the stack + * enables/configures the endpoints needed by the new configuration before calling this callback + * function. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Configure_Event; + + /** Event for USB interface setting changed. This event fires when a the USB host changes the + * interface setting to one of alternate interface settings. On receiving interface change + * request from host, the stack enables/configures the endpoints needed by the new alternate + * interface setting before calling this callback function. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Interface_Event; + + /** Event for USB feature changed. This event fires when a the USB host send set/clear feature + * request. The stack handles this request for USB_FEATURE_REMOTE_WAKEUP, USB_FEATURE_TEST_MODE + * and USB_FEATURE_ENDPOINT_STALL features only. On receiving feature request from host, the + * stack handle the request appropriately and then calls this callback function. + * \n + * \note This event is called from USB_ISR context and hence is time-critical. Having delays in this + * callback will prevent the device from enumerating correctly or operate properly. + * + */ + USB_CB_T USB_Feature_Event; + + /* cache and MMU translation functions */ + /** Reserved parameter for future use. should be set to zero. */ + uint32_t (* virt_to_phys)(void* vaddr); + /** Reserved parameter for future use. should be set to zero. */ + void (* cache_flush)(uint32_t* start_adr, uint32_t* end_adr); + +} USBD_API_INIT_PARAM_T; + + +/** \brief USBD stack Core API functions structure. + * \ingroup USBD_Core + * + * \details This module exposes functions which interact directly with USB device stack's core layer. + * The application layer uses this component when it has to implement custom class function driver or + * standard class function driver which is not part of the current USB device stack. + * The functions exposed by this interface are to register class specific EP0 handlers and corresponding + * utility functions to manipulate EP0 state machine of the stack. This interface also exposes + * function to register custom endpoint interrupt handler. + * + */ +typedef struct USBD_CORE_API +{ + /** \fn ErrorCode_t RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data) + * Function to register class specific EP0 event handler with USB device stack. + * + * The application layer uses this function when it has to register the custom class's EP0 handler. + * The stack calls all the registered class handlers on any EP0 event before going through default + * handling of the event. This gives the class handlers to implement class specific request handlers + * and also to override the default stack handling for a particular event targeted to the interface. + * Check \ref USB_EP_HANDLER_T for more details on how the callback function should be implemented. Also + * application layer could use this function to register EP0 handler which responds to vendor specific + * requests. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] pfn Class specific EP0 handler function. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_TOO_MANY_CLASS_HDLR(0x0004000c) The number of class handlers registered is + greater than the number of handlers allowed by the stack. + * + */ + ErrorCode_t (*RegisterClassHandler)(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data); + + /** \fn ErrorCode_t RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data) + * Function to register interrupt/event handler for the requested endpoint with USB device stack. + * + * The application layer uses this function to register the endpoint event handler. + * The stack calls all the registered endpoint handlers when + * - USB_EVT_OUT or USB_EVT_OUT_NAK events happen for OUT endpoint. + * - USB_EVT_IN or USB_EVT_IN_NAK events happen for IN endpoint. + * Check USB_EP_HANDLER_T for more details on how the callback function should be implemented. + * \note By default endpoint _NAK events are not enabled. Application should call \ref USBD_HW_API_T::EnableEvent + * for the corresponding endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] ep_index Endpoint index. Computed as + * - For OUT endpoints = 2 * endpoint number eg. for EP2_OUT it is 4. + * - For IN endopoints = (2 * endpoint number) + 1 eg. for EP2_IN it is 5. + * \param[in] pfn Endpoint event handler function. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_API_INVALID_PARAM2 ep_index is outside the boundary ( < 2 * USBD_API_INIT_PARAM_T::max_num_ep). + * + */ + ErrorCode_t (*RegisterEpHandler)(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data); + + /** \fn void SetupStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in setup state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in setup state. This function will read + * the setup packet received from USB host into stack's buffer. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*SetupStage )(USBD_HANDLE_T hUsb); + + /** \fn void DataInStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in data_in state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in data_in state. This function will write + * the data present in EP0Data buffer to EP0 FIFO for transmission to host. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*DataInStage)(USBD_HANDLE_T hUsb); + + /** \fn void DataOutStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in data_out state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in data_out state. This function will read + * the control data (EP0 out packets) received from USB host into EP0Data buffer. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*DataOutStage)(USBD_HANDLE_T hUsb); + + /** \fn void StatusInStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in status_in state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in status_in state. This function will send + * zero length IN packet on EP0 to host, indicating positive status. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*StatusInStage)(USBD_HANDLE_T hUsb); + /** \fn void StatusOutStage(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in status_out state. + * + * This function is called by USB stack and the application layer to + * set the EP0 state machine in status_out state. This function will read + * the zero length OUT packet received from USB host on EP0. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*StatusOutStage)(USBD_HANDLE_T hUsb); + + /** \fn void StallEp0(USBD_HANDLE_T hUsb) + * Function to set EP0 state machine in stall state. + * + * This function is called by USB stack and the application layer to + * generate STALL signaling on EP0 endpoint. This function will also + * reset the EP0Data buffer. + * \n + * \note This interface is provided to users to invoke this function in other + * scenarios which are not handle by current stack. In most user applications + * this function is not called directly.Also this function can be used by + * users who are selectively modifying the USB device stack's standard handlers + * through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*StallEp0)(USBD_HANDLE_T hUsb); + +} USBD_CORE_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ + + /** @cond ADVANCED_API */ + +/* forward declaration */ +struct _USB_CORE_CTRL_T; +typedef struct _USB_CORE_CTRL_T USB_CORE_CTRL_T; + +/* USB device Speed status defines */ +#define USB_FULL_SPEED 0 +#define USB_HIGH_SPEED 1 + +/* USB Endpoint Data Structure */ +typedef struct _USB_EP_DATA +{ + uint8_t *pData; + uint16_t Count; + uint16_t pad0; +} USB_EP_DATA; + + +/* USB core controller data structure */ +struct _USB_CORE_CTRL_T +{ + /* override-able function pointers ~ c++ style virtual functions*/ + USB_CB_T USB_EvtSetupHandler; + USB_CB_T USB_EvtOutHandler; + USB_PARAM_CB_T USB_ReqVendor; + USB_CB_T USB_ReqGetStatus; + USB_CB_T USB_ReqGetDescriptor; + USB_CB_T USB_ReqGetConfiguration; + USB_CB_T USB_ReqSetConfiguration; + USB_CB_T USB_ReqGetInterface; + USB_CB_T USB_ReqSetInterface; + USB_PARAM_CB_T USB_ReqSetClrFeature; + + /* USB Device Events Callback Functions */ + USB_CB_T USB_Reset_Event; + USB_CB_T USB_Suspend_Event; + USB_CB_T USB_Resume_Event; + USB_CB_T USB_SOF_Event; + USB_PARAM_CB_T USB_Power_Event; + USB_PARAM_CB_T USB_Error_Event; + USB_PARAM_CB_T USB_WakeUpCfg; + + /* USB Core Events Callback Functions */ + USB_CB_T USB_Configure_Event; + USB_CB_T USB_Interface_Event; + USB_CB_T USB_Feature_Event; + + /* cache and MMU translation functions */ + uint32_t (* virt_to_phys)(void* vaddr); + void (* cache_flush)(uint32_t* start_adr, uint32_t* end_adr); + + /* event handlers for endpoints. */ + USB_EP_HANDLER_T ep_event_hdlr[2 * USB_MAX_EP_NUM]; + void* ep_hdlr_data[2 * USB_MAX_EP_NUM]; + + /* USB class handlers */ + USB_EP_HANDLER_T ep0_hdlr_cb[USB_MAX_IF_NUM]; + void* ep0_cb_data[USB_MAX_IF_NUM]; + uint8_t num_ep0_hdlrs; + /* USB Core data Variables */ + uint8_t max_num_ep; /* max number of endpoints supported by the HW */ + uint8_t device_speed; + uint8_t num_interfaces; + uint8_t device_addr; + uint8_t config_value; + uint16_t device_status; + uint8_t *device_desc; + uint8_t *string_desc; + uint8_t *full_speed_desc; + uint8_t *high_speed_desc; + uint8_t *device_qualifier; + uint32_t ep_mask; + uint32_t ep_halt; + uint32_t ep_stall; + uint8_t alt_setting[USB_MAX_IF_NUM]; + /* HW driver data pointer */ + void* hw_data; + + /* USB Endpoint 0 Data Info */ + USB_EP_DATA EP0Data; + + /* USB Endpoint 0 Buffer */ + //ALIGNED(4) + uint8_t EP0Buf[64]; + + /* USB Setup Packet */ + //ALIGNED(4) + USB_SETUP_PACKET SetupPacket; + +}; + +/* USB Core Functions */ +extern void mwUSB_InitCore(USB_CORE_CTRL_T* pCtrl, USB_CORE_DESCS_T* pdescr, USBD_API_INIT_PARAM_T* param); +extern void mwUSB_ResetCore(USBD_HANDLE_T hUsb); + +/* inline functions */ +static INLINE void USB_SetSpeedMode(USB_CORE_CTRL_T* pCtrl, uint8_t mode) +{ + pCtrl->device_speed = mode; +} + +static INLINE bool USB_IsConfigured(USBD_HANDLE_T hUsb) +{ + USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*) hUsb; + return (bool) (pCtrl->config_value != 0); +} + +/** @cond DIRECT_API */ +/* midleware API */ +extern ErrorCode_t mwUSB_RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data); +extern ErrorCode_t mwUSB_RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data); +extern void mwUSB_SetupStage (USBD_HANDLE_T hUsb); +extern void mwUSB_DataInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_DataOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StallEp0(USBD_HANDLE_T hUsb); +extern ErrorCode_t mwUSB_RegisterClassHandler(USBD_HANDLE_T hUsb, USB_EP_HANDLER_T pfn, void* data); +extern ErrorCode_t mwUSB_RegisterEpHandler(USBD_HANDLE_T hUsb, uint32_t ep_index, USB_EP_HANDLER_T pfn, void* data); +extern void mwUSB_SetupStage (USBD_HANDLE_T hUsb); +extern void mwUSB_DataInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_DataOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusInStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StatusOutStage(USBD_HANDLE_T hUsb); +extern void mwUSB_StallEp0(USBD_HANDLE_T hUsb); +/** @endcond */ + +/** @endcond */ + +#endif /* __MW_USBD_CORE_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_desc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_desc.h new file mode 100644 index 0000000..510f936 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_desc.h @@ -0,0 +1,48 @@ +/*********************************************************************** +* $Id:: mw_usbd_desc.h 165 2011-04-14 17:41:11Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Descriptors Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __USBDESC_H__ +#define __USBDESC_H__ + +#include "usbd.h" + +#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) +#define B3VAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF),(((x) >> 16) & 0xFF) + +#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR)) +#define USB_CONFIGUARTION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR)) +#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR)) +#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR)) +#define USB_DEVICE_QUALI_SIZE (sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) +#define USB_OTHER_SPEED_CONF_SIZE (sizeof(USB_OTHER_SPEED_CONFIGURATION)) + +//#define HID_DESC_SIZE (sizeof(HID_DESCRIPTOR)) +//#define HID_REPORT_DESC_SIZE (sizeof(HID_ReportDescriptor)) + +extern const uint8_t HID_ReportDescriptor[]; +extern const uint16_t HID_ReportDescSize; +extern const uint16_t HID_DescOffset; + + +#endif /* __USBDESC_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_dfu.h b/source/lpc_chip_11u6x/inc/usbd/usbd_dfu.h new file mode 100644 index 0000000..950f5a3 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_dfu.h @@ -0,0 +1,120 @@ +/*********************************************************************** +* $Id:: mw_usbd_dfu.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Device Firmware Upgrade (DFU) module. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MW_USBD_DFU_H__ +#define __MW_USBD_DFU_H__ + +#include "usbd.h" + +/** \file + * \brief Device Firmware Upgrade (DFU) class descriptors. + * + * Definition of DFU class descriptors and their bit defines. + * + */ + +/** + * If USB device is only DFU capable, DFU Interface number is always 0. + * if USB device is (DFU + Other Class (Audio/Mass Storage/HID), DFU + * Interface number should also be 0 in this implementation. + */ +#define USB_DFU_IF_NUM 0x0 + +#define USB_DFU_DESCRIPTOR_TYPE 0x21 +#define USB_DFU_DESCRIPTOR_SIZE 9 +#define USB_DFU_SUBCLASS 0x01 + +/* DFU class-specific requests (Section 3, DFU Rev 1.1) */ +#define USB_REQ_DFU_DETACH 0x00 +#define USB_REQ_DFU_DNLOAD 0x01 +#define USB_REQ_DFU_UPLOAD 0x02 +#define USB_REQ_DFU_GETSTATUS 0x03 +#define USB_REQ_DFU_CLRSTATUS 0x04 +#define USB_REQ_DFU_GETSTATE 0x05 +#define USB_REQ_DFU_ABORT 0x06 + +#define DFU_STATUS_OK 0x00 +#define DFU_STATUS_errTARGET 0x01 +#define DFU_STATUS_errFILE 0x02 +#define DFU_STATUS_errWRITE 0x03 +#define DFU_STATUS_errERASE 0x04 +#define DFU_STATUS_errCHECK_ERASED 0x05 +#define DFU_STATUS_errPROG 0x06 +#define DFU_STATUS_errVERIFY 0x07 +#define DFU_STATUS_errADDRESS 0x08 +#define DFU_STATUS_errNOTDONE 0x09 +#define DFU_STATUS_errFIRMWARE 0x0a +#define DFU_STATUS_errVENDOR 0x0b +#define DFU_STATUS_errUSBR 0x0c +#define DFU_STATUS_errPOR 0x0d +#define DFU_STATUS_errUNKNOWN 0x0e +#define DFU_STATUS_errSTALLEDPKT 0x0f + +enum dfu_state { + DFU_STATE_appIDLE = 0, + DFU_STATE_appDETACH = 1, + DFU_STATE_dfuIDLE = 2, + DFU_STATE_dfuDNLOAD_SYNC = 3, + DFU_STATE_dfuDNBUSY = 4, + DFU_STATE_dfuDNLOAD_IDLE = 5, + DFU_STATE_dfuMANIFEST_SYNC = 6, + DFU_STATE_dfuMANIFEST = 7, + DFU_STATE_dfuMANIFEST_WAIT_RST= 8, + DFU_STATE_dfuUPLOAD_IDLE = 9, + DFU_STATE_dfuERROR = 10 +}; + +#define DFU_EP0_NONE 0 +#define DFU_EP0_UNHANDLED 1 +#define DFU_EP0_STALL 2 +#define DFU_EP0_ZLP 3 +#define DFU_EP0_DATA 4 + +#define USB_DFU_CAN_DOWNLOAD (1 << 0) +#define USB_DFU_CAN_UPLOAD (1 << 1) +#define USB_DFU_MANIFEST_TOL (1 << 2) +#define USB_DFU_WILL_DETACH (1 << 3) + +PRE_PACK struct POST_PACK _USB_DFU_FUNC_DESCRIPTOR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; + uint16_t wDetachTimeOut; + uint16_t wTransferSize; + uint16_t bcdDFUVersion; +}; +typedef struct _USB_DFU_FUNC_DESCRIPTOR USB_DFU_FUNC_DESCRIPTOR; + +PRE_PACK struct POST_PACK _DFU_STATUS { + uint8_t bStatus; + uint8_t bwPollTimeout[3]; + uint8_t bState; + uint8_t iString; +}; +typedef struct _DFU_STATUS DFU_STATUS_T; + +#define DFU_FUNC_DESC_SIZE sizeof(USB_DFU_FUNC_DESCRIPTOR) +#define DFU_GET_STATUS_SIZE 0x6 + + +#endif /* __MW_USBD_DFU_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_dfuuser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_dfuuser.h new file mode 100644 index 0000000..1477aa1 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_dfuuser.h @@ -0,0 +1,270 @@ +/*********************************************************************** +* $Id:: mw_usbd_dfuuser.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Device Firmware Upgrade Class Custom User Module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __DFUUSER_H__ +#define __DFUUSER_H__ + +#include "usbd.h" +#include "usbd_dfu.h" +#include "usbd_core.h" + +/** \file + * \brief Device Firmware Upgrade (DFU) API structures and function prototypes. + * + * Definition of functions exported by ROM based DFU function driver. + * + */ + + +/** \ingroup Group_USBD + * @defgroup USBD_DFU Device Firmware Upgrade (DFU) Class Function Driver + * \section Sec_MSCModDescription Module Description + * DFU Class Function Driver module. This module contains an internal implementation of the USB DFU Class. + * User applications can use this class driver instead of implementing the DFU class manually + * via the low-level USBD_HW and USBD_Core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB DFU Class. + */ + +/** \brief USB descriptors data structure. + * \ingroup USBD_DFU + * + * \details This module exposes functions which interact directly with USB device stack's core layer. + * The application layer uses this component when it has to implement custom class function driver or + * standard class function driver which is not part of the current USB device stack. + * The functions exposed by this interface are to register class specific EP0 handlers and corresponding + * utility functions to manipulate EP0 state machine of the stack. This interface also exposes + * function to register custom endpoint interrupt handler. + * + */ +typedef struct USBD_DFU_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_DFU_API::GetMemSize() routine.*/ + /* DFU paramas */ + uint16_t wTransferSize; /**< DFU transfer block size in number of bytes. + This value should match the value set in DFU descriptor + provided as part of the descriptor array + (\em high_speed_desc) passed to Init() through + \ref USB_CORE_DESCS_T structure. */ + + uint16_t pad; + /** Pointer to the DFU interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. + */ + uint8_t* intf_desc; + /* user defined functions */ + /** + * DFU Write callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a write command. For application using zero-copy buffer scheme + * this function is called for the first time with \em length parameter set to 0. + * The application code should update the buffer pointer. + * + * \param[in] block_num Destination start address. + * \param[in, out] src Pointer to a pointer to the source of data. Pointer-to-pointer + * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy + * for more details on zero-copy concept. + * \param[out] bwPollTimeout Pointer to a 3 byte buffer which the callback implementer + * should fill with the amount of minimum time, in milliseconds, + * that the host should wait before sending a subsequent + * DFU_GETSTATUS request. + * \param[in] length Number of bytes to be written. + * \return Returns DFU_STATUS_ values defined in mw_usbd_dfu.h. + * + */ + uint8_t (*DFU_Write)( uint32_t block_num, uint8_t** src, uint32_t length, uint8_t* bwPollTimeout); + + /** + * DFU Read callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a read command. + * + * \param[in] block_num Destination start address. + * \param[in, out] dst Pointer to a pointer to the source of data. Pointer-to-pointer + * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy + * for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return Returns + * - DFU_STATUS_ values defined in mw_usbd_dfu.h to return error conditions. + * - 0 if there is no more data to be read. Stack will send EOF frame and set + * DFU state-machine to dfuIdle state. + * - length of the data copied, should be greater than or equal to 16. If the data copied + * is less than DFU \em wTransferSize the stack will send EOF frame and + * goes to dfuIdle state. + * + */ + uint32_t (*DFU_Read)( uint32_t block_num, uint8_t** dst, uint32_t length); + + /** + * DFU done callback function. + * + * This function is provided by the application software. This function gets called + * after firmware download completes. + * + * \return Nothing. + * + */ + void (*DFU_Done)(void); + + /** + * DFU detach callback function. + * + * This function is provided by the application software. This function gets called + * after USB_REQ_DFU_DETACH is received. Applications which set USB_DFU_WILL_DETACH + * bit in DFU descriptor should define this function. As part of this function + * application can call Connect() routine to disconnect and then connect back with + * host. For application which rely on WinUSB based host application should use this + * feature since USB reset can be invoked only by kernel drivers on Windows host. + * By implementing this feature host doen't have to issue reset instead the device + * has to do it automatically by disconnect and connect procedure. + * + * \param[in] hUsb Handle DFU control structure. + * \return Nothing. + * + */ + void (*DFU_Detach)(USBD_HANDLE_T hUsb); + + /** + * Optional user override-able function to replace the default DFU class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_DFU_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*DFU_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +} USBD_DFU_INIT_PARAM_T; + + +/** \brief DFU class API functions structure. + * \ingroup USBD_DFU + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_DFU_API +{ + /** \fn uint32_t GetMemSize(USBD_DFU_INIT_PARAM_T* param) + * Function to determine the memory required by the DFU function driver module. + * + * This function is called by application layer before calling pUsbApi->dfu->Init(), to allocate memory used + * by DFU function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing DFU function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_DFU_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param) + * Function to initialize DFU function driver module. + * + * This function is called by application layer to initialize DFU function driver module. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing DFU function driver module initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either DFU_Write() or DFU_Done() or DFU_Read() call-backs are not defined. + * \retval ERR_USBD_BAD_DESC + * - USB_DFU_DESCRIPTOR_TYPE is not defined immediately after + * interface descriptor. + * - wTransferSize in descriptor doesn't match the value passed + * in param->wTransferSize. + * - DFU_Detach() is not defined while USB_DFU_WILL_DETACH is set + * in DFU descriptor. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param, uint32_t init_state); + +} USBD_DFU_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _USBD_DFU_CTRL_T +{ + /*ALIGNED(4)*/ DFU_STATUS_T dfu_req_get_status; + uint16_t pad; + uint8_t dfu_state; + uint8_t dfu_status; + uint8_t download_done; + uint8_t if_num; /* interface number */ + + uint8_t* xfr_buf; + USB_DFU_FUNC_DESCRIPTOR* dfu_desc; + + USB_CORE_CTRL_T* pUsbCtrl; + /* user defined functions */ + /* return DFU_STATUS_ values defined in mw_usbd_dfu.h */ + uint8_t (*DFU_Write)( uint32_t block_num, uint8_t** src, uint32_t length, uint8_t* bwPollTimeout); + /* return + * DFU_STATUS_ : values defined in mw_usbd_dfu.h in case of errors + * 0 : If end of memory reached + * length : Amount of data copied to destination buffer + */ + uint32_t (*DFU_Read)( uint32_t block_num, uint8_t** dst, uint32_t length); + /* callback called after download is finished */ + void (*DFU_Done)(void); + /* callback called after USB_REQ_DFU_DETACH is recived */ + void (*DFU_Detach)(USBD_HANDLE_T hUsb); + +} USBD_DFU_CTRL_T; + +/** @cond DIRECT_API */ +uint32_t mwDFU_GetMemSize(USBD_DFU_INIT_PARAM_T* param); +extern ErrorCode_t mwDFU_init(USBD_HANDLE_T hUsb, USBD_DFU_INIT_PARAM_T* param, uint32_t init_state); +/** @endcond */ + +/** @endcond */ + +#endif /* __DFUUSER_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_hid.h b/source/lpc_chip_11u6x/inc/usbd/usbd_hid.h new file mode 100644 index 0000000..b1e88cf --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_hid.h @@ -0,0 +1,430 @@ +/*********************************************************************** +* $Id: mw_usbd_hid.h.rca 1.2 Tue Nov 1 11:45:07 2011 nlv09221 Experimental $ +* +* Project: USB device ROM Stack +* +* Description: +* HID Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __HID_H__ +#define __HID_H__ + +#include "usbd.h" + +/** \file + * \brief Common definitions and declarations for the library USB HID Class driver. + * + * Common definitions and declarations for the library USB HID Class driver. + * \addtogroup USBD_HID + * @{ + */ + + +/** HID Subclass Codes + * @{ + */ +/** Descriptor Subclass value indicating that the device or interface does not implement a HID boot protocol. */ +#define HID_SUBCLASS_NONE 0x00 +/** Descriptor Subclass value indicating that the device or interface implements a HID boot protocol. */ +#define HID_SUBCLASS_BOOT 0x01 +/** @} */ + +/** HID Protocol Codes + * @{ + */ +/** Descriptor Protocol value indicating that the device or interface does not belong to a HID boot protocol. */ +#define HID_PROTOCOL_NONE 0x00 +/** Descriptor Protocol value indicating that the device or interface belongs to the Keyboard HID boot protocol. */ +#define HID_PROTOCOL_KEYBOARD 0x01 +/** Descriptor Protocol value indicating that the device or interface belongs to the Mouse HID boot protocol. */ +#define HID_PROTOCOL_MOUSE 0x02 +/** @} */ + + + +/** Descriptor Types + * @{ + */ +/** Descriptor header type value, to indicate a HID class HID descriptor. */ +#define HID_HID_DESCRIPTOR_TYPE 0x21 +/** Descriptor header type value, to indicate a HID class HID report descriptor. */ +#define HID_REPORT_DESCRIPTOR_TYPE 0x22 +/** Descriptor header type value, to indicate a HID class HID Physical descriptor. */ +#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 +/** @} */ + + +/** \brief HID class-specific HID Descriptor. + * + * Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID + * specification for details on the structure elements. + * + */ +PRE_PACK struct POST_PACK _HID_DESCRIPTOR { + uint8_t bLength; /**< Size of the descriptor, in bytes. */ + uint8_t bDescriptorType; /**< Type of HID descriptor. */ + uint16_t bcdHID; /**< BCD encoded version that the HID descriptor and device complies to. */ + uint8_t bCountryCode; /**< Country code of the localized device, or zero if universal. */ + uint8_t bNumDescriptors; /**< Total number of HID report descriptors for the interface. */ + + PRE_PACK struct POST_PACK _HID_DESCRIPTOR_LIST { + uint8_t bDescriptorType; /**< Type of HID report. */ + uint16_t wDescriptorLength; /**< Length of the associated HID report descriptor, in bytes. */ + } DescriptorList[1]; /**< Array of one or more descriptors */ +} ; +/** HID class-specific HID Descriptor. */ +typedef struct _HID_DESCRIPTOR HID_DESCRIPTOR; + +#define HID_DESC_SIZE sizeof(HID_DESCRIPTOR) + +/** HID Request Codes + * @{ + */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B +/** @} */ + +/** HID Report Types + * @{ + */ +#define HID_REPORT_INPUT 0x01 +#define HID_REPORT_OUTPUT 0x02 +#define HID_REPORT_FEATURE 0x03 +/** @} */ + + +/** Usage Pages + * @{ + */ +#define HID_USAGE_PAGE_UNDEFINED 0x00 +#define HID_USAGE_PAGE_GENERIC 0x01 +#define HID_USAGE_PAGE_SIMULATION 0x02 +#define HID_USAGE_PAGE_VR 0x03 +#define HID_USAGE_PAGE_SPORT 0x04 +#define HID_USAGE_PAGE_GAME 0x05 +#define HID_USAGE_PAGE_DEV_CONTROLS 0x06 +#define HID_USAGE_PAGE_KEYBOARD 0x07 +#define HID_USAGE_PAGE_LED 0x08 +#define HID_USAGE_PAGE_BUTTON 0x09 +#define HID_USAGE_PAGE_ORDINAL 0x0A +#define HID_USAGE_PAGE_TELEPHONY 0x0B +#define HID_USAGE_PAGE_CONSUMER 0x0C +#define HID_USAGE_PAGE_DIGITIZER 0x0D +#define HID_USAGE_PAGE_UNICODE 0x10 +#define HID_USAGE_PAGE_ALPHANUMERIC 0x14 +/** @} */ + + +/** Generic Desktop Page (0x01) + * @{ + */ +#define HID_USAGE_GENERIC_POINTER 0x01 +#define HID_USAGE_GENERIC_MOUSE 0x02 +#define HID_USAGE_GENERIC_JOYSTICK 0x04 +#define HID_USAGE_GENERIC_GAMEPAD 0x05 +#define HID_USAGE_GENERIC_KEYBOARD 0x06 +#define HID_USAGE_GENERIC_KEYPAD 0x07 +#define HID_USAGE_GENERIC_X 0x30 +#define HID_USAGE_GENERIC_Y 0x31 +#define HID_USAGE_GENERIC_Z 0x32 +#define HID_USAGE_GENERIC_RX 0x33 +#define HID_USAGE_GENERIC_RY 0x34 +#define HID_USAGE_GENERIC_RZ 0x35 +#define HID_USAGE_GENERIC_SLIDER 0x36 +#define HID_USAGE_GENERIC_DIAL 0x37 +#define HID_USAGE_GENERIC_WHEEL 0x38 +#define HID_USAGE_GENERIC_HATSWITCH 0x39 +#define HID_USAGE_GENERIC_COUNTED_BUFFER 0x3A +#define HID_USAGE_GENERIC_BYTE_COUNT 0x3B +#define HID_USAGE_GENERIC_MOTION_WAKEUP 0x3C +#define HID_USAGE_GENERIC_VX 0x40 +#define HID_USAGE_GENERIC_VY 0x41 +#define HID_USAGE_GENERIC_VZ 0x42 +#define HID_USAGE_GENERIC_VBRX 0x43 +#define HID_USAGE_GENERIC_VBRY 0x44 +#define HID_USAGE_GENERIC_VBRZ 0x45 +#define HID_USAGE_GENERIC_VNO 0x46 +#define HID_USAGE_GENERIC_SYSTEM_CTL 0x80 +#define HID_USAGE_GENERIC_SYSCTL_POWER 0x81 +#define HID_USAGE_GENERIC_SYSCTL_SLEEP 0x82 +#define HID_USAGE_GENERIC_SYSCTL_WAKE 0x83 +#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU 0x84 +#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU 0x85 +#define HID_USAGE_GENERIC_SYSCTL_APP_MENU 0x86 +#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU 0x87 +#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT 0x88 +#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT 0x89 +#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT 0x8A +#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT 0x8B +#define HID_USAGE_GENERIC_SYSCTL_MENU_UP 0x8C +#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN 0x8D +/** @} */ + +/** Simulation Controls Page (0x02) + * @{ + */ +#define HID_USAGE_SIMULATION_RUDDER 0xBA +#define HID_USAGE_SIMULATION_THROTTLE 0xBB +/** @} */ + +/* Virtual Reality Controls Page (0x03) */ +/* ... */ + +/* Sport Controls Page (0x04) */ +/* ... */ + +/* Game Controls Page (0x05) */ +/* ... */ + +/* Generic Device Controls Page (0x06) */ +/* ... */ + +/** Keyboard/Keypad Page (0x07) + * @{ + */ +/** Error "keys" */ +#define HID_USAGE_KEYBOARD_NOEVENT 0x00 +#define HID_USAGE_KEYBOARD_ROLLOVER 0x01 +#define HID_USAGE_KEYBOARD_POSTFAIL 0x02 +#define HID_USAGE_KEYBOARD_UNDEFINED 0x03 + +/** Letters */ +#define HID_USAGE_KEYBOARD_aA 0x04 +#define HID_USAGE_KEYBOARD_zZ 0x1D + +/** Numbers */ +#define HID_USAGE_KEYBOARD_ONE 0x1E +#define HID_USAGE_KEYBOARD_ZERO 0x27 + +#define HID_USAGE_KEYBOARD_RETURN 0x28 +#define HID_USAGE_KEYBOARD_ESCAPE 0x29 +#define HID_USAGE_KEYBOARD_DELETE 0x2A + +/** Funtion keys */ +#define HID_USAGE_KEYBOARD_F1 0x3A +#define HID_USAGE_KEYBOARD_F12 0x45 + +#define HID_USAGE_KEYBOARD_PRINT_SCREEN 0x46 + +/** Modifier Keys */ +#define HID_USAGE_KEYBOARD_LCTRL 0xE0 +#define HID_USAGE_KEYBOARD_LSHFT 0xE1 +#define HID_USAGE_KEYBOARD_LALT 0xE2 +#define HID_USAGE_KEYBOARD_LGUI 0xE3 +#define HID_USAGE_KEYBOARD_RCTRL 0xE4 +#define HID_USAGE_KEYBOARD_RSHFT 0xE5 +#define HID_USAGE_KEYBOARD_RALT 0xE6 +#define HID_USAGE_KEYBOARD_RGUI 0xE7 +#define HID_USAGE_KEYBOARD_SCROLL_LOCK 0x47 +#define HID_USAGE_KEYBOARD_NUM_LOCK 0x53 +#define HID_USAGE_KEYBOARD_CAPS_LOCK 0x39 +/** @} */ + +/* ... */ + +/** LED Page (0x08) + * @{ + */ +#define HID_USAGE_LED_NUM_LOCK 0x01 +#define HID_USAGE_LED_CAPS_LOCK 0x02 +#define HID_USAGE_LED_SCROLL_LOCK 0x03 +#define HID_USAGE_LED_COMPOSE 0x04 +#define HID_USAGE_LED_KANA 0x05 +#define HID_USAGE_LED_POWER 0x06 +#define HID_USAGE_LED_SHIFT 0x07 +#define HID_USAGE_LED_DO_NOT_DISTURB 0x08 +#define HID_USAGE_LED_MUTE 0x09 +#define HID_USAGE_LED_TONE_ENABLE 0x0A +#define HID_USAGE_LED_HIGH_CUT_FILTER 0x0B +#define HID_USAGE_LED_LOW_CUT_FILTER 0x0C +#define HID_USAGE_LED_EQUALIZER_ENABLE 0x0D +#define HID_USAGE_LED_SOUND_FIELD_ON 0x0E +#define HID_USAGE_LED_SURROUND_FIELD_ON 0x0F +#define HID_USAGE_LED_REPEAT 0x10 +#define HID_USAGE_LED_STEREO 0x11 +#define HID_USAGE_LED_SAMPLING_RATE_DETECT 0x12 +#define HID_USAGE_LED_SPINNING 0x13 +#define HID_USAGE_LED_CAV 0x14 +#define HID_USAGE_LED_CLV 0x15 +#define HID_USAGE_LED_RECORDING_FORMAT_DET 0x16 +#define HID_USAGE_LED_OFF_HOOK 0x17 +#define HID_USAGE_LED_RING 0x18 +#define HID_USAGE_LED_MESSAGE_WAITING 0x19 +#define HID_USAGE_LED_DATA_MODE 0x1A +#define HID_USAGE_LED_BATTERY_OPERATION 0x1B +#define HID_USAGE_LED_BATTERY_OK 0x1C +#define HID_USAGE_LED_BATTERY_LOW 0x1D +#define HID_USAGE_LED_SPEAKER 0x1E +#define HID_USAGE_LED_HEAD_SET 0x1F +#define HID_USAGE_LED_HOLD 0x20 +#define HID_USAGE_LED_MICROPHONE 0x21 +#define HID_USAGE_LED_COVERAGE 0x22 +#define HID_USAGE_LED_NIGHT_MODE 0x23 +#define HID_USAGE_LED_SEND_CALLS 0x24 +#define HID_USAGE_LED_CALL_PICKUP 0x25 +#define HID_USAGE_LED_CONFERENCE 0x26 +#define HID_USAGE_LED_STAND_BY 0x27 +#define HID_USAGE_LED_CAMERA_ON 0x28 +#define HID_USAGE_LED_CAMERA_OFF 0x29 +#define HID_USAGE_LED_ON_LINE 0x2A +#define HID_USAGE_LED_OFF_LINE 0x2B +#define HID_USAGE_LED_BUSY 0x2C +#define HID_USAGE_LED_READY 0x2D +#define HID_USAGE_LED_PAPER_OUT 0x2E +#define HID_USAGE_LED_PAPER_JAM 0x2F +#define HID_USAGE_LED_REMOTE 0x30 +#define HID_USAGE_LED_FORWARD 0x31 +#define HID_USAGE_LED_REVERSE 0x32 +#define HID_USAGE_LED_STOP 0x33 +#define HID_USAGE_LED_REWIND 0x34 +#define HID_USAGE_LED_FAST_FORWARD 0x35 +#define HID_USAGE_LED_PLAY 0x36 +#define HID_USAGE_LED_PAUSE 0x37 +#define HID_USAGE_LED_RECORD 0x38 +#define HID_USAGE_LED_ERROR 0x39 +#define HID_USAGE_LED_SELECTED_INDICATOR 0x3A +#define HID_USAGE_LED_IN_USE_INDICATOR 0x3B +#define HID_USAGE_LED_MULTI_MODE_INDICATOR 0x3C +#define HID_USAGE_LED_INDICATOR_ON 0x3D +#define HID_USAGE_LED_INDICATOR_FLASH 0x3E +#define HID_USAGE_LED_INDICATOR_SLOW_BLINK 0x3F +#define HID_USAGE_LED_INDICATOR_FAST_BLINK 0x40 +#define HID_USAGE_LED_INDICATOR_OFF 0x41 +#define HID_USAGE_LED_FLASH_ON_TIME 0x42 +#define HID_USAGE_LED_SLOW_BLINK_ON_TIME 0x43 +#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME 0x44 +#define HID_USAGE_LED_FAST_BLINK_ON_TIME 0x45 +#define HID_USAGE_LED_FAST_BLINK_OFF_TIME 0x46 +#define HID_USAGE_LED_INDICATOR_COLOR 0x47 +#define HID_USAGE_LED_RED 0x48 +#define HID_USAGE_LED_GREEN 0x49 +#define HID_USAGE_LED_AMBER 0x4A +#define HID_USAGE_LED_GENERIC_INDICATOR 0x4B +/** @} */ + +/* Button Page (0x09) + */ +/* There is no need to label these usages. */ + +/* Ordinal Page (0x0A) + */ +/* There is no need to label these usages. */ + +/** Telephony Device Page (0x0B) + * @{ + */ +#define HID_USAGE_TELEPHONY_PHONE 0x01 +#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE 0x02 +#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS 0x03 +#define HID_USAGE_TELEPHONY_HANDSET 0x04 +#define HID_USAGE_TELEPHONY_HEADSET 0x05 +#define HID_USAGE_TELEPHONY_KEYPAD 0x06 +#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON 0x07 +/** @} */ +/* ... */ + +/** Consumer Page (0x0C) + * @{ + */ +#define HID_USAGE_CONSUMER_CONTROL 0x01 +#define HID_USAGE_CONSUMER_FAST_FORWARD 0xB3 +#define HID_USAGE_CONSUMER_REWIND 0xB4 +#define HID_USAGE_CONSUMER_PLAY_PAUSE 0xCD +#define HID_USAGE_CONSUMER_VOLUME_INCREMENT 0xE9 +#define HID_USAGE_CONSUMER_VOLUME_DECREMENT 0xEA +/** @} */ +/* ... */ + +/* and others ... */ + + +/** HID Report Item Macros + * @{ + */ +/** Main Items */ +#define HID_Input(x) 0x81,x +#define HID_Output(x) 0x91,x +#define HID_Feature(x) 0xB1,x +#define HID_Collection(x) 0xA1,x +#define HID_EndCollection 0xC0 + +/** Data (Input, Output, Feature) */ +#define HID_Data 0<<0 +#define HID_Constant 1<<0 +#define HID_Array 0<<1 +#define HID_Variable 1<<1 +#define HID_Absolute 0<<2 +#define HID_Relative 1<<2 +#define HID_NoWrap 0<<3 +#define HID_Wrap 1<<3 +#define HID_Linear 0<<4 +#define HID_NonLinear 1<<4 +#define HID_PreferredState 0<<5 +#define HID_NoPreferred 1<<5 +#define HID_NoNullPosition 0<<6 +#define HID_NullState 1<<6 +#define HID_NonVolatile 0<<7 +#define HID_Volatile 1<<7 + +/** Collection Data */ +#define HID_Physical 0x00 +#define HID_Application 0x01 +#define HID_Logical 0x02 +#define HID_Report 0x03 +#define HID_NamedArray 0x04 +#define HID_UsageSwitch 0x05 +#define HID_UsageModifier 0x06 + +/** Global Items */ +#define HID_UsagePage(x) 0x05,x +#define HID_UsagePageVendor(x) 0x06,x,0xFF +#define HID_LogicalMin(x) 0x15,x +#define HID_LogicalMinS(x) 0x16,(x&0xFF),((x>>8)&0xFF) +#define HID_LogicalMinL(x) 0x17,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_LogicalMax(x) 0x25,x +#define HID_LogicalMaxS(x) 0x26,(x&0xFF),((x>>8)&0xFF) +#define HID_LogicalMaxL(x) 0x27,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_PhysicalMin(x) 0x35,x +#define HID_PhysicalMinS(x) 0x36,(x&0xFF),((x>>8)&0xFF) +#define HID_PhysicalMinL(x) 0x37,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_PhysicalMax(x) 0x45,x +#define HID_PhysicalMaxS(x) 0x46,(x&0xFF),((x>>8)&0xFF) +#define HID_PhysicalMaxL(x) 0x47,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_UnitExponent(x) 0x55,x +#define HID_Unit(x) 0x65,x +#define HID_UnitS(x) 0x66,(x&0xFF),((x>>8)&0xFF) +#define HID_UnitL(x) 0x67,(x&0xFF),((x>>8)&0xFF),((x>>16)&0xFF),((x>>24)&0xFF) +#define HID_ReportSize(x) 0x75,x +#define HID_ReportID(x) 0x85,x +#define HID_ReportCount(x) 0x95,x +#define HID_Push 0xA0 +#define HID_Pop 0xB0 + +/** Local Items */ +#define HID_Usage(x) 0x09,x +#define HID_UsageMin(x) 0x19,x +#define HID_UsageMax(x) 0x29,x +/** @} */ + +/** @} */ + +#endif /* __HID_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_hiduser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_hiduser.h new file mode 100644 index 0000000..77a1554 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_hiduser.h @@ -0,0 +1,421 @@ +/*********************************************************************** +* $Id:: mw_usbd_hiduser.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* HID Custom User Module Definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __HIDUSER_H__ +#define __HIDUSER_H__ + +#include "usbd.h" +#include "usbd_hid.h" +#include "usbd_core.h" + +/** \file + * \brief Human Interface Device (HID) API structures and function prototypes. + * + * Definition of functions exported by ROM based HID function driver. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_HID HID Class Function Driver + * \section Sec_HIDModDescription Module Description + * HID Class Function Driver module. This module contains an internal implementation of the USB HID Class. + * User applications can use this class driver instead of implementing the HID class manually + * via the low-level HW and core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB HID Class. + */ + +/** \brief HID report descriptor data structure. + * \ingroup USBD_HID + * + * \details This structure is used as part of HID function driver initialization + * parameter structure \ref USBD_HID_INIT_PARAM. This structure contains + * details of a report type supported by the application. An application + * can support multiple report types as a single HID device. The application + * should define this report type data structure per report it supports and + * the array of report types to USBD_HID_API::init() through \ref USBD_HID_INIT_PARAM + * structure. + * + * \note All descriptor pointers assigned in this structure should be on 4 byte + * aligned address boundary. + * + */ +typedef struct _HID_REPORT_T { + uint16_t len; /**< Size of the report descriptor in bytes. */ + uint8_t idle_time; /**< This value is used by stack to respond to Set_Idle & + GET_Idle requests for the specified report ID. The value + of this field specified the rate at which duplicate reports + are generated for the specified Report ID. For example, a + device with two input reports could specify an idle rate of + 20 milliseconds for report ID 1 and 500 milliseconds for + report ID 2. + */ + uint8_t __pad; /**< Padding space. */ + uint8_t* desc; /**< Report descriptor. */ +} USB_HID_REPORT_T; + +/** \brief USB descriptors data structure. + * \ingroup USBD_HID + * + * \details This module exposes functions which interact directly with USB device stack's core layer. + * The application layer uses this component when it has to implement custom class function driver or + * standard class function driver which is not part of the current USB device stack. + * The functions exposed by this interface are to register class specific EP0 handlers and corresponding + * utility functions to manipulate EP0 state machine of the stack. This interface also exposes + * function to register custom endpoint interrupt handler. + * + */ +typedef struct USBD_HID_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_HID_API::GetMemSize() routine.*/ + /* HID paramas */ + uint8_t max_reports; /**< Number of HID reports supported by this instance + of HID class driver. + */ + uint8_t pad[3]; + uint8_t* intf_desc; /**< Pointer to the HID interface descriptor within the + descriptor array (\em high_speed_desc) passed to Init() + through \ref USB_CORE_DESCS_T structure. + */ + USB_HID_REPORT_T* report_data; /**< Pointer to an array of HID report descriptor + data structure (\ref USB_HID_REPORT_T). The number + of elements in the array should be same a \em max_reports + value. The stack uses this array to respond to + requests received for various HID report descriptor + information. \note This array should be of global scope. + */ + + /* user defined functions */ + /* required functions */ + /** + * HID get report callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a HID_REQUEST_GET_REPORT request. The setup packet data (\em pSetup) + * is passed to the callback so that application can extract the report ID, report + * type and other information need to generate the report. \note HID reports are sent + * via interrupt IN endpoint also. This function is called only when report request + * is received on control endpoint. Application should implement \em HID_EpIn_Hdlr to + * send reports to host via interrupt IN endpoint. + * + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing report data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_GetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + + /** + * HID set report callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a HID_REQUEST_SET_REPORT request. The setup packet data (\em pSetup) + * is passed to the callback so that application can extract the report ID, report + * type and other information need to modify the report. An application might choose + * to ignore input Set_Report requests as meaningless. Alternatively these reports + * could be used to reset the origin of a control (that is, current position should + * report zero). + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in, out] pBuffer Pointer to a pointer of data buffer containing report data. + * Pointer-to-pointer is used to implement zero-copy buffers. + * See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Amount of data copied to destination buffer. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_SetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + + /* optional functions */ + + /** + * Optional callback function to handle HID_GetPhysDesc request. + * + * The application software could provide this callback HID_GetPhysDesc handler to + * handle get physical descriptor requests sent by the host. When host requests + * Physical Descriptor set 0, application should return a special descriptor + * identifying the number of descriptor sets and their sizes. A Get_Descriptor + * request with the Physical Index equal to 1 should return the first Physical + * Descriptor set. A device could possibly have alternate uses for its items. + * These can be enumerated by issuing subsequent Get_Descriptor requests while + * incrementing the Descriptor Index. A device should return the last descriptor + * set to requests with an index greater than the last number defined in the HID + * descriptor. + * \note Applications which don't have physical descriptor should set this data member + * to zero before calling the USBD_HID_API::Init(). + * \n + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in] pBuf Pointer to a pointer of data buffer containing physical descriptor + * data. If the physical descriptor is in USB accessible memory area + * application could just update the pointer or else it should copy + * the descriptor to the address pointed by this pointer. + * \param[in] length Amount of data copied to destination buffer or descriptor length. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_GetPhysDesc)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + + /** + * Optional callback function to handle HID_REQUEST_SET_IDLE request. + * + * The application software could provide this callback to handle HID_REQUEST_SET_IDLE + * requests sent by the host. This callback is provided to applications to adjust + * timers associated with various reports, which are sent to host over interrupt + * endpoint. The setup packet data (\em pSetup) is passed to the callback so that + * application can extract the report ID, report type and other information need + * to modify the report's idle time. + * \note Applications which don't send reports on Interrupt endpoint or don't + * have idle time between reports should set this data member to zero before + * calling the USBD_HID_API::Init(). + * \n + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in] idleTime Idle time to be set for the specified report. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_SetIdle)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t idleTime); + + /** + * Optional callback function to handle HID_REQUEST_SET_PROTOCOL request. + * + * The application software could provide this callback to handle HID_REQUEST_SET_PROTOCOL + * requests sent by the host. This callback is provided to applications to adjust + * modes of their code between boot mode and report mode. + * \note Applications which don't support protocol modes should set this data member + * to zero before calling the USBD_HID_API::Init(). + * \n + * + * \param[in] hHid Handle to HID function driver. + * \param[in] pSetup Pointer to setup packet received from host. + * \param[in] protocol Protocol mode. + * 0 = Boot Protocol + * 1 = Report Protocol + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_SetProtocol)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t protocol); + + /** + * Optional Interrupt IN endpoint event handler. + * + * The application software could provide Interrupt IN endpoint event handler. + * Application which send reports to host on interrupt endpoint should provide + * an endpoint event handler through this data member. This data member is + * ignored if the interface descriptor \em intf_desc doesn't have any IN interrupt + * endpoint descriptor associated. + * \n + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Handle to HID function driver. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_EpIn_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + /** + * Optional Interrupt OUT endpoint event handler. + * + * The application software could provide Interrupt OUT endpoint event handler. + * Application which receives reports from host on interrupt endpoint should provide + * an endpoint event handler through this data member. This data member is + * ignored if the interface descriptor \em intf_desc doesn't have any OUT interrupt + * endpoint descriptor associated. + * \n + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Handle to HID function driver. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should return \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_EpOut_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + /* user override-able function */ + /** + * Optional user override-able function to replace the default HID_GetReportDesc handler. + * + * The application software could override the default HID_GetReportDesc handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_HID_API::Init() and also provide report data array + * \em report_data field. + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_GetReportDesc)(USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + /** + * Optional user override-able function to replace the default HID class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_HID_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*HID_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + +} USBD_HID_INIT_PARAM_T; + +/** \brief HID class API functions structure. + * \ingroup USBD_HID + * + * This structure contains pointers to all the function exposed by HID function driver module. + * + */ +typedef struct USBD_HID_API +{ + /** \fn uint32_t GetMemSize(USBD_HID_INIT_PARAM_T* param) + * Function to determine the memory required by the HID function driver module. + * + * This function is called by application layer before calling pUsbApi->hid->Init(), to allocate memory used + * by HID function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing HID function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_HID_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param) + * Function to initialize HID function driver module. + * + * This function is called by application layer to initialize HID function driver + * module. On successful initialization the function returns a handle to HID + * function driver module in passed param structure. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing HID function driver module + * initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte + * aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either HID_GetReport() or HID_SetReport() + * callback are not defined. + * \retval ERR_USBD_BAD_DESC HID_HID_DESCRIPTOR_TYPE is not defined + * immediately after interface descriptor. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param); + +} USBD_HID_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _HID_CTRL_T { + /* pointer to controller */ + USB_CORE_CTRL_T* pUsbCtrl; + /* descriptor pointers */ + uint8_t* hid_desc; + USB_HID_REPORT_T* report_data; + + uint8_t protocol; + uint8_t if_num; /* interface number */ + uint8_t epin_adr; /* IN interrupt endpoint */ + uint8_t epout_adr; /* OUT interrupt endpoint */ + + /* user defined functions */ + ErrorCode_t (*HID_GetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* length); + ErrorCode_t (*HID_SetReport)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length); + ErrorCode_t (*HID_GetPhysDesc)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + ErrorCode_t (*HID_SetIdle)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t idleTime); + ErrorCode_t (*HID_SetProtocol)( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t protocol); + + /* virtual overridable functions */ + ErrorCode_t (*HID_GetReportDesc)(USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuf, uint16_t* length); + +}USB_HID_CTRL_T; + +/** @cond DIRECT_API */ +extern uint32_t mwHID_GetMemSize(USBD_HID_INIT_PARAM_T* param); +extern ErrorCode_t mwHID_init(USBD_HANDLE_T hUsb, USBD_HID_INIT_PARAM_T* param); +/** @endcond */ + +/** @endcond */ + +#endif /* __HIDUSER_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_hw.h b/source/lpc_chip_11u6x/inc/usbd/usbd_hw.h new file mode 100644 index 0000000..e34485c --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_hw.h @@ -0,0 +1,457 @@ +/*********************************************************************** +* $Id:: mw_usbd_hw.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* USB Hardware Function prototypes. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __USBHW_H__ +#define __USBHW_H__ + +#include "error.h" +#include "usbd.h" +#include "usbd_core.h" + +/** \file + * \brief USB Hardware Function prototypes. + * + * Definition of functions exported by ROM based Device Controller Driver (DCD). + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_HW USB Device Controller Driver + * \section Sec_HWModDescription Module Description + * The Device Controller Driver Layer implements the routines to deal directly with the hardware. + */ + +/** \ingroup USBD_HW +* USB Endpoint/class handler Callback Events. +* +*/ +enum USBD_EVENT_T { + USB_EVT_SETUP =1, /**< 1 Setup Packet received */ + USB_EVT_OUT, /**< 2 OUT Packet received */ + USB_EVT_IN, /**< 3 IN Packet sent */ + USB_EVT_OUT_NAK, /**< 4 OUT Packet - Not Acknowledged */ + USB_EVT_IN_NAK, /**< 5 IN Packet - Not Acknowledged */ + USB_EVT_OUT_STALL, /**< 6 OUT Packet - Stalled */ + USB_EVT_IN_STALL, /**< 7 IN Packet - Stalled */ + USB_EVT_OUT_DMA_EOT, /**< 8 DMA OUT EP - End of Transfer */ + USB_EVT_IN_DMA_EOT, /**< 9 DMA IN EP - End of Transfer */ + USB_EVT_OUT_DMA_NDR, /**< 10 DMA OUT EP - New Descriptor Request */ + USB_EVT_IN_DMA_NDR, /**< 11 DMA IN EP - New Descriptor Request */ + USB_EVT_OUT_DMA_ERR, /**< 12 DMA OUT EP - Error */ + USB_EVT_IN_DMA_ERR, /**< 13 DMA IN EP - Error */ + USB_EVT_RESET, /**< 14 Reset event recieved */ + USB_EVT_SOF, /**< 15 Start of Frame event */ + USB_EVT_DEV_STATE, /**< 16 Device status events */ + USB_EVT_DEV_ERROR /**< 17 Device error events */ +}; + +/** + * \brief Hardware API functions structure. + * \ingroup USBD_HW + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_HW_API +{ + /** \fn uint32_t GetMemSize(USBD_API_INIT_PARAM_T* param) + * Function to determine the memory required by the USB device stack's DCD and core layers. + * + * This function is called by application layer before calling pUsbApi->hw->Init(), to allocate memory used + * by DCD and core layers. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing USB device stack initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_API_INIT_PARAM_T* param); + + /** \fn ErrorCode_t Init(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param) + * Function to initialize USB device stack's DCD and core layers. + * + * This function is called by application layer to initialize USB hardware and core layers. + * On successful initialization the function returns a handle to USB device stack which should + * be passed to the rest of the functions. + * + * \param[in,out] phUsb Pointer to the USB device stack handle of type USBD_HANDLE_T. + * \param[in] pDesc Structure containing pointers to various descriptor arrays needed by the stack. + * These descriptors are reported to USB host as part of enumerations process. + * \param[in] param Structure containing USB device stack initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK(0) On success + * \retval ERR_USBD_BAD_MEM_BUF(0x0004000b) When insufficient memory buffer is passed or memory + * is not aligned on 2048 boundary. + */ + ErrorCode_t (*Init)(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param); + + /** \fn void Connect(USBD_HANDLE_T hUsb, uint32_t con) + * Function to make USB device visible/invisible on the USB bus. + * + * This function is called after the USB initialization. This function uses the soft connect + * feature to make the device visible on the USB bus. This function is called only after the + * application is ready to handle the USB data. The enumeration process is started by the + * host after the device detection. The driver handles the enumeration process according to + * the USB descriptors passed in the USB initialization function. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] con States whether to connect (1) or to disconnect (0). + * \return Nothing. + */ + void (*Connect)(USBD_HANDLE_T hUsb, uint32_t con); + + /** \fn void ISR(USBD_HANDLE_T hUsb) + * Function to USB device controller interrupt events. + * + * When the user application is active the interrupt handlers are mapped in the user flash + * space. The user application must provide an interrupt handler for the USB interrupt and + * call this function in the interrupt handler routine. The driver interrupt handler takes + * appropriate action according to the data received on the USB bus. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*ISR)(USBD_HANDLE_T hUsb); + + /** \fn void Reset(USBD_HANDLE_T hUsb) + * Function to Reset USB device stack and hardware controller. + * + * Reset USB device stack and hardware controller. Disables all endpoints except EP0. + * Clears all pending interrupts and resets endpoint transfer queues. + * This function is called internally by pUsbApi->hw->init() and from reset event. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*Reset)(USBD_HANDLE_T hUsb); + + /** \fn void ForceFullSpeed(USBD_HANDLE_T hUsb, uint32_t cfg) + * Function to force high speed USB device to operate in full speed mode. + * + * This function is useful for testing the behavior of current device when connected + * to a full speed only hosts. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg When 1 - set force full-speed or + * 0 - clear force full-speed. + * \return Nothing. + */ + void (*ForceFullSpeed )(USBD_HANDLE_T hUsb, uint32_t cfg); + + /** \fn void WakeUpCfg(USBD_HANDLE_T hUsb, uint32_t cfg) + * Function to configure USB device controller to wake-up host on remote events. + * + * This function is called by application layer to configure the USB device controller + * to wakeup on remote events. It is recommended to call this function from users's + * USB_WakeUpCfg() callback routine registered with stack. + * \note User's USB_WakeUpCfg() is registered with stack by setting the USB_WakeUpCfg member + * of USBD_API_INIT_PARAM_T structure before calling pUsbApi->hw->Init() routine. + * Certain USB device controllers needed to keep some clocks always on to generate + * resume signaling through pUsbApi->hw->WakeUp(). This hook is provided to support + * such controllers. In most controllers cases this is an empty routine. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg When 1 - Configure controller to wake on remote events or + * 0 - Configure controller not to wake on remote events. + * \return Nothing. + */ + void (*WakeUpCfg)(USBD_HANDLE_T hUsb, uint32_t cfg); + + /** \fn void SetAddress(USBD_HANDLE_T hUsb, uint32_t adr) + * Function to set USB address assigned by host in device controller hardware. + * + * This function is called automatically when USB_REQUEST_SET_ADDRESS request is received + * by the stack from USB host. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] adr USB bus Address to which the device controller should respond. Usually + * assigned by the USB host. + * \return Nothing. + */ + void (*SetAddress)(USBD_HANDLE_T hUsb, uint32_t adr); + + /** \fn void Configure(USBD_HANDLE_T hUsb, uint32_t cfg) + * Function to configure device controller hardware with selected configuration. + * + * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received + * by the stack from USB host. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg Configuration index. + * \return Nothing. + */ + void (*Configure)(USBD_HANDLE_T hUsb, uint32_t cfg); + + /** \fn void ConfigEP(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD) + * Function to configure USB Endpoint according to descriptor. + * + * This function is called automatically when USB_REQUEST_SET_CONFIGURATION request is received + * by the stack from USB host. All the endpoints associated with the selected configuration + * are configured. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] pEPD Endpoint descriptor structure defined in USB 2.0 specification. + * \return Nothing. + */ + void (*ConfigEP)(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD); + + /** \fn void DirCtrlEP(USBD_HANDLE_T hUsb, uint32_t dir) + * Function to set direction for USB control endpoint EP0. + * + * This function is called automatically by the stack on need basis. + * This interface is provided to users to invoke this function in other scenarios which are not + * handle by current stack. In most user applications this function is not called directly. + * Also this function can be used by users who are selectively modifying the USB device stack's + * standard handlers through callback interface exposed by the stack. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] cfg When 1 - Set EP0 in IN transfer mode + * 0 - Set EP0 in OUT transfer mode + * \return Nothing. + */ + void (*DirCtrlEP)(USBD_HANDLE_T hUsb, uint32_t dir); + + /** \fn void EnableEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to enable selected USB endpoint. + * + * This function enables interrupts on selected endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*EnableEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void DisableEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to disable selected USB endpoint. + * + * This function disables interrupts on selected endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*DisableEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void ResetEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to reset selected USB endpoint. + * + * This function flushes the endpoint buffers and resets data toggle logic. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*ResetEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void SetStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to STALL selected USB endpoint. + * + * Generates STALL signaling for requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*SetStallEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn void ClrStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum) + * Function to clear STALL state for the requested endpoint. + * + * This function clears STALL state for the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \return Nothing. + */ + void (*ClrStallEP)(USBD_HANDLE_T hUsb, uint32_t EPNum); + + /** \fn ErrorCode_t SetTestMode(USBD_HANDLE_T hUsb, uint8_t mode) + * Function to set high speed USB device controller in requested test mode. + * + * USB-IF requires the high speed device to be put in various test modes + * for electrical testing. This USB device stack calls this function whenever + * it receives USB_REQUEST_CLEAR_FEATURE request for USB_FEATURE_TEST_MODE. + * Users can put the device in test mode by directly calling this function. + * Returns ERR_USBD_INVALID_REQ when device controller is full-speed only. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] mode Test mode defined in USB 2.0 electrical testing specification. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK(0) - On success + * \retval ERR_USBD_INVALID_REQ(0x00040001) - Invalid test mode or + * Device controller is full-speed only. + */ + ErrorCode_t (*SetTestMode)(USBD_HANDLE_T hUsb, uint8_t mode); + + /** \fn uint32_t ReadEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData) + * Function to read data received on the requested endpoint. + * + * This function is called by USB stack and the application layer to read the data + * received on the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \param[in,out] pData Pointer to the data buffer where data is to be copied. + * \return Returns the number of bytes copied to the buffer. + */ + uint32_t (*ReadEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData); + + /** \fn uint32_t ReadReqEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len) + * Function to queue read request on the specified endpoint. + * + * This function is called by USB stack and the application layer to queue a read request + * on the specified endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \param[in,out] pData Pointer to the data buffer where data is to be copied. This buffer + * address should be accessible by USB DMA master. + * \param[in] len Length of the buffer passed. + * \return Returns the length of the requested buffer. + */ + uint32_t (*ReadReqEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len); + + /** \fn uint32_t ReadSetupPkt(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t *pData) + * Function to read setup packet data received on the requested endpoint. + * + * This function is called by USB stack and the application layer to read setup packet data + * received on the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP0_IN is represented by 0x80 number. + * \param[in,out] pData Pointer to the data buffer where data is to be copied. + * \return Returns the number of bytes copied to the buffer. + */ + uint32_t (*ReadSetupPkt)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t *pData); + + /** \fn uint32_t WriteEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt) + * Function to write data to be sent on the requested endpoint. + * + * This function is called by USB stack and the application layer to send data + * on the requested endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number as per USB specification. + * ie. An EP1_IN is represented by 0x81 number. + * \param[in] pData Pointer to the data buffer from where data is to be copied. + * \param[in] cnt Number of bytes to write. + * \return Returns the number of bytes written. + */ + uint32_t (*WriteEP)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt); + + /** \fn void WakeUp(USBD_HANDLE_T hUsb) + * Function to generate resume signaling on bus for remote host wakeup. + * + * This function is called by application layer to remotely wakeup host controller + * when system is in suspend state. Application should indicate this remote wakeup + * capability by setting USB_CONFIG_REMOTE_WAKEUP in bmAttributes of Configuration + * Descriptor. Also this routine will generate resume signalling only if host + * enables USB_FEATURE_REMOTE_WAKEUP by sending SET_FEATURE request before suspending + * the bus. + * + * \param[in] hUsb Handle to the USB device stack. + * \return Nothing. + */ + void (*WakeUp)(USBD_HANDLE_T hUsb); + + /** \fn void EnableEvent(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable) + * Function to enable/disable selected USB event. + * + * This function enables interrupts on selected endpoint. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] EPNum Endpoint number corresponding to the event. + * ie. An EP1_IN is represented by 0x81 number. For device events + * set this param to 0x0. + * \param[in] event_type Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \param[in] enable 1 - enable event, 0 - disable event. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK(0) - On success + * \retval ERR_USBD_INVALID_REQ(0x00040001) - Invalid event type. + */ + ErrorCode_t (*EnableEvent)(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable); + +} USBD_HW_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes used by stack internally + *-----------------------------------------------------------------------------*/ +/** @cond DIRECT_API */ + +/* Driver functions */ +uint32_t hwUSB_GetMemSize(USBD_API_INIT_PARAM_T* param); +ErrorCode_t hwUSB_Init(USBD_HANDLE_T* phUsb, USB_CORE_DESCS_T* pDesc, USBD_API_INIT_PARAM_T* param); +void hwUSB_Connect(USBD_HANDLE_T hUsb, uint32_t con); +void hwUSB_ISR(USBD_HANDLE_T hUsb); + +/* USB Hardware Functions */ +extern void hwUSB_Reset(USBD_HANDLE_T hUsb); +extern void hwUSB_ForceFullSpeed (USBD_HANDLE_T hUsb, uint32_t con); +extern void hwUSB_WakeUpCfg(USBD_HANDLE_T hUsb, uint32_t cfg); +extern void hwUSB_SetAddress(USBD_HANDLE_T hUsb, uint32_t adr); +extern void hwUSB_Configure(USBD_HANDLE_T hUsb, uint32_t cfg); +extern void hwUSB_ConfigEP(USBD_HANDLE_T hUsb, USB_ENDPOINT_DESCRIPTOR *pEPD); +extern void hwUSB_DirCtrlEP(USBD_HANDLE_T hUsb, uint32_t dir); +extern void hwUSB_EnableEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_DisableEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_ResetEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_SetStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern void hwUSB_ClrStallEP(USBD_HANDLE_T hUsb, uint32_t EPNum); +extern ErrorCode_t hwUSB_SetTestMode(USBD_HANDLE_T hUsb, uint8_t mode); /* for FS only devices return ERR_USBD_INVALID_REQ */ +extern uint32_t hwUSB_ReadEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData); +extern uint32_t hwUSB_ReadReqEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t len); +extern uint32_t hwUSB_ReadSetupPkt(USBD_HANDLE_T hUsb, uint32_t, uint32_t *); +extern uint32_t hwUSB_WriteEP(USBD_HANDLE_T hUsb, uint32_t EPNum, uint8_t *pData, uint32_t cnt); + +/* generate resume signaling on the bus */ +extern void hwUSB_WakeUp(USBD_HANDLE_T hUsb); +extern ErrorCode_t hwUSB_EnableEvent(USBD_HANDLE_T hUsb, uint32_t EPNum, uint32_t event_type, uint32_t enable); +/* TODO implement following routines +- function to program TD and queue them to ep Qh +*/ + +/** @endcond */ + + +#endif /* __USBHW_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_msc.h b/source/lpc_chip_11u6x/inc/usbd/usbd_msc.h new file mode 100644 index 0000000..a62938f --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_msc.h @@ -0,0 +1,119 @@ +/*********************************************************************** +* $Id:: mw_usbd_msc.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Mass Storage Class definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __MSC_H__ +#define __MSC_H__ + +#include "usbd.h" + +/** \file + * \brief Mass Storage class (MSC) descriptors. + * + * Definition of MSC class descriptors and their bit defines. + * + */ + +/* MSC Subclass Codes */ +#define MSC_SUBCLASS_RBC 0x01 +#define MSC_SUBCLASS_SFF8020I_MMC2 0x02 +#define MSC_SUBCLASS_QIC157 0x03 +#define MSC_SUBCLASS_UFI 0x04 +#define MSC_SUBCLASS_SFF8070I 0x05 +#define MSC_SUBCLASS_SCSI 0x06 + +/* MSC Protocol Codes */ +#define MSC_PROTOCOL_CBI_INT 0x00 +#define MSC_PROTOCOL_CBI_NOINT 0x01 +#define MSC_PROTOCOL_BULK_ONLY 0x50 + + +/* MSC Request Codes */ +#define MSC_REQUEST_RESET 0xFF +#define MSC_REQUEST_GET_MAX_LUN 0xFE + + +/* MSC Bulk-only Stage */ +#define MSC_BS_CBW 0 /* Command Block Wrapper */ +#define MSC_BS_DATA_OUT 1 /* Data Out Phase */ +#define MSC_BS_DATA_IN 2 /* Data In Phase */ +#define MSC_BS_DATA_IN_LAST 3 /* Data In Last Phase */ +#define MSC_BS_DATA_IN_LAST_STALL 4 /* Data In Last Phase with Stall */ +#define MSC_BS_CSW 5 /* Command Status Wrapper */ +#define MSC_BS_ERROR 6 /* Error */ + + +/* Bulk-only Command Block Wrapper */ +PRE_PACK struct POST_PACK _MSC_CBW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; +} ; +typedef struct _MSC_CBW MSC_CBW; + +/* Bulk-only Command Status Wrapper */ +PRE_PACK struct POST_PACK _MSC_CSW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; +} ; +typedef struct _MSC_CSW MSC_CSW; + +#define MSC_CBW_Signature 0x43425355 +#define MSC_CSW_Signature 0x53425355 + + +/* CSW Status Definitions */ +#define CSW_CMD_PASSED 0x00 +#define CSW_CMD_FAILED 0x01 +#define CSW_PHASE_ERROR 0x02 + + +/* SCSI Commands */ +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SELECT6 0x15 +#define SCSI_MODE_SENSE6 0x1A +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_MEDIA_REMOVAL 0x1E +#define SCSI_READ_FORMAT_CAPACITIES 0x23 +#define SCSI_READ_CAPACITY 0x25 +#define SCSI_READ10 0x28 +#define SCSI_WRITE10 0x2A +#define SCSI_VERIFY10 0x2F +#define SCSI_READ12 0xA8 +#define SCSI_WRITE12 0xAA +#define SCSI_MODE_SELECT10 0x55 +#define SCSI_MODE_SENSE10 0x5A + + +#endif /* __MSC_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_mscuser.h b/source/lpc_chip_11u6x/inc/usbd/usbd_mscuser.h new file mode 100644 index 0000000..eddc1b9 --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_mscuser.h @@ -0,0 +1,270 @@ +/*********************************************************************** +* $Id:: mw_usbd_mscuser.h 577 2012-11-20 01:42:04Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* Mass Storage Class Custom User Module definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MSCUSER_H__ +#define __MSCUSER_H__ + +#include "error.h" +#include "usbd.h" +#include "usbd_msc.h" +#include "usbd_core.h" +#include "app_usbd_cfg.h" + +/** \file + * \brief Mass Storage Class (MSC) API structures and function prototypes. + * + * Definition of functions exported by ROM based MSC function driver. + * + */ + +/** \ingroup Group_USBD + * @defgroup USBD_MSC Mass Storage Class (MSC) Function Driver + * \section Sec_MSCModDescription Module Description + * MSC Class Function Driver module. This module contains an internal implementation of the USB MSC Class. + * User applications can use this class driver instead of implementing the MSC class manually + * via the low-level USBD_HW and USBD_Core APIs. + * + * This module is designed to simplify the user code by exposing only the required interface needed to interface with + * Devices using the USB MSC Class. + */ + +/** \brief Mass Storage class function driver initialization parameter data structure. + * \ingroup USBD_MSC + * + * \details This data structure is used to pass initialization parameters to the + * Mass Storage class function driver's init function. + * + */ +typedef struct USBD_MSC_INIT_PARAM +{ + /* memory allocation params */ + uint32_t mem_base; /**< Base memory location from where the stack can allocate + data and buffers. \note The memory address set in this field + should be accessible by USB DMA controller. Also this value + should be aligned on 4 byte boundary. + */ + uint32_t mem_size; /**< The size of memory buffer which stack can use. + \note The \em mem_size should be greater than the size + returned by USBD_MSC_API::GetMemSize() routine.*/ + /* mass storage params */ + uint8_t* InquiryStr; /**< Pointer to the 28 character string. This string is + sent in response to the SCSI Inquiry command. \note The data + pointed by the pointer should be of global scope. + */ + uint32_t BlockCount; /**< Number of blocks present in the mass storage device */ + uint32_t BlockSize; /**< Block size in number of bytes */ + uint32_t MemorySize; /**< Memory size in number of bytes */ + /** Pointer to the interface descriptor within the descriptor + * array (\em high_speed_desc) passed to Init() through \ref USB_CORE_DESCS_T + * structure. The stack assumes both HS and FS use same BULK endpoints. + */ + + uint8_t* intf_desc; + /* user defined functions */ + + /** + * MSC Write callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a write command. + * + * \param[in] offset Destination start address. + * \param[in, out] src Pointer to a pointer to the source of data. Pointer-to-pointer + * is used to implement zero-copy buffers. See \ref USBD_ZeroCopy + * for more details on zero-copy concept. + * \param[in] length Number of bytes to be written. + * \return Nothing. + * + */ + void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset); + /** + * MSC Read callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a read command. + * + * \param[in] offset Source start address. + * \param[in, out] dst Pointer to a pointer to the source of data. The MSC function drivers + * implemented in stack are written with zero-copy model. Meaning the stack doesn't make an + * extra copy of buffer before writing/reading data from USB hardware FIFO. Hence the + * parameter is pointer to a pointer containing address buffer (uint8_t** dst). + * So that the user application can update the buffer pointer instead of copying data to + * address pointed by the parameter. /note The updated buffer address should be accessible + * by USB DMA master. If user doesn't want to use zero-copy model, then the user should copy + * data to the address pointed by the passed buffer pointer parameter and shouldn't change + * the address value. See \ref USBD_ZeroCopy for more details on zero-copy concept. + * \param[in] length Number of bytes to be read. + * \return Nothing. + * + */ + void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset); + /** + * MSC Verify callback function. + * + * This function is provided by the application software. This function gets called + * when host sends a verify command. The callback function should compare the buffer + * with the destination memory at the requested offset and + * + * \param[in] offset Destination start address. + * \param[in] buf Buffer containing the data sent by the host. + * \param[in] length Number of bytes to verify. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK If data in the buffer matches the data at destination + * \retval ERR_FAILED At least one byte is different. + * + */ + ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t buf[], uint32_t length, uint32_t high_offset); + /** + * Optional callback function to optimize MSC_Write buffer transfer. + * + * This function is provided by the application software. This function gets called + * when host sends SCSI_WRITE10/SCSI_WRITE12 command. The callback function should + * update the \em buff_adr pointer so that the stack transfers the data directly + * to the target buffer. /note The updated buffer address should be accessible + * by USB DMA master. If user doesn't want to use zero-copy model, then the user + * should not update the buffer pointer. See \ref USBD_ZeroCopy for more details + * on zero-copy concept. + * + * \param[in] offset Destination start address. + * \param[in,out] buf Buffer containing the data sent by the host. + * \param[in] length Number of bytes to write. + * \return Nothing. + * + */ + void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset); + + /** + * Optional user override-able function to replace the default MSC class handler. + * + * The application software could override the default EP0 class handler with their + * own by providing the handler function address as this data member of the parameter + * structure. Application which like the default handler should set this data member + * to zero before calling the USBD_MSC_API::Init(). + * \n + * \note + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in] data Pointer to the data which will be passed when callback function is called by the stack. + * \param[in] event Type of endpoint event. See \ref USBD_EVENT_T for more details. + * \return The call back should returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success. + * \retval ERR_USBD_UNHANDLED Event is not handled hence pass the event to next in line. + * \retval ERR_USBD_xxx For other error conditions. + * + */ + ErrorCode_t (*MSC_Ep0_Hdlr) (USBD_HANDLE_T hUsb, void* data, uint32_t event); + + uint64_t MemorySize64; + +} USBD_MSC_INIT_PARAM_T; + +/** \brief MSC class API functions structure. + * \ingroup USBD_MSC + * + * This module exposes functions which interact directly with USB device controller hardware. + * + */ +typedef struct USBD_MSC_API +{ + /** \fn uint32_t GetMemSize(USBD_MSC_INIT_PARAM_T* param) + * Function to determine the memory required by the MSC function driver module. + * + * This function is called by application layer before calling pUsbApi->msc->Init(), to allocate memory used + * by MSC function driver module. The application should allocate the memory which is accessible by USB + * controller/DMA controller. + * \note Some memory areas are not accessible by all bus masters. + * + * \param[in] param Structure containing MSC function driver module initialization parameters. + * \return Returns the required memory size in bytes. + */ + uint32_t (*GetMemSize)(USBD_MSC_INIT_PARAM_T* param); + + /** \fn ErrorCode_t init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param) + * Function to initialize MSC function driver module. + * + * This function is called by application layer to initialize MSC function driver module. + * + * \param[in] hUsb Handle to the USB device stack. + * \param[in, out] param Structure containing MSC function driver module initialization parameters. + * \return Returns \ref ErrorCode_t type to indicate success or error condition. + * \retval LPC_OK On success + * \retval ERR_USBD_BAD_MEM_BUF Memory buffer passed is not 4-byte + * aligned or smaller than required. + * \retval ERR_API_INVALID_PARAM2 Either MSC_Write() or MSC_Read() or + * MSC_Verify() callbacks are not defined. + * \retval ERR_USBD_BAD_INTF_DESC Wrong interface descriptor is passed. + * \retval ERR_USBD_BAD_EP_DESC Wrong endpoint descriptor is passed. + */ + ErrorCode_t (*init)(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param); + +} USBD_MSC_API_T; + +/*----------------------------------------------------------------------------- + * Private functions & structures prototypes + *-----------------------------------------------------------------------------*/ +/** @cond ADVANCED_API */ + +typedef struct _MSC_CTRL_T +{ + /* If it's a USB HS, the max packet is 512, if it's USB FS, + the max packet is 64. Use 512 for both HS and FS. */ + /*ALIGNED(4)*/ uint8_t BulkBuf[USB_HS_MAX_BULK_PACKET]; /* Bulk In/Out Buffer */ + /*ALIGNED(4)*/MSC_CBW CBW; /* Command Block Wrapper */ + /*ALIGNED(4)*/MSC_CSW CSW; /* Command Status Wrapper */ + + USB_CORE_CTRL_T* pUsbCtrl; + + uint64_t Offset; /* R/W Offset */ + uint32_t Length; /* R/W Length */ + uint32_t BulkLen; /* Bulk In/Out Length */ + uint8_t* rx_buf; + + uint8_t BulkStage; /* Bulk Stage */ + uint8_t if_num; /* interface number */ + uint8_t epin_num; /* BULK IN endpoint number */ + uint8_t epout_num; /* BULK OUT endpoint number */ + uint32_t MemOK; /* Memory OK */ + + uint8_t* InquiryStr; + uint32_t BlockCount; + uint32_t BlockSize; + uint64_t MemorySize; + /* user defined functions */ + void (*MSC_Write)( uint32_t offset, uint8_t** src, uint32_t length, uint32_t high_offset); + void (*MSC_Read)( uint32_t offset, uint8_t** dst, uint32_t length, uint32_t high_offset); + ErrorCode_t (*MSC_Verify)( uint32_t offset, uint8_t src[], uint32_t length, uint32_t high_offset); + /* optional call back for MSC_Write optimization */ + void (*MSC_GetWriteBuf)( uint32_t offset, uint8_t** buff_adr, uint32_t length, uint32_t high_offset); + + +}USB_MSC_CTRL_T; + +/** @cond DIRECT_API */ +extern uint32_t mwMSC_GetMemSize(USBD_MSC_INIT_PARAM_T* param); +extern ErrorCode_t mwMSC_init(USBD_HANDLE_T hUsb, USBD_MSC_INIT_PARAM_T* param); +/** @endcond */ + +/** @endcond */ + + +#endif /* __MSCUSER_H__ */ diff --git a/source/lpc_chip_11u6x/inc/usbd/usbd_rom_api.h b/source/lpc_chip_11u6x/inc/usbd/usbd_rom_api.h new file mode 100644 index 0000000..464bbab --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd/usbd_rom_api.h @@ -0,0 +1,92 @@ +/*********************************************************************** +* $Id:: mw_usbd_rom_api.h 331 2012-08-09 18:54:34Z usb10131 $ +* +* Project: USB device ROM Stack +* +* Description: +* ROM API Module definitions. +* +*********************************************************************** +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ +#ifndef __MW_USBD_ROM_API_H +#define __MW_USBD_ROM_API_H +/** \file + * \brief ROM API for USB device stack. + * + * Definition of functions exported by ROM based USB device stack. + * + */ + +#include "error.h" +#include "usbd.h" +#include "usbd_hw.h" +#include "usbd_core.h" +#include "usbd_mscuser.h" +#include "usbd_dfuuser.h" +#include "usbd_hiduser.h" +#include "usbd_cdcuser.h" + +/** \brief Main USBD API functions structure. + * \ingroup Group_USBD + * + * This structure contains pointer to various USB Device stack's sub-module + * function tables. This structure is used as main entry point to access + * various methods (grouped in sub-modules) exposed by ROM based USB device + * stack. + * + */ +typedef struct USBD_API +{ + const USBD_HW_API_T* hw; /**< Pointer to function table which exposes functions + which interact directly with USB device stack's core + layer.*/ + const USBD_CORE_API_T* core; /**< Pointer to function table which exposes functions + which interact directly with USB device controller + hardware.*/ + const USBD_MSC_API_T* msc; /**< Pointer to function table which exposes functions + provided by MSC function driver module. + */ + const USBD_DFU_API_T* dfu; /**< Pointer to function table which exposes functions + provided by DFU function driver module. + */ + const USBD_HID_API_T* hid; /**< Pointer to function table which exposes functions + provided by HID function driver module. + */ + const USBD_CDC_API_T* cdc; /**< Pointer to function table which exposes functions + provided by CDC-ACM function driver module. + */ + const uint32_t* reserved6; /**< Reserved for future function driver module. + */ + const uint32_t version; /**< Version identifier of USB ROM stack. The version is + defined as 0x0CHDMhCC where each nibble represents version + number of the corresponding component. + CC - 7:0 - 8bit core version number + h - 11:8 - 4bit hardware interface version number + M - 15:12 - 4bit MSC class module version number + D - 19:16 - 4bit DFU class module version number + H - 23:20 - 4bit HID class module version number + C - 27:24 - 4bit CDC class module version number + H - 31:28 - 4bit reserved + */ + +} USBD_API_T; + +/* Applications using USBD ROM API should define this instance. The pointer should be assigned a value computed based on chip definitions. */ +extern const USBD_API_T* g_pUsbApi; +#define USBD_API g_pUsbApi + +#endif /*__MW_USBD_ROM_API_H*/ + diff --git a/source/lpc_chip_11u6x/inc/usbd_11u6x.h b/source/lpc_chip_11u6x/inc/usbd_11u6x.h new file mode 100644 index 0000000..8f63f4c --- /dev/null +++ b/source/lpc_chip_11u6x/inc/usbd_11u6x.h @@ -0,0 +1,72 @@ +/* + * @brief LPC11U6x USB device register block + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __USBD_11U6X_H_ +#define __USBD_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup USBD_11U6X CHIP: LPC11u6x USB Device driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief USB device register block structure + */ +typedef struct { /*!< USB Structure */ + __IO uint32_t DEVCMDSTAT; /*!< USB Device Command/Status register */ + __IO uint32_t INFO; /*!< USB Info register */ + __IO uint32_t EPLISTSTART; /*!< USB EP Command/Status List start address */ + __IO uint32_t DATABUFSTART; /*!< USB Data buffer start address */ + __IO uint32_t LPM; /*!< Link Power Management register */ + __IO uint32_t EPSKIP; /*!< USB Endpoint skip */ + __IO uint32_t EPINUSE; /*!< USB Endpoint Buffer in use */ + __IO uint32_t EPBUFCFG; /*!< USB Endpoint Buffer Configuration register */ + __IO uint32_t INTSTAT; /*!< USB interrupt status register */ + __IO uint32_t INTEN; /*!< USB interrupt enable register */ + __IO uint32_t INTSETSTAT; /*!< USB set interrupt status register */ + __IO uint32_t INTROUTING; /*!< USB interrupt routing register */ + __I uint32_t RESERVED0[1]; + __I uint32_t EPTOGGLE; /*!< USB Endpoint toggle register */ +} LPC_USB_T; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/inc/wwdt_11u6x.h b/source/lpc_chip_11u6x/inc/wwdt_11u6x.h new file mode 100644 index 0000000..2aabd5a --- /dev/null +++ b/source/lpc_chip_11u6x/inc/wwdt_11u6x.h @@ -0,0 +1,246 @@ +/* + * @brief LPC11u6x WWDT chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#ifndef __WWDT_11U6X_H_ +#define __WWDT_11U6X_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup WWDT_11U6X CHIP: LPC11u6x Windowed Watchdog driver + * @ingroup CHIP_11U6X_Drivers + * @{ + */ + +/** + * @brief Windowed Watchdog register block structure + */ +typedef struct { /*!< WWDT Structure */ + __IO uint32_t MOD; /*!< Watchdog mode register. This register contains the basic mode and status of the Watchdog Timer. */ + __IO uint32_t TC; /*!< Watchdog timer constant register. This register determines the time-out value. */ + __O uint32_t FEED; /*!< Watchdog feed sequence register. Writing 0xAA followed by 0x55 to this register reloads the Watchdog timer with the value contained in WDTC. */ + __I uint32_t TV; /*!< Watchdog timer value register. This register reads out the current value of the Watchdog timer. */ + __IO uint32_t CLKSEL; /*!< Watchdog clock select register. */ + __IO uint32_t WARNINT; /*!< Watchdog warning interrupt register. This register contains the Watchdog warning interrupt compare value. */ + __IO uint32_t WINDOW; /*!< Watchdog timer window register. This register contains the Watchdog window value. */ +} LPC_WWDT_T; + +/** + * @brief Watchdog Mode register definitions + */ +/** Watchdog Mode Bitmask */ +#define WWDT_WDMOD_BITMASK ((uint32_t) 0x1F) +/** WWDT interrupt enable bit */ +#define WWDT_WDMOD_WDEN ((uint32_t) (1 << 0)) +/** WWDT interrupt enable bit */ +#define WWDT_WDMOD_WDRESET ((uint32_t) (1 << 1)) +/** WWDT time out flag bit */ +#define WWDT_WDMOD_WDTOF ((uint32_t) (1 << 2)) +/** WDT Time Out flag bit */ +#define WWDT_WDMOD_WDINT ((uint32_t) (1 << 3)) +/** WWDT Protect flag bit */ +#define WWDT_WDMOD_WDPROTECT ((uint32_t) (1 << 4)) +/** WWDT lock bit */ +#define WWDT_WDMOD_LOCK ((uint32_t) (1 << 5)) + +/** + * @brief Initialize the Watchdog timer + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + */ +void Chip_WWDT_Init(LPC_WWDT_T *pWWDT); + +/** + * @brief Shutdown the Watchdog timer + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + */ +void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT); + +/** + * @brief Set WDT timeout constant value used for feed + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param timeout : WDT timeout in ticks, between WWDT_TICKS_MIN and WWDT_TICKS_MAX + * @return none + */ +STATIC INLINE void Chip_WWDT_SetTimeOut(LPC_WWDT_T *pWWDT, uint32_t timeout) +{ + pWWDT->TC = timeout; +} + +/** + * @brief Feed watchdog timer + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + * @note If this function isn't called, a watchdog timer warning will occur. + * After the warning, a timeout will occur if a feed has happened. + */ +STATIC INLINE void Chip_WWDT_Feed(LPC_WWDT_T *pWWDT) +{ + pWWDT->FEED = 0xAA; + pWWDT->FEED = 0x55; +} + +/** + * @brief Set WWDT warning interrupt + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param timeout : WDT warning in ticks, between 0 and 1023 + * @return None + * @note This is the number of ticks after the watchdog interrupt that the + * warning interrupt will be generated. + */ +STATIC INLINE void Chip_WWDT_SetWarning(LPC_WWDT_T *pWWDT, uint32_t timeout) +{ + pWWDT->WARNINT = timeout; +} + +/** + * @brief Set WWDT window time + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param timeout : WDT timeout in ticks, between WWDT_TICKS_MIN and WWDT_TICKS_MAX + * @return None + * @note The watchdog timer must be fed between the timeout from the Chip_WWDT_SetTimeOut() + * function and this function, with this function defining the last tick before the + * watchdog window interrupt occurs. + */ +STATIC INLINE void Chip_WWDT_SetWindow(LPC_WWDT_T *pWWDT, uint32_t timeout) +{ + pWWDT->WINDOW = timeout; +} + +/** + * @brief Enable watchdog timer options + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param options : An or'ed set of options of values + * WWDT_WDMOD_WDEN, WWDT_WDMOD_WDRESET, and WWDT_WDMOD_WDPROTECT + * @return None + * @note You can enable more than one option at once (ie, WWDT_WDMOD_WDRESET | + * WWDT_WDMOD_WDPROTECT), but use the WWDT_WDMOD_WDEN after all other options + * are set (or unset) with no other options. If WWDT_WDMOD_LOCK is used, it cannot + * be unset. + */ +STATIC INLINE void Chip_WWDT_SetOption(LPC_WWDT_T *pWWDT, uint32_t options) +{ + pWWDT->MOD |= options; +} + +/** + * @brief Disable/clear watchdog timer options + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param options : An or'ed set of options of values + * WWDT_WDMOD_WDEN, WWDT_WDMOD_WDRESET, and WWDT_WDMOD_WDPROTECT + * @return None + * @note You can disable more than one option at once (ie, WWDT_WDMOD_WDRESET | + * WWDT_WDMOD_WDTOF). + */ +STATIC INLINE void Chip_WWDT_UnsetOption(LPC_WWDT_T *pWWDT, uint32_t options) +{ + pWWDT->MOD &= (~options) & WWDT_WDMOD_BITMASK; +} + +/** + * @brief Enable WWDT activity + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return None + */ +STATIC INLINE void Chip_WWDT_Start(LPC_WWDT_T *pWWDT) +{ + Chip_WWDT_SetOption(pWWDT, WWDT_WDMOD_WDEN); + Chip_WWDT_Feed(pWWDT); +} + +/** + * @brief Read WWDT status flag + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return Watchdog status, an Or'ed value of WWDT_WDMOD_* + */ +STATIC INLINE uint32_t Chip_WWDT_GetStatus(LPC_WWDT_T *pWWDT) +{ + return pWWDT->MOD; +} + +/** + * @brief Clear WWDT interrupt status flags + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param status : Or'ed value of status flag(s) that you want to clear, should be: + * - WWDT_WDMOD_WDTOF: Clear watchdog timeout flag + * - WWDT_WDMOD_WDINT: Clear watchdog warning flag + * @return None + */ +void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status); + +/** + * @brief Get the current value of WDT + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @return current value of WDT + */ +STATIC INLINE uint32_t Chip_WWDT_GetCurrentCount(LPC_WWDT_T *pWWDT) +{ + return pWWDT->TV; +} + +/** + * @brief Watchdog Timer Clock Source Selection register definitions + */ +/** Clock source select bitmask */ +#define WWDT_CLKSEL_BITMASK ((uint32_t) 0x10000001) +/** Lock the clock source selection */ +#define WWDT_CLKSEL_LOCK ((uint32_t) (1 << 31)) + +/** + * @brief Watchdog Clock Source definitions + */ +typedef enum { + WWDT_CLKSRC_IRC = 0, /*!< Internal RC oscillator */ + WWDT_CLKSRC_WATCHDOG_WDOSC = 1, /*!< Watchdog oscillator (WDOSC) */ +} CHIP_WWDT_CLK_SRC_T; + +/** + * @brief Get the current value of WDT + * @param pWWDT : The base of WatchDog Timer peripheral on the chip + * @param wdtClkSrc : Selected watchdog clock source + * @return Nothing + */ +STATIC INLINE void Chip_WWDT_SelClockSource(LPC_WWDT_T *pWWDT, CHIP_WWDT_CLK_SRC_T wdtClkSrc) +{ + pWWDT->CLKSEL = wdtClkSrc & WWDT_CLKSEL_BITMASK; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __WWDT_11U6X_H_ */ diff --git a/source/lpc_chip_11u6x/src/adc_11u6x.c b/source/lpc_chip_11u6x/src/adc_11u6x.c new file mode 100644 index 0000000..9d7b848 --- /dev/null +++ b/source/lpc_chip_11u6x/src/adc_11u6x.c @@ -0,0 +1,209 @@ +/* + * @brief LPC11u6x ADC driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Set ADC interrupt bits (safe) */ +void Chip_ADC_SetIntBits(LPC_ADC_T *pADC, uint32_t intMask) +{ + uint32_t temp; + + /* Read and write values may not be the same, write 0 to + undefined bits */ + temp = pADC->INTEN & 0x07FFFFFF; + + pADC->INTEN = temp | intMask; +} + +/* Clear ADC interrupt bits (safe) */ +void Chip_ADC_ClearIntBits(LPC_ADC_T *pADC, uint32_t intMask) +{ + uint32_t temp; + + /* Read and write values may not be the same, write 0 to + undefined bits */ + temp = pADC->INTEN & 0x07FFFFFF; + + pADC->INTEN = temp & ~intMask; +} + +/* Set ADC threshold selection bits (safe) */ +void Chip_ADC_SetTHRSELBits(LPC_ADC_T *pADC, uint32_t mask) +{ + uint32_t temp; + + /* Read and write values may not be the same, write 0 to + undefined bits */ + temp = pADC->CHAN_THRSEL & 0x00000FFF; + + pADC->CHAN_THRSEL = temp | mask; +} + +/* Clear ADC threshold selection bits (safe) */ +void Chip_ADC_ClearTHRSELBits(LPC_ADC_T *pADC, uint32_t mask) +{ + uint32_t temp; + + /* Read and write values may not be the same, write 0 to + undefined bits */ + temp = pADC->CHAN_THRSEL & 0x00000FFF; + + pADC->CHAN_THRSEL = temp & ~mask; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize the ADC peripheral */ +void Chip_ADC_Init(LPC_ADC_T *pADC, uint32_t flags) +{ + /* Power up ADC and enable ADC base clock */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_ADC_PD); + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_ADC); + + /* Disable ADC interrupts */ + pADC->INTEN = 0; + + /* Set ADC control options */ + pADC->CTRL = flags; +} + +/* Start ADC calibration */ +void Chip_ADC_StartCalibration(LPC_ADC_T *pADC) +{ + uint32_t save_ADC_CTRL; + + save_ADC_CTRL = pADC->CTRL; + Chip_ADC_SetClockRate(LPC_ADC, ADC_CALIBRATE_RATE); + + pADC->CTRL = (pADC->CTRL | ADC_CR_CALMODEBIT) & ~ADC_CR_LPWRMODEBIT; +} + +/** + * @brief Start ADC calibration + * @param pADC : The base of ADC peripheral on the chip + * @return TRUE if calibration is complete, otherwise FALSE. + */ +bool Chip_ADC_IsCalibrationDone(LPC_ADC_T *pADC) +{ + return (bool) ((pADC->CTRL & ADC_CR_CALMODEBIT) == 0); +} + + +/* Shutdown ADC */ +void Chip_ADC_DeInit(LPC_ADC_T *pADC) +{ + pADC->INTEN = 0; + pADC->CTRL = 0; + + /* Stop ADC clock and then power down ADC */ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_ADC); + Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_ADC_PD); +} + +/* Set ADC clock rate */ +void Chip_ADC_SetClockRate(LPC_ADC_T *pADC, uint32_t rate) +{ + Chip_ADC_SetDivider(pADC, ((Chip_Clock_GetSystemClockRate() + (rate>>2)) / rate) -1); +} + +/* Helper function for safely setting ADC sequencer register bits */ +void Chip_ADC_SetSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits) +{ + uint32_t temp; + + /* Read sequencer register and mask off bits 20..25 */ + temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20); + + /* OR in passed bits */ + pADC->SEQ_CTRL[seqIndex] = temp | bits; +} + +/* Helper function for safely clearing ADC sequencer register bits */ +void Chip_ADC_ClearSequencerBits(LPC_ADC_T *pADC, ADC_SEQ_IDX_T seqIndex, uint32_t bits) +{ + uint32_t temp; + + /* Read sequencer register and mask off bits 20..25 */ + temp = pADC->SEQ_CTRL[seqIndex] & ~(0x3F << 20); + + /* OR in passed bits */ + pADC->SEQ_CTRL[seqIndex] = temp & ~bits; +} + +/* Enable interrupts in ADC (sequencers A/B and overrun) */ +void Chip_ADC_EnableInt(LPC_ADC_T *pADC, uint32_t intMask) +{ + Chip_ADC_SetIntBits(pADC, intMask); +} + +/* Disable interrupts in ADC (sequencers A/B and overrun) */ +void Chip_ADC_DisableInt(LPC_ADC_T *pADC, uint32_t intMask) +{ + Chip_ADC_ClearIntBits(pADC, intMask); +} + +/* Enable a threshold event interrupt in ADC */ +void Chip_ADC_SetThresholdInt(LPC_ADC_T *pADC, uint8_t ch, ADC_INTEN_THCMP_T thInt) +{ + int shiftIndex = 3 + (ch * 2); + + /* Clear current bits first */ + Chip_ADC_ClearIntBits(pADC, (ADC_INTEN_CMP_MASK << shiftIndex)); + + /* Set new threshold interrupt type */ + Chip_ADC_SetIntBits(pADC, ((uint32_t) thInt << shiftIndex)); +} + +/* Select threshold 0 values for comparison for selected channels */ +void Chip_ADC_SelectTH0Channels(LPC_ADC_T *pADC, uint32_t channels) +{ + Chip_ADC_ClearTHRSELBits(pADC, channels); +} + +/* Select threshold 1 value for comparison for selected channels */ +void Chip_ADC_SelectTH1Channels(LPC_ADC_T *pADC, uint32_t channels) +{ + Chip_ADC_SetTHRSELBits(pADC, channels); +} diff --git a/source/lpc_chip_11u6x/src/chip_11u6x.c b/source/lpc_chip_11u6x/src/chip_11u6x.c new file mode 100644 index 0000000..5292a06 --- /dev/null +++ b/source/lpc_chip_11u6x/src/chip_11u6x.c @@ -0,0 +1,84 @@ +/* + * @brief LPC11u6x Miscellaneous chip specific functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/* System Clock Frequency (Core Clock) */ +uint32_t SystemCoreClock; + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Update system core clock rate, should be called if the system has + a clock rate change */ +void SystemCoreClockUpdate(void) +{ + /* CPU core speed */ + SystemCoreClock = Chip_Clock_GetSystemClockRate(); +} + +void Chip_USB_Init(void) +{ + /* Set USB PLL input to main oscillator */ + Chip_Clock_SetUSBPLLSource(SYSCTL_USBPLLCLKSRC_MAINOSC); + /* Setup USB PLL (FCLKIN = 12MHz) * 4 = 48MHz + MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2) + FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz + FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */ + Chip_Clock_SetupUSBPLL(3, 1); + + /* Powerup USB PLL */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_USBPLL_PD); + + /* Wait for PLL to lock */ + while (!Chip_Clock_IsUSBPLLLocked()) {} + + /* enable USB main clock */ + Chip_Clock_SetUSBClockSource(SYSCTL_USBCLKSRC_PLLOUT, 1); + /* Enable AHB clock to the USB block and USB RAM. */ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USB); + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_USBRAM); + /* power UP USB Phy */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_USBPAD_PD); +} diff --git a/source/lpc_chip_11u6x/src/clock_11u6x.c b/source/lpc_chip_11u6x/src/clock_11u6x.c new file mode 100644 index 0000000..3e57145 --- /dev/null +++ b/source/lpc_chip_11u6x/src/clock_11u6x.c @@ -0,0 +1,319 @@ +/* + * @brief LPC11U6X System clock control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Inprecise clock rates for the watchdog oscillator */ +STATIC const uint32_t wdtOSCRate[WDTLFO_OSC_4_60 + 1] = { + 0, /* WDT_OSC_ILLEGAL */ + 600000, /* WDT_OSC_0_60 */ + 1050000, /* WDT_OSC_1_05 */ + 1400000, /* WDT_OSC_1_40 */ + 1750000, /* WDT_OSC_1_75 */ + 2100000, /* WDT_OSC_2_10 */ + 2400000, /* WDT_OSC_2_40 */ + 2700000, /* WDT_OSC_2_70 */ + 3000000, /* WDT_OSC_3_00 */ + 3250000, /* WDT_OSC_3_25 */ + 3500000, /* WDT_OSC_3_50 */ + 3750000, /* WDT_OSC_3_75 */ + 4000000, /* WDT_OSC_4_00 */ + 4200000, /* WDT_OSC_4_20 */ + 4400000, /* WDT_OSC_4_40 */ + 4600000 /* WDT_OSC_4_60 */ +}; + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Compute a WDT rate */ +STATIC uint32_t Chip_Clock_GetWDTRate(uint32_t reg) +{ + uint32_t div; + CHIP_WDTLFO_OSC_T clk; + + /* Get WDT oscillator settings */ + clk = (CHIP_WDTLFO_OSC_T) ((reg >> 5) & 0xF); + div = reg & 0x1F; + + /* Compute clock rate and divided by divde value */ + return wdtOSCRate[clk] / ((div + 1) << 1); +} + +/* Compute a PLL frequency */ +STATIC uint32_t Chip_Clock_GetPLLFreq(uint32_t PLLReg, uint32_t inputRate) +{ + uint32_t msel = ((PLLReg & 0x1F) + 1); + + return inputRate * msel; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Get USART 1/2/3/4 UART base rate */ +uint32_t Chip_Clock_GetUSARTNBaseClockRate(void) +{ + uint64_t inclk; + uint32_t div; + + div = (uint32_t) Chip_Clock_GetUSARTNBaseClockDiv(); + if (div == 0) { + /* Divider is 0 so UART clock is disabled */ + inclk = 0; + } + else { + uint32_t mult, divf; + + /* Input clock into FRG block is the divided main system clock */ + inclk = (uint64_t) (Chip_Clock_GetMainClockRate() / div); + + divf = Chip_Clock_GetUSARTNFRGDivider(); + if (divf == 0xFF) { + /* Fractional part is enabled, get multiplier */ + mult = (uint32_t) Chip_Clock_GetUSARTNFRGMultiplier(); + + /* Get fractional error */ + inclk = (inclk * 256) / (uint64_t) (256 + mult); + } + else { + /* Integer divide from fractional divider */ + inclk = inclk / (uint64_t) div; + } + } + + return (uint32_t) inclk; +} + +/* Set USART 1/2/3/4 UART base rate */ +uint32_t Chip_Clock_SetUSARTNBaseClockRate(uint32_t rate, bool fEnable) +{ + uint32_t div, inclk; + + /* Input clock into FRG block is the main system clock */ + inclk = Chip_Clock_GetMainClockRate(); + + /* Get integer divider for coarse rate */ + div = inclk / rate; + if (div == 0) { + div = 1; + } + + /* Approximated rate with only integer divider */ + Chip_Clock_SetUSARTNBaseClockDiv((uint8_t) div); + + if (fEnable) { + uint32_t uart_fra_multiplier; + + /* Reset FRG */ + Chip_SYSCTL_PeriphReset(RESET_FRG); + + /* Enable fractional divider */ + Chip_Clock_SetUSARTNFRGDivider(0xFF); + + /* Compute the fractional divisor (the lower byte is the + fractional portion) */ + uart_fra_multiplier = ((inclk / div) * 256) / rate; + + /* ...just the fractional portion (the lower byte) */ + Chip_Clock_SetUSARTNFRGMultiplier((uint8_t) uart_fra_multiplier); + } + else { + /* Disable fractional generator and use integer divider only */ + Chip_Clock_SetUSARTNFRGDivider(0); + } + + return Chip_Clock_GetUSARTNBaseClockRate(); +} + +/* Set System PLL clock source */ +void Chip_Clock_SetSystemPLLSource(CHIP_SYSCTL_PLLCLKSRC_T src) +{ + LPC_SYSCTL->SYSPLLCLKSEL = (uint32_t) src; + LPC_SYSCTL->SYSPLLCLKUEN = 0; + LPC_SYSCTL->SYSPLLCLKUEN = 1; +} + +/* Bypass System Oscillator and set oscillator frequency range */ +void Chip_Clock_SetPLLBypass(bool bypass, bool highfr) +{ + uint32_t ctrl = 0; + + if (bypass) { + ctrl |= (1 << 0); + } + if (highfr) { + ctrl |= (1 << 1); + } + + LPC_SYSCTL->SYSOSCCTRL = ctrl; +} + +/* Set USB PLL clock source */ +void Chip_Clock_SetUSBPLLSource(CHIP_SYSCTL_USBPLLCLKSRC_T src) +{ + LPC_SYSCTL->USBPLLCLKSEL = (uint32_t) src; + LPC_SYSCTL->USBPLLCLKUEN = 0; + LPC_SYSCTL->USBPLLCLKUEN = 1; +} + +/* Set main system clock source */ +void Chip_Clock_SetMainClockSource(CHIP_SYSCTL_MAINCLKSRC_T src) +{ + LPC_SYSCTL->MAINCLKSEL = (uint32_t) src; + LPC_SYSCTL->MAINCLKUEN = 0; + LPC_SYSCTL->MAINCLKUEN = 1; +} + +/* Set USB clock source and divider */ +void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src, uint32_t div) +{ + LPC_SYSCTL->USBCLKSEL = (uint32_t) src; + LPC_SYSCTL->USBCLKUEN = 0; + LPC_SYSCTL->USBCLKUEN = 1; + LPC_SYSCTL->USBCLKDIV = div; +} + +/* Set CLKOUT clock source and divider */ +void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src, uint32_t div) +{ + LPC_SYSCTL->CLKOUTSEL = (uint32_t) src; + LPC_SYSCTL->CLKOUTUEN = 0; + LPC_SYSCTL->CLKOUTUEN = 1; + LPC_SYSCTL->CLKOUTDIV = div; +} + +/* Return estimated watchdog oscillator rate */ +uint32_t Chip_Clock_GetWDTOSCRate(void) +{ + return Chip_Clock_GetWDTRate(LPC_SYSCTL->WDTOSCCTRL); +} + +/* Return System PLL input clock rate */ +uint32_t Chip_Clock_GetSystemPLLInClockRate(void) +{ + uint32_t clkRate; + + switch ((CHIP_SYSCTL_PLLCLKSRC_T) (LPC_SYSCTL->SYSPLLCLKSEL & 0x3)) { + case SYSCTL_PLLCLKSRC_IRC: + clkRate = Chip_Clock_GetIntOscRate(); + break; + + case SYSCTL_PLLCLKSRC_MAINOSC: + clkRate = Chip_Clock_GetMainOscRate(); + break; + + case SYSCTL_PLLCLKSRC_RTC32K: + clkRate = Chip_Clock_GetRTCOscRate(); + break; + + default: + clkRate = 0; + } + + return clkRate; +} + +/* Return System PLL output clock rate */ +uint32_t Chip_Clock_GetSystemPLLOutClockRate(void) +{ + return Chip_Clock_GetPLLFreq(LPC_SYSCTL->SYSPLLCTRL, + Chip_Clock_GetSystemPLLInClockRate()); +} + +/* Return USB PLL input clock rate */ +uint32_t Chip_Clock_GetUSBPLLInClockRate(void) +{ + uint32_t clkRate; + + switch ((CHIP_SYSCTL_USBPLLCLKSRC_T) (LPC_SYSCTL->USBPLLCLKSEL & 0x3)) { + case SYSCTL_PLLCLKSRC_IRC: + clkRate = Chip_Clock_GetIntOscRate(); + break; + + case SYSCTL_PLLCLKSRC_MAINOSC: + clkRate = Chip_Clock_GetMainOscRate(); + break; + + default: + clkRate = 0; + } + + return clkRate; +} + +/* Return USB PLL output clock rate */ +uint32_t Chip_Clock_GetUSBPLLOutClockRate(void) +{ + return Chip_Clock_GetPLLFreq(LPC_SYSCTL->USBPLLCTRL, + Chip_Clock_GetUSBPLLInClockRate()); +} + +/* Return main clock rate */ +uint32_t Chip_Clock_GetMainClockRate(void) +{ + uint32_t clkRate = 0; + + switch ((CHIP_SYSCTL_MAINCLKSRC_T) (LPC_SYSCTL->MAINCLKSEL & 0x3)) { + case SYSCTL_MAINCLKSRC_IRC: + clkRate = Chip_Clock_GetIntOscRate(); + break; + + case SYSCTL_MAINCLKSRC_PLLIN: + clkRate = Chip_Clock_GetSystemPLLInClockRate(); + break; + + case SYSCTL_MAINCLKSRC_WDTOSC: + clkRate = Chip_Clock_GetWDTOSCRate(); + break; + + case SYSCTL_MAINCLKSRC_PLLOUT: + clkRate = Chip_Clock_GetSystemPLLOutClockRate(); + break; + } + + return clkRate; +} + +/* Return system clock rate */ +uint32_t Chip_Clock_GetSystemClockRate(void) +{ + /* No point in checking for divide by 0 */ + return Chip_Clock_GetMainClockRate() / LPC_SYSCTL->SYSAHBCLKDIV; +} diff --git a/source/lpc_chip_11u6x/src/crc_11u6x.c b/source/lpc_chip_11u6x/src/crc_11u6x.c new file mode 100644 index 0000000..802fa1e --- /dev/null +++ b/source/lpc_chip_11u6x/src/crc_11u6x.c @@ -0,0 +1,117 @@ +/* + * @brief LPC11u6x Cyclic Redundancy Check (CRC) Engine driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize CRC engine */ +void Chip_CRC_Init(void) +{ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CRC); +} + +/* De-initialize CRC engine */ +void Chip_CRC_Deinit(void) +{ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_CRC); +} + +/* Sets up the CRC engine with defaults based on the polynomial to be used */ +void Chip_CRC_UseDefaultConfig(CRC_POLY_T poly) +{ + switch (poly) { + case CRC_POLY_CRC16: + Chip_CRC_UseCRC16(); + break; + + case CRC_POLY_CRC32: + Chip_CRC_UseCRC32(); + break; + + case CRC_POLY_CCITT: + default: + Chip_CRC_UseCCITT(); + break; + } +} + +/* configure CRC engine and compute CCITT checksum from 8-bit data */ +uint32_t Chip_CRC_CRC8(const uint8_t *data, uint32_t bytes) +{ + Chip_CRC_UseCCITT(); + while (bytes > 0) { + Chip_CRC_Write8(*data); + data++; + bytes--; + } + + return Chip_CRC_Sum(); +} + +/* Convenience function for computing a standard CRC16 checksum from 16-bit data block */ +uint32_t Chip_CRC_CRC16(const uint16_t *data, uint32_t hwords) +{ + Chip_CRC_UseCRC16(); + while (hwords > 0) { + Chip_CRC_Write16(*data); + data++; + hwords--; + } + + return Chip_CRC_Sum(); +} + +/* Convenience function for computing a standard CRC32 checksum from 32-bit data block */ +uint32_t Chip_CRC_CRC32(const uint32_t *data, uint32_t words) +{ + Chip_CRC_UseCRC32(); + while (words > 0) { + Chip_CRC_Write32(*data); + data++; + words--; + } + + return Chip_CRC_Sum(); +} diff --git a/source/lpc_chip_11u6x/src/dma_11u6x.c b/source/lpc_chip_11u6x/src/dma_11u6x.c new file mode 100644 index 0000000..294a769 --- /dev/null +++ b/source/lpc_chip_11u6x/src/dma_11u6x.c @@ -0,0 +1,115 @@ +/* + * @brief LPC11u6x DMA chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/* DMA SRAM table - this can be optionally used with the Chip_DMA_SetSRAMBase() + function if a DMA SRAM table is needed. This table is correctly aligned for + the DMA controller. */ +#if defined(__CC_ARM) +/* Keil alignement to 256 bytes */ +__align(256) DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL]; +#endif /* defined (__CC_ARM) */ + +/* IAR support */ +#if defined(__ICCARM__) +/* IAR EWARM alignement to 256 bytes */ +#pragma data_alignment=256 +DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL]; +#endif /* defined (__ICCARM__) */ + +#if defined( __GNUC__ ) +/* GNU alignement to 256 bytes */ +DMA_CHDESC_T Chip_DMA_Table[MAX_DMA_CHANNEL] __attribute__ ((aligned(256))); +#endif /* defined (__GNUC__) */ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Set DMA transfer register interrupt bits (safe) */ +void Chip_DMA_SetTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask) +{ + uint32_t temp; + + /* Read and write values may not be the same, write 0 to + undefined bits */ + temp = pDMA->DMACH[ch].XFERCFG & ~0xFC000CC0; + + pDMA->DMACH[ch].XFERCFG = temp | mask; +} + +/* Clear DMA transfer register interrupt bits (safe) */ +void Chip_DMA_ClearTranBits(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t mask) +{ + uint32_t temp; + + /* Read and write values may not be the same, write 0 to + undefined bits */ + temp = pDMA->DMACH[ch].XFERCFG & ~0xFC000CC0; + + pDMA->DMACH[ch].XFERCFG = temp & ~mask; +} + +/* Update the transfer size in an existing DMA channel transfer configuration */ +void Chip_DMA_SetupChannelTransferSize(LPC_DMA_T *pDMA, DMA_CHID_T ch, uint32_t trans) +{ + Chip_DMA_ClearTranBits(pDMA, ch, (0x3FF << 16)); + Chip_DMA_SetTranBits(pDMA, ch, DMA_XFERCFG_XFERCOUNT(trans)); +} + +/* Sets up a DMA channel with the passed DMA transfer descriptor */ +bool Chip_DMA_SetupTranChannel(LPC_DMA_T *pDMA, DMA_CHID_T ch, DMA_CHDESC_T *desc) +{ + bool good = false; + DMA_CHDESC_T *pDesc = (DMA_CHDESC_T *) pDMA->SRAMBASE; + + if ((Chip_DMA_GetActiveChannels(pDMA) & (1 << ch)) == 0) { + /* Channel is not active, so update the descriptor */ + pDesc[ch] = *desc; + + good = true; + } + + return good; +} diff --git a/source/lpc_chip_11u6x/src/gpio_11u6x.c b/source/lpc_chip_11u6x/src/gpio_11u6x.c new file mode 100644 index 0000000..63d7123 --- /dev/null +++ b/source/lpc_chip_11u6x/src/gpio_11u6x.c @@ -0,0 +1,104 @@ +/* + * @brief LPC11u6x GPIO driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize GPIO block */ +void Chip_GPIO_Init(LPC_GPIO_T *pGPIO) +{ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO); +} + +/* De-Initialize GPIO block */ +void Chip_GPIO_DeInit(LPC_GPIO_T *pGPIO) +{ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_GPIO); +} + +/* Set a GPIO direction */ +void Chip_GPIO_WriteDirBit(LPC_GPIO_T *pGPIO, uint32_t port, uint8_t bit, bool setting) +{ + if (setting) { + pGPIO->DIR[port] |= 1UL << bit; + } + else { + pGPIO->DIR[port] &= ~(1UL << bit); + } +} + +/* Set Direction for a GPIO port */ +void Chip_GPIO_SetDir(LPC_GPIO_T *pGPIO, uint8_t portNum, uint32_t bitValue, uint8_t out) +{ + if (out) { + pGPIO->DIR[portNum] |= bitValue; + } + else { + pGPIO->DIR[portNum] &= ~bitValue; + } +} + +/* Set GPIO direction for a single GPIO pin */ +void Chip_GPIO_SetPinDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint8_t pin, bool output) +{ + if (output) { + Chip_GPIO_SetPinDIROutput(pGPIO, port, pin); + } + else { + Chip_GPIO_SetPinDIRInput(pGPIO, port, pin); + } +} + +/* Set GPIO direction for a all selected GPIO pins to an input or output */ +void Chip_GPIO_SetPortDIR(LPC_GPIO_T *pGPIO, uint8_t port, uint32_t pinMask, bool outSet) +{ + if (outSet) { + Chip_GPIO_SetPortDIROutput(pGPIO, port, pinMask); + } + else { + Chip_GPIO_SetPortDIRInput(pGPIO, port, pinMask); + } +} diff --git a/source/lpc_chip_11u6x/src/gpiogroup_11u6x.c b/source/lpc_chip_11u6x/src/gpiogroup_11u6x.c new file mode 100644 index 0000000..34f9840 --- /dev/null +++ b/source/lpc_chip_11u6x/src/gpiogroup_11u6x.c @@ -0,0 +1,48 @@ +/* + * @brief LPC11U6x GPIO group driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ diff --git a/source/lpc_chip_11u6x/src/i2c_11u6x.c b/source/lpc_chip_11u6x/src/i2c_11u6x.c new file mode 100644 index 0000000..7efad75 --- /dev/null +++ b/source/lpc_chip_11u6x/src/i2c_11u6x.c @@ -0,0 +1,554 @@ +/* + * @brief LPC11u6x I2C driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Control flags */ +#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA) +#define LPC_I2Cx(id) ((i2c[id].ip)) +#define SLAVE_ACTIVE(iic) (((iic)->flags & 0xFF00) != 0) + +/* I2C common interface structure */ +struct i2c_interface { + LPC_I2C_T *ip; /* IP base address of the I2C device */ + CHIP_SYSCTL_CLOCK_T clk; /* Clock used by I2C */ + I2C_EVENTHANDLER_T mEvent; /* Current active Master event handler */ + I2C_EVENTHANDLER_T sEvent; /* Slave transfer events */ + I2C_XFER_T *mXfer; /* Current active xfer pointer */ + I2C_XFER_T *sXfer; /* Pointer to store xfer when bus is busy */ + uint32_t flags; /* Flags used by I2C master and slave */ +}; + +/* Slave interface structure */ +struct i2c_slave_interface { + I2C_XFER_T *xfer; + I2C_EVENTHANDLER_T event; +}; + +/* I2C interfaces */ +static struct i2c_interface i2c[I2C_NUM_INTERFACE] = { + {LPC_I2C0, SYSCTL_CLOCK_I2C0, Chip_I2C_EventHandler, NULL, NULL, NULL, 0}, + {LPC_I2C1, SYSCTL_CLOCK_I2C1, Chip_I2C_EventHandler, NULL, NULL, NULL, 0} +}; + +static struct i2c_slave_interface i2c_slave[I2C_NUM_INTERFACE][I2C_SLAVE_NUM_INTERFACE]; + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +STATIC INLINE void enableClk(I2C_ID_T id) +{ + Chip_Clock_EnablePeriphClock(i2c[id].clk); +} + +STATIC INLINE void disableClk(I2C_ID_T id) +{ + Chip_Clock_DisablePeriphClock(i2c[id].clk); +} + +/* Get the ADC Clock Rate */ +STATIC INLINE uint32_t getClkRate(I2C_ID_T id) +{ + return Chip_Clock_GetMainClockRate(); +} + +/* Enable I2C and start master transfer */ +STATIC INLINE void startMasterXfer(LPC_I2C_T *pI2C) +{ + /* Reset STA, STO, SI */ + pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA; + + /* Enter to Master Transmitter mode */ + pI2C->CONSET = I2C_CON_I2EN | I2C_CON_STA; +} + +/* Enable I2C and enable slave transfers */ +STATIC INLINE void startSlaverXfer(LPC_I2C_T *pI2C) +{ + /* Reset STA, STO, SI */ + pI2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA; + + /* Enter to Master Transmitter mode */ + pI2C->CONSET = I2C_CON_I2EN | I2C_CON_AA; +} + +/* Check if I2C bus is free */ +STATIC INLINE int isI2CBusFree(LPC_I2C_T *pI2C) +{ + return !(pI2C->CONSET & I2C_CON_STO); +} + +/* Get current state of the I2C peripheral */ +STATIC INLINE int getCurState(LPC_I2C_T *pI2C) +{ + return (int) (pI2C->STAT & I2C_STAT_CODE_BITMASK); +} + +/* Check if the active state belongs to master mode*/ +STATIC INLINE int isMasterState(LPC_I2C_T *pI2C) +{ + return getCurState(pI2C) < 0x60; +} + +/* Set OWN slave address for specific slave ID */ +STATIC void setSlaveAddr(LPC_I2C_T *pI2C, I2C_SLAVE_ID sid, uint8_t addr, uint8_t mask) +{ + uint32_t index = (uint32_t) sid - 1; + pI2C->MASK[index] = mask; + if (sid == I2C_SLAVE_0) { + pI2C->ADR0 = addr; + } + else { + volatile uint32_t *abase = &pI2C->ADR1; + abase[index - 1] = addr; + } +} + +/* Match the slave address */ +STATIC int isSlaveAddrMatching(uint8_t addr1, uint8_t addr2, uint8_t mask) +{ + mask |= 1; + return (addr1 & ~mask) == (addr2 & ~mask); +} + +/* Get the index of the active slave */ +STATIC I2C_SLAVE_ID lookupSlaveIndex(LPC_I2C_T *pI2C, uint8_t slaveAddr) +{ + if (!(slaveAddr >> 1)) { + return I2C_SLAVE_GENERAL; /* General call address */ + } + if (isSlaveAddrMatching(pI2C->ADR0, slaveAddr, pI2C->MASK[0])) { + return I2C_SLAVE_0; + } + if (isSlaveAddrMatching(pI2C->ADR1, slaveAddr, pI2C->MASK[1])) { + return I2C_SLAVE_1; + } + if (isSlaveAddrMatching(pI2C->ADR2, slaveAddr, pI2C->MASK[2])) { + return I2C_SLAVE_2; + } + if (isSlaveAddrMatching(pI2C->ADR3, slaveAddr, pI2C->MASK[3])) { + return I2C_SLAVE_3; + } + + /* If everything is fine the code should never come here */ + return I2C_SLAVE_GENERAL; +} + +/* Master transfer state change handler handler */ +int handleMasterXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer) +{ + uint32_t cclr = I2C_CON_FLAGS; + + switch (getCurState(pI2C)) { + case 0x08: /* Start condition on bus */ + case 0x10: /* Repeated start condition */ + pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0); + break; + + /* Tx handling */ + case 0x18: /* SLA+W sent and ACK received */ + case 0x28: /* DATA sent and ACK received */ + if (!xfer->txSz) { + cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO); + } + else { + pI2C->DAT = *xfer->txBuff++; + xfer->txSz--; + } + break; + + /* Rx handling */ + case 0x58: /* Data Received and NACK sent */ + cclr &= ~I2C_CON_STO; + + case 0x50: /* Data Received and ACK sent */ + *xfer->rxBuff++ = pI2C->DAT; + xfer->rxSz--; + + case 0x40: /* SLA+R sent and ACK received */ + if (xfer->rxSz > 1) { + cclr &= ~I2C_CON_AA; + } + break; + + /* NAK Handling */ + case 0x20: /* SLA+W sent NAK received */ + case 0x48: /* SLA+R sent NAK received */ + xfer->status = I2C_STATUS_SLAVENAK; + cclr &= ~I2C_CON_STO; + break; + + case 0x30: /* DATA sent NAK received */ + xfer->status = I2C_STATUS_NAK; + cclr &= ~I2C_CON_STO; + break; + + case 0x38: /* Arbitration lost */ + xfer->status = I2C_STATUS_ARBLOST; + break; + + /* Bus Error */ + case 0x00: + xfer->status = I2C_STATUS_BUSERR; + cclr &= ~I2C_CON_STO; + } + + /* Set clear control flags */ + pI2C->CONSET = cclr ^ I2C_CON_FLAGS; + pI2C->CONCLR = cclr; + + /* If stopped return 0 */ + if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) { + if (xfer->status == I2C_STATUS_BUSY) { + xfer->status = I2C_STATUS_DONE; + } + return 0; + } + return 1; +} + +/* Find the slave address of SLA+W or SLA+R */ +I2C_SLAVE_ID getSlaveIndex(LPC_I2C_T *pI2C) +{ + switch (getCurState(pI2C)) { + case 0x60: + case 0x68: + case 0x70: + case 0x78: + case 0xA8: + case 0xB0: + return lookupSlaveIndex(pI2C, pI2C->DAT); + } + + /* If everything is fine code should never come here */ + return I2C_SLAVE_GENERAL; +} + +/* Slave state machine handler */ +int handleSlaveXferState(LPC_I2C_T *pI2C, I2C_XFER_T *xfer) +{ + uint32_t cclr = I2C_CON_FLAGS; + int ret = RET_SLAVE_BUSY; + + xfer->status = I2C_STATUS_BUSY; + switch (getCurState(pI2C)) { + case 0x80: /* SLA: Data received + ACK sent */ + case 0x90: /* GC: Data received + ACK sent */ + *xfer->rxBuff++ = pI2C->DAT; + xfer->rxSz--; + ret = RET_SLAVE_RX; + if (xfer->rxSz > 1) { + cclr &= ~I2C_CON_AA; + } + break; + + case 0x60: /* Own SLA+W received */ + case 0x68: /* Own SLA+W received after losing arbitration */ + case 0x70: /* GC+W received */ + case 0x78: /* GC+W received after losing arbitration */ + xfer->slaveAddr = pI2C->DAT & ~1; + if (xfer->rxSz > 1) { + cclr &= ~I2C_CON_AA; + } + break; + + case 0xA8: /* SLA+R received */ + case 0xB0: /* SLA+R received after losing arbitration */ + xfer->slaveAddr = pI2C->DAT & ~1; + + case 0xB8: /* DATA sent and ACK received */ + pI2C->DAT = *xfer->txBuff++; + xfer->txSz--; + if (xfer->txSz > 0) { + cclr &= ~I2C_CON_AA; + } + ret = RET_SLAVE_TX; + break; + + case 0xC0: /* Data transmitted and NAK received */ + case 0xC8: /* Last data transmitted and ACK received */ + case 0x88: /* SLA: Data received + NAK sent */ + case 0x98: /* GC: Data received + NAK sent */ + case 0xA0: /* STOP/Repeated START condition received */ + ret = RET_SLAVE_IDLE; + cclr &= ~I2C_CON_AA; + xfer->status = I2C_STATUS_DONE; + if (xfer->slaveAddr & 1) { + cclr &= ~I2C_CON_STA; + } + break; + } + + /* Set clear control flags */ + pI2C->CONSET = cclr ^ I2C_CON_FLAGS; + pI2C->CONCLR = cclr; + + return ret; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Chip event handler interrupt based */ +void Chip_I2C_EventHandler(I2C_ID_T id, I2C_EVENT_T event) +{ + struct i2c_interface *iic = &i2c[id]; + volatile I2C_STATUS_T *stat; + + /* Only WAIT event needs to be handled */ + if (event != I2C_EVENT_WAIT) { + return; + } + + stat = &iic->mXfer->status; + /* Wait for the status to change */ + while (*stat == I2C_STATUS_BUSY) {} +} + +/* Chip polling event handler */ +void Chip_I2C_EventHandlerPolling(I2C_ID_T id, I2C_EVENT_T event) +{ + struct i2c_interface *iic = &i2c[id]; + volatile I2C_STATUS_T *stat; + + /* Only WAIT event needs to be handled */ + if (event != I2C_EVENT_WAIT) { + return; + } + + stat = &iic->mXfer->status; + /* Call the state change handler till xfer is done */ + while (*stat == I2C_STATUS_BUSY) { + if (Chip_I2C_IsStateChanged(id)) { + Chip_I2C_MasterStateHandler(id); + } + } +} + +/* Initializes the LPC_I2C peripheral with specified parameter */ +void Chip_I2C_Init(I2C_ID_T id) +{ + enableClk(id); + + /* Set I2C operation to default */ + LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN); +} + +/* De-initializes the I2C peripheral registers to their default reset values */ +void Chip_I2C_DeInit(I2C_ID_T id) +{ + /* Disable I2C control */ + LPC_I2Cx(id)->CONCLR = I2C_CON_I2EN | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA; + + disableClk(id); +} + +/* Set up clock rate for LPC_I2C peripheral */ +void Chip_I2C_SetClockRate(I2C_ID_T id, uint32_t clockrate) +{ + uint32_t SCLValue; + + SCLValue = (getClkRate(id) / clockrate); + LPC_I2Cx(id)->SCLH = (uint32_t) (SCLValue >> 1); + LPC_I2Cx(id)->SCLL = (uint32_t) (SCLValue - LPC_I2Cx(id)->SCLH); +} + +/* Get current clock rate for LPC_I2C peripheral */ +uint32_t Chip_I2C_GetClockRate(I2C_ID_T id) +{ + return getClkRate(id) / (LPC_I2Cx(id)->SCLH + LPC_I2Cx(id)->SCLL); +} + +/* Set the master event handler */ +int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event) +{ + struct i2c_interface *iic = &i2c[id]; + if (!iic->mXfer) { + iic->mEvent = event; + } + return iic->mEvent == event; +} + +/* Get the master event handler */ +I2C_EVENTHANDLER_T Chip_I2C_GetMasterEventHandler(I2C_ID_T id) +{ + return i2c[id].mEvent; +} + +/* Transmit and Receive data in master mode */ +int Chip_I2C_MasterTransfer(I2C_ID_T id, I2C_XFER_T *xfer) +{ + struct i2c_interface *iic = &i2c[id]; + + iic->mEvent(id, I2C_EVENT_LOCK); + xfer->status = I2C_STATUS_BUSY; + iic->mXfer = xfer; + + /* If slave xfer not in progress */ + if (!iic->sXfer) { + startMasterXfer(iic->ip); + } + iic->mEvent(id, I2C_EVENT_WAIT); + iic->mXfer = 0; + + /* Wait for stop condition to appear on bus */ + while (!isI2CBusFree(iic->ip)) {} + + /* Start slave if one is active */ + if (SLAVE_ACTIVE(iic)) { + startSlaverXfer(iic->ip); + } + + iic->mEvent(id, I2C_EVENT_UNLOCK); + return (int) xfer->status; +} + +/* Master tx only */ +int Chip_I2C_MasterSend(I2C_ID_T id, uint8_t slaveAddr, const uint8_t *buff, uint8_t len) +{ + I2C_XFER_T xfer = {0}; + xfer.slaveAddr = slaveAddr; + xfer.txBuff = buff; + xfer.txSz = len; + while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {} + return len - xfer.txSz; +} + +/* Transmit one byte and receive an array of bytes after a repeated start condition is generated in Master mode. + * This function is useful for communicating with the I2C slave registers + */ +int Chip_I2C_MasterCmdRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t cmd, uint8_t *buff, int len) +{ + I2C_XFER_T xfer = {0}; + xfer.slaveAddr = slaveAddr; + xfer.txBuff = &cmd; + xfer.txSz = 1; + xfer.rxBuff = buff; + xfer.rxSz = len; + while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {} + return len - xfer.rxSz; +} + +/* Sequential master read */ +int Chip_I2C_MasterRead(I2C_ID_T id, uint8_t slaveAddr, uint8_t *buff, int len) +{ + I2C_XFER_T xfer = {0}; + xfer.slaveAddr = slaveAddr; + xfer.rxBuff = buff; + xfer.rxSz = len; + while (Chip_I2C_MasterTransfer(id, &xfer) == I2C_STATUS_ARBLOST) {} + return len - xfer.rxSz; +} + +/* Check if master state is active */ +int Chip_I2C_IsMasterActive(I2C_ID_T id) +{ + return isMasterState(i2c[id].ip); +} + +/* State change handler for master transfer */ +void Chip_I2C_MasterStateHandler(I2C_ID_T id) +{ + if (!handleMasterXferState(i2c[id].ip, i2c[id].mXfer)) { + i2c[id].mEvent(id, I2C_EVENT_DONE); + } +} + +/* Setup slave function */ +void Chip_I2C_SlaveSetup(I2C_ID_T id, + I2C_SLAVE_ID sid, + I2C_XFER_T *xfer, + I2C_EVENTHANDLER_T event, + uint8_t addrMask) +{ + struct i2c_interface *iic = &i2c[id]; + struct i2c_slave_interface *si2c = &i2c_slave[id][sid]; + si2c->xfer = xfer; + si2c->event = event; + + /* Set up the slave address */ + if (sid != I2C_SLAVE_GENERAL) { + setSlaveAddr(iic->ip, sid, xfer->slaveAddr, addrMask); + } + + if (!SLAVE_ACTIVE(iic) && !iic->mXfer) { + startSlaverXfer(iic->ip); + } + iic->flags |= 1 << (sid + 8); +} + +/* I2C Slave event handler */ +void Chip_I2C_SlaveStateHandler(I2C_ID_T id) +{ + int ret; + struct i2c_interface *iic = &i2c[id]; + + /* Get the currently addressed slave */ + if (!iic->sXfer) { + struct i2c_slave_interface *si2c; + + I2C_SLAVE_ID sid = getSlaveIndex(iic->ip); + si2c = &i2c_slave[id][sid]; + iic->sXfer = si2c->xfer; + iic->sEvent = si2c->event; + } + + iic->sXfer->slaveAddr |= iic->mXfer != 0; + ret = handleSlaveXferState(iic->ip, iic->sXfer); + if (ret) { + if (iic->sXfer->status == I2C_STATUS_DONE) { + iic->sXfer = 0; + } + iic->sEvent(id, (I2C_EVENT_T) ret); + } +} + +/* Disable I2C device */ +void Chip_I2C_Disable(I2C_ID_T id) +{ + LPC_I2Cx(id)->CONCLR = I2C_I2CONCLR_I2ENC; +} + +/* State change checking */ +int Chip_I2C_IsStateChanged(I2C_ID_T id) +{ + return (LPC_I2Cx(id)->CONSET & I2C_CON_SI) != 0; +} diff --git a/source/lpc_chip_11u6x/src/i2cm_11u6x.c b/source/lpc_chip_11u6x/src/i2cm_11u6x.c new file mode 100644 index 0000000..afc0c43 --- /dev/null +++ b/source/lpc_chip_11u6x/src/i2cm_11u6x.c @@ -0,0 +1,197 @@ +/* + * @brief LPC11u6x I2C master driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Control flags */ +#define I2C_CON_FLAGS (I2C_CON_AA | I2C_CON_SI | I2C_CON_STO | I2C_CON_STA) + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initializes the LPC_I2C peripheral with specified parameter */ +void Chip_I2CM_Init(LPC_I2C_T *pI2C) +{ + CHIP_SYSCTL_CLOCK_T clk = SYSCTL_CLOCK_I2C0; + CHIP_SYSCTL_PERIPH_RESET_T rst = RESET_I2C0; + + if (pI2C == LPC_I2C1) { + clk = SYSCTL_CLOCK_I2C1; + rst = RESET_I2C1; + } + /* Enable I2C clock */ + Chip_Clock_EnablePeriphClock(clk); + + /* Peripheral reset control to I2C */ + Chip_SYSCTL_PeriphReset(rst); +} + +/* De-initializes the I2C peripheral registers to their default reset values */ +void Chip_I2CM_DeInit(LPC_I2C_T *pI2C) +{ + CHIP_SYSCTL_CLOCK_T clk = SYSCTL_CLOCK_I2C0; + + if (pI2C == LPC_I2C1) { + clk = SYSCTL_CLOCK_I2C1; + } + /* Disable I2C clock */ + Chip_Clock_DisablePeriphClock(clk); +} + +/* Set up bus speed for LPC_I2C interface */ +void Chip_I2CM_SetBusSpeed(LPC_I2C_T *pI2C, uint32_t busSpeed) +{ + uint32_t clockDiv = (Chip_Clock_GetMainClockRate() / busSpeed); + + Chip_I2CM_SetDutyCycle(pI2C, (clockDiv >> 1), (clockDiv - (clockDiv >> 1))); +} + +/* Master transfer state change handler handler */ +uint32_t Chip_I2CM_XferHandler(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer) +{ + uint32_t cclr = I2C_CON_FLAGS; + + switch (Chip_I2CM_GetCurState(pI2C)) { + case 0x08: /* Start condition on bus */ + case 0x10: /* Repeated start condition */ + pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0); + break; + + /* Tx handling */ + case 0x20: /* SLA+W sent NAK received */ + case 0x30: /* DATA sent NAK received */ + if ((xfer->options & I2CM_XFER_OPTION_IGNORE_NACK) == 0) { + xfer->status = I2CM_STATUS_NAK; + cclr &= ~I2C_CON_STO; + break; + } + + case 0x18: /* SLA+W sent and ACK received */ + case 0x28: /* DATA sent and ACK received */ + if (!xfer->txSz) { + if (xfer->rxSz) { + cclr &= ~I2C_CON_STA; + } + else { + xfer->status = I2CM_STATUS_OK; + cclr &= ~I2C_CON_STO; + } + + } + else { + pI2C->DAT = *xfer->txBuff++; + xfer->txSz--; + } + break; + + /* Rx handling */ + case 0x58: /* Data Received and NACK sent */ + case 0x50: /* Data Received and ACK sent */ + *xfer->rxBuff++ = pI2C->DAT; + xfer->rxSz--; + + case 0x40: /* SLA+R sent and ACK received */ + if ((xfer->rxSz > 1) || (xfer->options & I2CM_XFER_OPTION_LAST_RX_ACK)) { + cclr &= ~I2C_CON_AA; + } + if (xfer->rxSz == 0) { + xfer->status = I2CM_STATUS_OK; + cclr &= ~I2C_CON_STO; + } + break; + + /* NAK Handling */ + case 0x48: /* SLA+R sent NAK received */ + xfer->status = I2CM_STATUS_SLAVE_NAK; + cclr &= ~I2C_CON_STO; + break; + + case 0x38: /* Arbitration lost */ + xfer->status = I2CM_STATUS_ARBLOST; + break; + + case 0x00: /* Bus Error */ + xfer->status = I2CM_STATUS_BUS_ERROR; + cclr &= ~I2C_CON_STO; + break; + + default: + xfer->status = I2CM_STATUS_ERROR; + cclr &= ~I2C_CON_STO; + break; + } + + /* Set clear control flags */ + pI2C->CONSET = cclr ^ I2C_CON_FLAGS; + pI2C->CONCLR = cclr; + + return xfer->status != I2CM_STATUS_BUSY; +} + +/* Transmit and Receive data in master mode */ +void Chip_I2CM_Xfer(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer) +{ + /* set the transfer status as busy */ + xfer->status = I2CM_STATUS_BUSY; + /* Clear controller state. */ + Chip_I2CM_ResetControl(pI2C); + /* Enter to Master Transmitter mode */ + Chip_I2CM_SendStart(pI2C); +} + +/* Transmit and Receive data in master mode */ +uint32_t Chip_I2CM_XferBlocking(LPC_I2C_T *pI2C, I2CM_XFER_T *xfer) +{ + uint32_t ret = 0; + /* start transfer */ + Chip_I2CM_Xfer(pI2C, xfer); + + while (ret == 0) { + /* wait for status change interrupt */ + while ( Chip_I2CM_StateChanged(pI2C) == 0) {} + /* call state change handler */ + ret = Chip_I2CM_XferHandler(pI2C, xfer); + } + return ret; +} diff --git a/source/lpc_chip_11u6x/src/iocon_11u6x.c b/source/lpc_chip_11u6x/src/iocon_11u6x.c new file mode 100644 index 0000000..a2352f8 --- /dev/null +++ b/source/lpc_chip_11u6x/src/iocon_11u6x.c @@ -0,0 +1,82 @@ +/* + * @brief LPC11u6x IOCON driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Sets I/O Control pin mux */ +void Chip_IOCON_PinMuxSet(LPC_IOCON_T *pIOCON, uint8_t port, uint8_t pin, uint32_t modefunc) +{ + switch (port) { + case 0: + pIOCON->PIO0[pin] = modefunc; + break; + + case 1: + pIOCON->PIO1[pin] = modefunc; + break; + + case 2: + if (pin >= 2) { + pIOCON->PIO2B[pin - 2] = modefunc; + } + else { + pIOCON->PIO2A[pin] = modefunc; + } + break; + + default: + break; + } +} + +/*Set all I/O Control pin muxing*/ +void Chip_IOCON_SetPinMuxing(LPC_IOCON_T *pIOCON, const PINMUX_GRP_T* pinArray, uint32_t arrayLength) +{ + uint32_t ix; + + for (ix = 0; ix < arrayLength; ix++ ) { + Chip_IOCON_PinMuxSet(pIOCON, pinArray[ix].port, pinArray[ix].pin, pinArray[ix].modefunc); + } +} diff --git a/source/lpc_chip_11u6x/src/pinint_11u6x.c b/source/lpc_chip_11u6x/src/pinint_11u6x.c new file mode 100644 index 0000000..f540c24 --- /dev/null +++ b/source/lpc_chip_11u6x/src/pinint_11u6x.c @@ -0,0 +1,77 @@ +/* + * @brief LPC11u6x Pin Interrupt and Pattern Match driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Set source for pattern match engine */ +void Chip_PININT_SetPatternMatchSrc(LPC_PIN_INT_T *pPININT, uint8_t chan, Chip_PININT_BITSLICE_T slice) +{ + uint32_t pmsrc_reg; + + /* Source source for pattern matching */ + pmsrc_reg = pPININT->PMSRC & ~(PININT_SRC_BITSOURCE_MASK << (PININT_SRC_BITSOURCE_START + (slice * 3))); + pPININT->PMSRC = pmsrc_reg | (chan << (PININT_SRC_BITSOURCE_START + (slice * 3))); +} + +/* Configure Pattern match engine */ +void Chip_PININT_SetPatternMatchConfig(LPC_PIN_INT_T *pPININT, Chip_PININT_BITSLICE_T slice, + Chip_PININT_BITSLICE_CFG_T slice_cfg, bool end_point) +{ + uint32_t pmcfg_reg; + + /* Configure bit slice configuration */ + pmcfg_reg = pPININT->PMCFG & ~(PININT_SRC_BITCFG_MASK << (PININT_SRC_BITCFG_START + (slice * 3))); + pPININT->PMCFG = pmcfg_reg | (slice_cfg << (PININT_SRC_BITCFG_START + (slice * 3))); + + /* If end point is true, enable the bits */ + if (end_point == true) { + /* By default slice 7 is final component */ + if (slice != PININTBITSLICE7) { + pPININT->PMCFG |= (0x1 << slice); + } + } +} diff --git a/source/lpc_chip_11u6x/src/pmu_11u6x.c b/source/lpc_chip_11u6x/src/pmu_11u6x.c new file mode 100644 index 0000000..9a6bacd --- /dev/null +++ b/source/lpc_chip_11u6x/src/pmu_11u6x.c @@ -0,0 +1,105 @@ +/* + * @brief LPC11u6x PMU chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Enter MCU Sleep mode */ +void Chip_PMU_SleepState(LPC_PMU_T *pPMU) +{ + pPMU->PCON = PMU_PCON_PM_SLEEP; + + /* Enter sleep mode */ + __WFI(); +} + +/* Enter MCU Deep Sleep mode */ +void Chip_PMU_DeepSleepState(LPC_PMU_T *pPMU) +{ + SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos); + pPMU->PCON = PMU_PCON_PM_DEEPSLEEP; + + /* Enter sleep mode */ + __WFI(); +} + +/* Enter MCU Power down mode */ +void Chip_PMU_PowerDownState(LPC_PMU_T *pPMU) +{ + SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos); + pPMU->PCON = PMU_PCON_PM_POWERDOWN; + + /* Enter sleep mode */ + __WFI(); +} + +/* Enter MCU Deep Power down mode */ +void Chip_PMU_DeepPowerDownState(LPC_PMU_T *pPMU) +{ + SCB->SCR |= (1UL << SCB_SCR_SLEEPDEEP_Pos); + pPMU->PCON = PMU_PCON_PM_DEEPPOWERDOWN; + + /* Enter sleep mode */ + __WFI(); +} + +/* Put some of the peripheral in sleep mode */ +void Chip_PMU_Sleep(LPC_PMU_T *pPMU, CHIP_PMU_MCUPOWER_T SleepMode) +{ + if (SleepMode == PMU_MCU_DEEP_SLEEP) { + Chip_PMU_DeepSleepState(pPMU); + } + else if (SleepMode == PMU_MCU_POWER_DOWN) { + Chip_PMU_PowerDownState(pPMU); + } + else if (SleepMode == PMU_MCU_DEEP_PWRDOWN) { + Chip_PMU_DeepPowerDownState(pPMU); + } + else { + /* PMU_MCU_SLEEP */ + Chip_PMU_SleepState(pPMU); + } +} diff --git a/source/lpc_chip_11u6x/src/ring_buffer.c b/source/lpc_chip_11u6x/src/ring_buffer.c new file mode 100644 index 0000000..47a0c34 --- /dev/null +++ b/source/lpc_chip_11u6x/src/ring_buffer.c @@ -0,0 +1,167 @@ +/* + * @brief Common ring buffer support functions + * + * @note + * Copyright(C) NXP Semiconductors, 2012 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include +#include "ring_buffer.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +#define RB_INDH(rb) ((rb)->head & ((rb)->count - 1)) +#define RB_INDT(rb) ((rb)->tail & ((rb)->count - 1)) + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize ring buffer */ +int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count) +{ + RingBuff->data = buffer; + RingBuff->count = count; + RingBuff->itemSz = itemSize; + RingBuff->head = RingBuff->tail = 0; + + return 1; +} + +/* Insert a single item into Ring Buffer */ +int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data) +{ + uint8_t *ptr = RingBuff->data; + + /* We cannot insert when queue is full */ + if (RingBuffer_IsFull(RingBuff)) + return 0; + + ptr += RB_INDH(RingBuff) * RingBuff->itemSz; + memcpy(ptr, data, RingBuff->itemSz); + RingBuff->head++; + + return 1; +} + +/* Insert multiple items into Ring Buffer */ +int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num) +{ + uint8_t *ptr = RingBuff->data; + int cnt1, cnt2; + + /* We cannot insert when queue is full */ + if (RingBuffer_IsFull(RingBuff)) + return 0; + + /* Calculate the segment lengths */ + cnt1 = cnt2 = RingBuffer_GetFree(RingBuff); + if (RB_INDH(RingBuff) + cnt1 >= RingBuff->count) + cnt1 = RingBuff->count - RB_INDH(RingBuff); + cnt2 -= cnt1; + + cnt1 = MIN(cnt1, num); + num -= cnt1; + + cnt2 = MIN(cnt2, num); + num -= cnt2; + + /* Write segment 1 */ + ptr += RB_INDH(RingBuff) * RingBuff->itemSz; + memcpy(ptr, data, cnt1 * RingBuff->itemSz); + RingBuff->head += cnt1; + + /* Write segment 2 */ + ptr = (uint8_t *) RingBuff->data + RB_INDH(RingBuff) * RingBuff->itemSz; + data = (const uint8_t *) data + cnt1 * RingBuff->itemSz; + memcpy(ptr, data, cnt2 * RingBuff->itemSz); + RingBuff->head += cnt2; + + return cnt1 + cnt2; +} + +/* Pop single item from Ring Buffer */ +int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data) +{ + uint8_t *ptr = RingBuff->data; + + /* We cannot pop when queue is empty */ + if (RingBuffer_IsEmpty(RingBuff)) + return 0; + + ptr += RB_INDT(RingBuff) * RingBuff->itemSz; + memcpy(data, ptr, RingBuff->itemSz); + RingBuff->tail++; + + return 1; +} + +/* Pop multiple items from Ring buffer */ +int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num) +{ + uint8_t *ptr = RingBuff->data; + int cnt1, cnt2; + + /* We cannot insert when queue is empty */ + if (RingBuffer_IsEmpty(RingBuff)) + return 0; + + /* Calculate the segment lengths */ + cnt1 = cnt2 = RingBuffer_GetCount(RingBuff); + if (RB_INDT(RingBuff) + cnt1 >= RingBuff->count) + cnt1 = RingBuff->count - RB_INDT(RingBuff); + cnt2 -= cnt1; + + cnt1 = MIN(cnt1, num); + num -= cnt1; + + cnt2 = MIN(cnt2, num); + num -= cnt2; + + /* Write segment 1 */ + ptr += RB_INDT(RingBuff) * RingBuff->itemSz; + memcpy(data, ptr, cnt1 * RingBuff->itemSz); + RingBuff->tail += cnt1; + + /* Write segment 2 */ + ptr = (uint8_t *) RingBuff->data + RB_INDT(RingBuff) * RingBuff->itemSz; + data = (uint8_t *) data + cnt1 * RingBuff->itemSz; + memcpy(data, ptr, cnt2 * RingBuff->itemSz); + RingBuff->tail += cnt2; + + return cnt1 + cnt2; +} diff --git a/source/lpc_chip_11u6x/src/romdiv_11u6x.c b/source/lpc_chip_11u6x/src/romdiv_11u6x.c new file mode 100644 index 0000000..093184a --- /dev/null +++ b/source/lpc_chip_11u6x/src/romdiv_11u6x.c @@ -0,0 +1,79 @@ +/* + * @brief Routines to overload "/" and "%" operator in C using ROM based divider library + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +#if !defined( __GNUC__ ) + +/* Redirector of signed 32 bit integer divider to ROM routine */ +int __aeabi_idiv(int numerator, int denominator) +{ + ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase; + return pROMDiv->sidiv(numerator, denominator); +} + +/* Redirector of unsigned 32 bit integer divider to ROM routine */ +unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator) +{ + ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase; + return pROMDiv->uidiv(numerator, denominator); +} + +/* Redirector of signed 32 bit integer divider with reminder to ROM routine */ +__value_in_regs IDIV_RETURN_T __aeabi_idivmod(int numerator, int denominator) +{ + ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase; + return pROMDiv->sidivmod(numerator, denominator); +} + +/* Redirector of unsigned 32 bit integer divider with reminder to ROM routine */ +__value_in_regs UIDIV_RETURN_T __aeabi_uidivmod(unsigned numerator, unsigned denominator) +{ + ROM_DIV_API_T const *pROMDiv = LPC_ROM_API->divApiBase; + return pROMDiv->uidivmod(numerator, denominator); +} + +#endif /* !defined( __GNUC__ ) */ diff --git a/source/lpc_chip_11u6x/src/rtc_11u6x.c b/source/lpc_chip_11u6x/src/rtc_11u6x.c new file mode 100644 index 0000000..a577a90 --- /dev/null +++ b/source/lpc_chip_11u6x/src/rtc_11u6x.c @@ -0,0 +1,60 @@ +/* + * @brief LPC11u6x RTC chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize the RTC peripheral */ +void Chip_RTC_Init(LPC_RTC_T *pRTC) +{ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_RTC); +} + +/* De-initialize the RTC peripheral */ +void Chip_RTC_DeInit(LPC_RTC_T *pRTC) +{ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_RTC); +} diff --git a/source/lpc_chip_11u6x/src/sct_11u6x.c b/source/lpc_chip_11u6x/src/sct_11u6x.c new file mode 100644 index 0000000..fa014bc --- /dev/null +++ b/source/lpc_chip_11u6x/src/sct_11u6x.c @@ -0,0 +1,98 @@ +/* + * @brief LPC11u6x State Configurable Timer driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* SCT clock shared count flag */ +static uint8_t sctUsedCount; + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize SCT */ +void Chip_SCT_Init(LPC_SCT_T *pSCT) +{ + if (sctUsedCount == 0) { + /* Does not handle unbalanced Init() and DeInit() calls */ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SCT0_1); + } + sctUsedCount++; + + if (pSCT == LPC_SCT0) { + Chip_SYSCTL_PeriphReset(RESET_SCT0); + } + else { + Chip_SYSCTL_PeriphReset(RESET_SCT1); + } +} + +/* Shutdown SCT */ +void Chip_SCT_DeInit(LPC_SCT_T *pSCT) +{ + sctUsedCount--; + if (sctUsedCount == 0) { + /* Does not handle unbalanced Init() and DeInit() calls */ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SCT0_1); + } +} + +/* Set/Clear SCT control register */ +void Chip_SCT_SetClrControl(LPC_SCT_T *pSCT, uint32_t value, FunctionalState ena) +{ + if (ena == ENABLE) { + Chip_SCT_SetControl(pSCT, value); + } + else { + Chip_SCT_ClearControl(pSCT, value); + } +} + +/* Set Conflict resolution */ +void Chip_SCT_SetConflictResolution(LPC_SCT_T *pSCT, uint8_t outnum, uint8_t value) +{ + uint32_t tem; + + tem = pSCT->RES & (~(0x03 << (2 * outnum))); + pSCT->RES = tem | (value << (2 * outnum)); +} diff --git a/source/lpc_chip_11u6x/src/ssp_11u6x.c b/source/lpc_chip_11u6x/src/ssp_11u6x.c new file mode 100644 index 0000000..a35eb90 --- /dev/null +++ b/source/lpc_chip_11u6x/src/ssp_11u6x.c @@ -0,0 +1,493 @@ +/* + * @brief LPC11u6x SSP Registers and control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +STATIC void SSP_Write2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + if (xf_setup->tx_data) { + Chip_SSP_SendFrame(pSSP, (*(uint16_t *) ((uint32_t) xf_setup->tx_data + + xf_setup->tx_cnt))); + xf_setup->tx_cnt += 2; + } + else { + Chip_SSP_SendFrame(pSSP, 0xFFFF); + } +} + +/** SSP macro: write 1 bytes to FIFO buffer */ +STATIC void SSP_Write1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + if (xf_setup->tx_data) { + Chip_SSP_SendFrame(pSSP, (*(uint8_t *) ((uint32_t) xf_setup->tx_data + xf_setup->tx_cnt))); + } + else { + Chip_SSP_SendFrame(pSSP, 0xFF); + } + + xf_setup->tx_cnt++; +} + +/** SSP macro: read 1 bytes from FIFO buffer */ +STATIC void SSP_Read2BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + uint16_t rDat; + + while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) && + (xf_setup->rx_cnt < xf_setup->length)) { + rDat = Chip_SSP_ReceiveFrame(pSSP); + if (xf_setup->rx_data) { + *(uint16_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat; + xf_setup->rx_cnt += 2; + } + } +} + +/** SSP macro: read 2 bytes from FIFO buffer */ +STATIC void SSP_Read1BFifo(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + uint16_t rDat; + + while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) && + (xf_setup->rx_cnt < xf_setup->length)) { + rDat = Chip_SSP_ReceiveFrame(pSSP); + if (xf_setup->rx_data) { + *(uint8_t *) ((uint32_t) xf_setup->rx_data + xf_setup->rx_cnt) = rDat; + } + + xf_setup->rx_cnt++; + } +} + +/* Returns clock for the peripheral block */ +STATIC CHIP_SYSCTL_CLOCK_T Chip_SSP_GetClockIndex(LPC_SSP_T *pSSP) +{ + CHIP_SYSCTL_CLOCK_T clkSSP; + + if (pSSP == LPC_SSP0) { + clkSSP = SYSCTL_CLOCK_SSP0; + } + else { + clkSSP = SYSCTL_CLOCK_SSP1; + } + + return clkSSP; +} + +/* Returns reset ID for the peripheral block */ +STATIC CHIP_SYSCTL_PERIPH_RESET_T Chip_SSP_GetResetIndex(LPC_SSP_T *pSSP) +{ + CHIP_SYSCTL_PERIPH_RESET_T resetSSP; + + if (pSSP == LPC_SSP0) { + resetSSP = RESET_SSP0; + } + else { + resetSSP = RESET_SSP1; + } + + return resetSSP; +} + +/* Returns reset ID for the peripheral block */ +STATIC void Chip_SSP_SetSSPClkDivider(LPC_SSP_T *pSSP, uint32_t div) +{ + if (pSSP == LPC_SSP0) { + Chip_Clock_SetSSP0ClockDiv(div); + } + else { + Chip_Clock_SetSSP1ClockDiv(div); + } +} + +/* Returns SSP peripheral clock for the peripheral block */ +STATIC uint32_t Chip_SSP_GetPCLKkRate(LPC_SSP_T *pSSP) +{ + uint32_t sspCLK = Chip_Clock_GetMainClockRate(); + + if (pSSP == LPC_SSP0) { + sspCLK /= Chip_Clock_GetSSP0ClockDiv(); + } + else { + sspCLK /= Chip_Clock_GetSSP1ClockDiv(); + } + + return sspCLK; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/*Set up output clocks per bit for SSP bus*/ +void Chip_SSP_SetClockRate(LPC_SSP_T *pSSP, uint32_t clk_rate, uint32_t prescale) +{ + uint32_t temp; + temp = pSSP->CR0 & (~(SSP_CR0_SCR(0xFF))); + pSSP->CR0 = temp | (SSP_CR0_SCR(clk_rate)); + pSSP->CPSR = prescale; +} + +/* SSP Polling Read/Write in blocking mode */ +uint32_t Chip_SSP_RWFrames_Blocking(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + /* Clear all remaining frames in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) { + Chip_SSP_ReceiveFrame(pSSP); + } + + /* Clear status */ + Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK); + + if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) { + while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) { + /* write data to buffer */ + if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) { + SSP_Write2BFifo(pSSP, xf_setup); + } + + /* Check overrun error */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + SSP_Read2BFifo(pSSP, xf_setup); + } + } + else { + while (xf_setup->rx_cnt < xf_setup->length || xf_setup->tx_cnt < xf_setup->length) { + /* write data to buffer */ + if (( Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && ( xf_setup->tx_cnt < xf_setup->length) ) { + SSP_Write1BFifo(pSSP, xf_setup); + } + + /* Check overrun error */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + SSP_Read1BFifo(pSSP, xf_setup); + } + } + if (xf_setup->tx_data) { + return xf_setup->tx_cnt; + } + else if (xf_setup->rx_data) { + return xf_setup->rx_cnt; + } + + return 0; +} + +/* SSP Polling Write in blocking mode */ +uint32_t Chip_SSP_WriteFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len) +{ + uint32_t tx_cnt = 0, rx_cnt = 0; + + /* Clear all remaining frames in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) { + Chip_SSP_ReceiveFrame(pSSP); + } + + /* Clear status */ + Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK); + + if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) { + uint16_t *wdata16; + + wdata16 = (uint16_t *) buffer; + + while (tx_cnt < buffer_len || rx_cnt < buffer_len) { + /* write data to buffer */ + if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) { + Chip_SSP_SendFrame(pSSP, *wdata16); + wdata16++; + tx_cnt += 2; + } + + /* Check overrun error */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET) { + Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */ + rx_cnt += 2; + } + } + } + else { + uint8_t *wdata8; + + wdata8 = buffer; + + while (tx_cnt < buffer_len || rx_cnt < buffer_len) { + /* write data to buffer */ + if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) { + Chip_SSP_SendFrame(pSSP, *wdata8); + wdata8++; + tx_cnt++; + } + + /* Check overrun error */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) { + Chip_SSP_ReceiveFrame(pSSP); /* read dummy data */ + rx_cnt++; + } + } + } + + return tx_cnt; + +} + +/* SSP Polling Read in blocking mode */ +uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len) +{ + uint32_t rx_cnt = 0, tx_cnt = 0; + + /* Clear all remaining frames in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) { + Chip_SSP_ReceiveFrame(pSSP); + } + + /* Clear status */ + Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK); + + if (Chip_SSP_GetDataSize(pSSP) > SSP_BITS_8) { + uint16_t *rdata16; + + rdata16 = (uint16_t *) buffer; + + while (tx_cnt < buffer_len || rx_cnt < buffer_len) { + /* write data to buffer */ + if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) { + Chip_SSP_SendFrame(pSSP, 0xFFFF); /* just send dummy data */ + tx_cnt += 2; + } + + /* Check overrun error */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) { + *rdata16 = Chip_SSP_ReceiveFrame(pSSP); + rdata16++; + rx_cnt += 2; + } + } + } + else { + uint8_t *rdata8; + + rdata8 = buffer; + + while (tx_cnt < buffer_len || rx_cnt < buffer_len) { + /* write data to buffer */ + if ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) { + Chip_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */ + tx_cnt++; + } + + /* Check overrun error */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) { + *rdata8 = Chip_SSP_ReceiveFrame(pSSP); + rdata8++; + rx_cnt++; + } + } + } + + return rx_cnt; + +} + +/* Clean all data in RX FIFO of SSP */ +void Chip_SSP_Int_FlushData(LPC_SSP_T *pSSP) +{ + if (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) { + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_BSY)) {} + } + + /* Clear all remaining frames in RX FIFO */ + while (Chip_SSP_GetStatus(pSSP, SSP_STAT_RNE)) { + Chip_SSP_ReceiveFrame(pSSP); + } + + /* Clear status */ + Chip_SSP_ClearIntPending(pSSP, SSP_INT_CLEAR_BITMASK); +} + +/* SSP Interrupt Read/Write with 8-bit frame width */ +Status Chip_SSP_Int_RWFrames8Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + /* Check overrun error in RIS register */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) { + /* check if RX FIFO contains data */ + SSP_Read1BFifo(pSSP, xf_setup); + + while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) { + /* Write data to buffer */ + SSP_Write1BFifo(pSSP, xf_setup); + + /* Check overrun error in RIS register */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + SSP_Read1BFifo(pSSP, xf_setup); + } + + return SUCCESS; + } + + return ERROR; +} + +/* SSP Interrupt Read/Write with 16-bit frame width */ +Status Chip_SSP_Int_RWFrames16Bits(LPC_SSP_T *pSSP, Chip_SSP_DATA_SETUP_T *xf_setup) +{ + /* Check overrun error in RIS register */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + if ((xf_setup->tx_cnt != xf_setup->length) || (xf_setup->rx_cnt != xf_setup->length)) { + /* check if RX FIFO contains data */ + SSP_Read2BFifo(pSSP, xf_setup); + + while ((Chip_SSP_GetStatus(pSSP, SSP_STAT_TNF)) && (xf_setup->tx_cnt != xf_setup->length)) { + /* Write data to buffer */ + SSP_Write2BFifo(pSSP, xf_setup); + + /* Check overrun error in RIS register */ + if (Chip_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) { + return ERROR; + } + + /* Check for any data available in RX FIFO */ + SSP_Read2BFifo(pSSP, xf_setup); + } + + return SUCCESS; + } + + return ERROR; +} + +/* Set the SSP operating modes, master or slave */ +void Chip_SSP_SetMaster(LPC_SSP_T *pSSP, bool master) +{ + if (master) { + Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER); + } + else { + Chip_SSP_Set_Mode(pSSP, SSP_MODE_SLAVE); + } +} + +/* Set the clock frequency for SSP interface */ +void Chip_SSP_SetBitRate(LPC_SSP_T *pSSP, uint32_t bitRate) +{ + uint32_t ssp_clk, cr0_div, cmp_clk, prescale; + + ssp_clk = Chip_SSP_GetPCLKkRate(pSSP); + + cr0_div = 0; + cmp_clk = 0xFFFFFFFF; + prescale = 2; + + while (cmp_clk > bitRate) { + cmp_clk = ssp_clk / ((cr0_div + 1) * prescale); + if (cmp_clk > bitRate) { + cr0_div++; + if (cr0_div > 0xFF) { + cr0_div = 0; + prescale += 2; + } + } + } + + Chip_SSP_SetClockRate(pSSP, cr0_div, prescale); +} + +/* Initialize the SSP */ +void Chip_SSP_Init(LPC_SSP_T *pSSP) +{ + Chip_Clock_EnablePeriphClock(Chip_SSP_GetClockIndex(pSSP)); + Chip_SSP_SetSSPClkDivider(pSSP, 1); + Chip_SYSCTL_PeriphReset(Chip_SSP_GetResetIndex(pSSP)); + + Chip_SSP_Set_Mode(pSSP, SSP_MODE_MASTER); + Chip_SSP_SetFormat(pSSP, SSP_BITS_8, SSP_FRAMEFORMAT_SPI, SSP_CLOCK_CPHA0_CPOL0); + Chip_SSP_SetBitRate(pSSP, 100000); +} + +/* De-initializes the SSP peripheral */ +void Chip_SSP_DeInit(LPC_SSP_T *pSSP) +{ + Chip_SSP_Disable(pSSP); + + Chip_Clock_DisablePeriphClock(Chip_SSP_GetClockIndex(pSSP)); + Chip_SSP_SetSSPClkDivider(pSSP, 0); +} diff --git a/source/lpc_chip_11u6x/src/stopwatch_11u6.c b/source/lpc_chip_11u6x/src/stopwatch_11u6.c new file mode 100644 index 0000000..b6ce6cb --- /dev/null +++ b/source/lpc_chip_11u6x/src/stopwatch_11u6.c @@ -0,0 +1,106 @@ +/* + * @brief LPC11u6x specific stopwatch implementation + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" +#include "stopwatch.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Precompute these to optimize runtime */ +static uint32_t ticksPerSecond; +static uint32_t ticksPerMs; +static uint32_t ticksPerUs; + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize stopwatch */ +void StopWatch_Init(void) +{ + /* Use timer 1. Set prescaler to divide by 8 */ + const uint32_t prescaleDivisor = 8; + Chip_TIMER_Init(LPC_TIMER32_1); + Chip_TIMER_PrescaleSet(LPC_TIMER32_1, prescaleDivisor - 1); + Chip_TIMER_Enable(LPC_TIMER32_1); + + /* Pre-compute tick rate. */ + ticksPerSecond = Chip_Clock_GetSystemClockRate() / prescaleDivisor; + ticksPerMs = ticksPerSecond / 1000; + ticksPerUs = ticksPerSecond / 1000000; +} + +/* Start a stopwatch */ +uint32_t StopWatch_Start(void) +{ + /* Return the current timer count. */ + return Chip_TIMER_ReadCount(LPC_TIMER32_1); +} + +/* Returns number of ticks per second of the stopwatch timer */ +uint32_t StopWatch_TicksPerSecond(void) +{ + return ticksPerSecond; +} + +/* Converts from stopwatch ticks to mS. */ +uint32_t StopWatch_TicksToMs(uint32_t ticks) +{ + return ticks / ticksPerMs; +} + +/* Converts from stopwatch ticks to uS. */ +uint32_t StopWatch_TicksToUs(uint32_t ticks) +{ + return ticks / ticksPerUs; +} + +/* Converts from mS to stopwatch ticks. */ +uint32_t StopWatch_MsToTicks(uint32_t mS) +{ + return mS * ticksPerMs; +} + +/* Converts from uS to stopwatch ticks. */ +uint32_t StopWatch_UsToTicks(uint32_t uS) +{ + return uS * ticksPerUs; +} diff --git a/source/lpc_chip_11u6x/src/syscon_11u6x.c b/source/lpc_chip_11u6x/src/syscon_11u6x.c new file mode 100644 index 0000000..ffd122e --- /dev/null +++ b/source/lpc_chip_11u6x/src/syscon_11u6x.c @@ -0,0 +1,107 @@ +/* + * @brief LPC11U6X System Control functions + * + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* PDSLEEPCFG register mask */ +#define PDSLEEPUSEMASK 0x00000037 +#define PDSLEEPMASKTMP (SYSCTL_DEEPSLP_BOD_PD | SYSCTL_DEEPSLP_WDTOSC_PD) +#define PDSLEEPMASK ((PDSLEEPUSEMASK) &~(PDSLEEPMASKTMP)) + +/* PDWAKECFG register mask */ +#define PDWAKEUPUSEMASK 0x00000800 +#define PDWAKEUPMASKTMP 0x000025FF + +/* PDRUNCFG register mask */ +#define PDRUNCFGUSEMASK 0x0000C800 +#define PDRUNCFGMASKTMP 0x000025FF + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Setup a pin source for the pin interrupts (0-7) */ +void Chip_SYSCTL_SetPinInterrupt(uint32_t intno, uint8_t port, uint8_t pin) +{ + if (port == 0) { + /* Pins P0.1 to P0.23 only */ + LPC_SYSCTL->PINTSEL[intno] = (uint32_t) pin; + } else { + /* P1.1 to P1.31 and P2.0 to P2.7 */ + LPC_SYSCTL->PINTSEL[intno] = (uint32_t) ((port - 1) * 32 + pin + 24); + } +} + + +/* Setup deep sleep behaviour for power down */ +void Chip_SYSCTL_SetDeepSleepPD(uint32_t sleepmask) +{ + /* Update new value */ + LPC_SYSCTL->PDSLEEPCFG = PDSLEEPMASK | (sleepmask & PDSLEEPMASKTMP); +} + +/* Setup wakeup behaviour from deep sleep */ +void Chip_SYSCTL_SetWakeup(uint32_t wakeupmask) +{ + /* Update new value */ + LPC_SYSCTL->PDWAKECFG = PDWAKEUPUSEMASK | (wakeupmask & PDWAKEUPMASKTMP); +} + +/* Power down one or more blocks or peripherals */ +void Chip_SYSCTL_PowerDown(uint32_t powerdownmask) +{ + uint32_t pdrun; + + pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun |= (powerdownmask & PDRUNCFGMASKTMP); + + LPC_SYSCTL->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK); +} + +/* Power up one or more blocks or peripherals */ +void Chip_SYSCTL_PowerUp(uint32_t powerupmask) +{ + uint32_t pdrun; + + pdrun = LPC_SYSCTL->PDRUNCFG & PDRUNCFGMASKTMP; + pdrun &= ~(powerupmask & PDRUNCFGMASKTMP); + + LPC_SYSCTL->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK); +} diff --git a/source/lpc_chip_11u6x/src/sysinit_11u6x.c b/source/lpc_chip_11u6x/src/sysinit_11u6x.c new file mode 100644 index 0000000..9bdbec3 --- /dev/null +++ b/source/lpc_chip_11u6x/src/sysinit_11u6x.c @@ -0,0 +1,165 @@ +/* + * @brief LPC11u6x Chip specific SystemInit + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/* Enable this definition to use the ROM API for PLL setup */ +// #define USE_ROM_API + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Clock and PLL initialization based on the internal oscillator */ +void Chip_SetupIrcClocking(void) +{ +#if defined(USE_ROM_API) + uint32_t cmd[4], resp[2]; +#endif + + /* Turn on the IRC by clearing the power down bit */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_IRC_PD); + + /* Select the PLL input in the IRC */ + Chip_Clock_SetSystemPLLSource(SYSCTL_PLLCLKSRC_IRC); + + /* Setup FLASH access */ + Chip_FMC_SetFLASHAccess(FLASHTIM_3CLK_CPU); + +#if defined(USE_ROM_API) + /* Use ROM API for setting up PLL */ + cmd[0] = Chip_Clock_GetIntOscRate() / 1000; /* in KHz */ + cmd[1] = 48000000 / 1000; /* 48MHz system clock rate */ + cmd[2] = CPU_FREQ_EQU; + cmd[3] = 48000000 / 10000; /* Timeout */ + LPC_PWRD_API->set_pll(cmd, resp); + + /* Dead loop on fail */ + while (resp[0] != PLL_CMD_SUCCESS) {} +#else + /* Power down PLL to change the PLL divider ratio */ + Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_SYSPLL_PD); + + /* Configure the PLL M and P dividers */ + /* Setup PLL for main oscillator rate (FCLKIN = 12MHz) * 4 = 48MHz + MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2) + FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz + FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */ + Chip_Clock_SetupSystemPLL(3, 1); + + /* Turn on the PLL by clearing the power down bit */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_SYSPLL_PD); + + /* Wait for PLL to lock */ + while (!Chip_Clock_IsSystemPLLLocked()) {} + + /* Set system clock divider to 1 */ + Chip_Clock_SetSysClockDiv(1); + + /* Set main clock source to the system PLL. This will drive 24MHz + for the main clock and 24MHz for the system clock */ + Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT); +#endif +} + +/* Clock and PLL initialization based on the external oscillator */ +void Chip_SetupXtalClocking(void) +{ + volatile int i; +#if defined(USE_ROM_API) + uint32_t cmd[4], resp[2]; +#endif + + /* Powerup main oscillator */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_SYSOSC_PD); + + /* Wait for at least 580uS for osc to stabilize */ + for (i = 0; i < 2500; i++) {} + + /* Set system PLL input to main oscillator */ + Chip_Clock_SetSystemPLLSource(SYSCTL_PLLCLKSRC_MAINOSC); + + /* Setup FLASH access to 3 clocks */ + Chip_FMC_SetFLASHAccess(FLASHTIM_3CLK_CPU); + +#if defined(USE_ROM_API) + /* Use ROM API for setting up PLL */ + cmd[0] = Chip_Clock_GetMainOscRate() / 1000; /* in KHz */ + cmd[1] = 48000000 / 1000; /* 48MHz system clock rate */ + cmd[2] = CPU_FREQ_EQU; + cmd[3] = 48000000 / 10000; /* Timeout */ + LPC_PWRD_API->set_pll(cmd, resp); + + /* Dead loop on fail */ + while (resp[0] != PLL_CMD_SUCCESS) {} +#else + /* Power down PLL to change the PLL divider ratio */ + Chip_SYSCTL_PowerDown(SYSCTL_POWERDOWN_SYSPLL_PD); + + /* Setup PLL for main oscillator rate (FCLKIN = 12MHz) * 4 = 48MHz + MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2) + FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz + FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */ + Chip_Clock_SetupSystemPLL(3, 1); + + /* Powerup system PLL */ + Chip_SYSCTL_PowerUp(SYSCTL_POWERDOWN_SYSPLL_PD); + + /* Wait for PLL to lock */ + while (!Chip_Clock_IsSystemPLLLocked()) {} + + /* Set system clock divider to 1 */ + Chip_Clock_SetSysClockDiv(1); + + /* Set main clock source to the system PLL. This will drive 48MHz + for the main clock and 48MHz for the system clock */ + Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_PLLOUT); +#endif +} + +/* Set up and initialize hardware prior to call to main */ +void Chip_SystemInit(void) +{ + /* Initial internal clocking */ + Chip_SetupIrcClocking(); +} diff --git a/source/lpc_chip_11u6x/src/timer_11u6x.c b/source/lpc_chip_11u6x/src/timer_11u6x.c new file mode 100644 index 0000000..4e35082 --- /dev/null +++ b/source/lpc_chip_11u6x/src/timer_11u6x.c @@ -0,0 +1,115 @@ +/* + * @brief LPC11u6x 16/32-bit Timer/PWM control functions + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Returns clock index for a specific timer referenced by IP block address */ +STATIC CHIP_SYSCTL_CLOCK_T Chip_TIMER_GetClock(LPC_TIMER_T *pTMR) +{ + CHIP_SYSCTL_CLOCK_T tmrClk; + if (pTMR == LPC_TIMER32_1) { + tmrClk = SYSCTL_CLOCK_CT32B1; + } + else if (pTMR == LPC_TIMER16_0) { + tmrClk = SYSCTL_CLOCK_CT16B0; + } + else if (pTMR == LPC_TIMER16_1) { + tmrClk = SYSCTL_CLOCK_CT16B1; + } + else { + tmrClk = SYSCTL_CLOCK_CT32B0; + } + + return tmrClk; +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize a timer */ +void Chip_TIMER_Init(LPC_TIMER_T *pTMR) +{ + Chip_Clock_EnablePeriphClock(Chip_TIMER_GetClock(pTMR)); +} + +/* Shutdown a timer */ +void Chip_TIMER_DeInit(LPC_TIMER_T *pTMR) +{ + Chip_Clock_DisablePeriphClock(Chip_TIMER_GetClock(pTMR)); +} + +/* Resets the timer terminal and prescale counts to 0 */ +void Chip_TIMER_Reset(LPC_TIMER_T *pTMR) +{ + uint32_t reg; + + /* Disable timer, set terminal count to non-0 */ + reg = pTMR->TCR; + pTMR->TCR = 0; + pTMR->TC = 1; + + /* Reset timer counter */ + pTMR->TCR = TIMER_RESET; + + /* Wait for terminal count to clear */ + while (pTMR->TC != 0) {} + + /* Restore timer state */ + pTMR->TCR = reg; +} + +/* Sets external match control (MATn.matchnum) pin control */ +void Chip_TIMER_ExtMatchControlSet(LPC_TIMER_T *pTMR, int8_t initial_state, + TIMER_PIN_MATCH_STATE_T matchState, int8_t matchnum) +{ + uint32_t mask, reg; + + /* Clear bits corresponding to selected match register */ + mask = (1 << matchnum) | (0x03 << (4 + (matchnum * 2))); + reg = pTMR->EMR &= ~mask; + + /* Set new configuration for selected match register */ + pTMR->EMR = reg | (((uint32_t) initial_state) << matchnum) | + (((uint32_t) matchState) << (4 + (matchnum * 2))); +} diff --git a/source/lpc_chip_11u6x/src/uart_0_11u6x.c b/source/lpc_chip_11u6x/src/uart_0_11u6x.c new file mode 100644 index 0000000..9c89cd9 --- /dev/null +++ b/source/lpc_chip_11u6x/src/uart_0_11u6x.c @@ -0,0 +1,283 @@ +/* + * @brief LPC11u6x USART0 chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initializes the pUART peripheral */ +void Chip_UART0_Init(LPC_USART0_T *pUART) +{ + /* A USART 0 divider of 1 is used with this driver */ + Chip_Clock_SetUSART0ClockDiv(1); + + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_UART0); + + /* Enable FIFOs by default, reset them */ + Chip_UART0_SetupFIFOS(pUART, (UART0_FCR_FIFO_EN | UART0_FCR_RX_RS | UART0_FCR_TX_RS)); + + /* Disable fractional divider */ + pUART->FDR = 0x10; +} + +/* De-initializes the pUART peripheral */ +void Chip_UART0_DeInit(LPC_USART0_T *pUART) +{ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_UART0); +} + +/* Transmit a byte array through the UART peripheral (non-blocking) */ +int Chip_UART0_Send(LPC_USART0_T *pUART, const void *data, int numBytes) +{ + int sent = 0; + uint8_t *p8 = (uint8_t *) data; + + /* Send until the transmit FIFO is full or out of bytes */ + while ((sent < numBytes) && + ((Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_THRE) != 0)) { + Chip_UART0_SendByte(pUART, *p8); + p8++; + sent++; + } + + return sent; +} + +/* Transmit a byte array through the UART peripheral (blocking) */ +int Chip_UART0_SendBlocking(LPC_USART0_T *pUART, const void *data, int numBytes) +{ + int pass, sent = 0; + uint8_t *p8 = (uint8_t *) data; + + while (numBytes > 0) { + pass = Chip_UART0_Send(pUART, p8, numBytes); + numBytes -= pass; + sent += pass; + p8 += pass; + } + + return sent; +} + +/* Read data through the UART peripheral (non-blocking) */ +int Chip_UART0_Read(LPC_USART0_T *pUART, void *data, int numBytes) +{ + int readBytes = 0; + uint8_t *p8 = (uint8_t *) data; + + /* Send until the transmit FIFO is full or out of bytes */ + while ((readBytes < numBytes) && + ((Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_RDR) != 0)) { + *p8 = Chip_UART0_ReadByte(pUART); + p8++; + readBytes++; + } + + return readBytes; +} + +/* Read data through the UART peripheral (blocking) */ +int Chip_UART0_ReadBlocking(LPC_USART0_T *pUART, void *data, int numBytes) +{ + int pass, readBytes = 0; + uint8_t *p8 = (uint8_t *) data; + + while (numBytes > 0) { + pass = Chip_UART0_Read(pUART, p8, numBytes); + numBytes -= pass; + readBytes += pass; + p8 += pass; + } + + return readBytes; +} + +/* Determines and sets best dividers to get a target bit rate */ +uint32_t Chip_UART0_SetBaud(LPC_USART0_T *pUART, uint32_t baudrate) +{ + uint32_t div, divh, divl, clkin; + + /* USART clock input divider of 1 */ + Chip_Clock_SetUSART0ClockDiv(1); + + /* Determine UART clock in rate without FDR */ + clkin = Chip_Clock_GetMainClockRate(); + div = clkin / (baudrate * 16); + + /* High and low halves of the divider */ + divh = div / 256; + divl = div - (divh * 256); + + Chip_UART0_EnableDivisorAccess(pUART); + Chip_UART0_SetDivisorLatches(pUART, divl, divh); + Chip_UART0_DisableDivisorAccess(pUART); + + /* Fractional FDR already setup for 1 in UART init */ + + return clkin / (div * 16); +} + +/* UART receive-only interrupt handler for ring buffers */ +void Chip_UART0_RXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB) +{ + /* New data will be ignored if data not popped in time */ + while (Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_RDR) { + uint8_t ch = Chip_UART0_ReadByte(pUART); + RingBuffer_Insert(pRB, &ch); + } +} + +/* UART transmit-only interrupt handler for ring buffers */ +void Chip_UART0_TXIntHandlerRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB) +{ + uint8_t ch; + + /* Fill FIFO until full or until TX ring buffer is empty */ + while ((Chip_UART0_ReadLineStatus(pUART) & UART0_LSR_THRE) != 0 && + RingBuffer_Pop(pRB, &ch)) { + Chip_UART0_SendByte(pUART, ch); + } +} + +/* Populate a transmit ring buffer and start UART transmit */ +uint32_t Chip_UART0_SendRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, const void *data, int bytes) +{ + uint32_t ret; + uint8_t *p8 = (uint8_t *) data; + + /* Don't let UART transmit ring buffer change in the UART IRQ handler */ + Chip_UART0_IntDisable(pUART, UART0_IER_THREINT); + + /* Move as much data as possible into transmit ring buffer */ + ret = RingBuffer_InsertMult(pRB, p8, bytes); + Chip_UART0_TXIntHandlerRB(pUART, pRB); + + /* Add additional data to transmit ring buffer if possible */ + ret += RingBuffer_InsertMult(pRB, (p8 + ret), (bytes - ret)); + + /* Enable UART transmit interrupt */ + Chip_UART0_IntEnable(pUART, UART0_IER_THREINT); + + return ret; +} + +/* Copy data from a receive ring buffer */ +int Chip_UART0_ReadRB(LPC_USART0_T *pUART, RINGBUFF_T *pRB, void *data, int bytes) +{ + (void) pUART; + + return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes); +} + +/* UART receive/transmit interrupt handler for ring buffers */ +void Chip_UART0_IRQRBHandler(LPC_USART0_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB) +{ + /* Handle transmit interrupt if enabled */ + if (pUART->IER & UART0_IER_THREINT) { + Chip_UART0_TXIntHandlerRB(pUART, pTXRB); + + /* Disable transmit interrupt if the ring buffer is empty */ + if (RingBuffer_IsEmpty(pTXRB)) { + Chip_UART0_IntDisable(pUART, UART0_IER_THREINT); + } + } + + /* Handle receive interrupt */ + Chip_UART0_RXIntHandlerRB(pUART, pRXRB); +} + +/* Determines and sets best dividers to get a target baud rate */ +uint32_t Chip_UART0_SetBaudFDR(LPC_USART0_T *pUART, uint32_t baudrate) + +{ + uint32_t uClk; + uint32_t dval, mval; + uint32_t dl; + uint32_t rate16 = 16 * baudrate; + uint32_t actualRate = 0; + + /* Get Clock rate */ + uClk = Chip_Clock_GetMainClockRate(); + + /* The fractional is calculated as (PCLK % (16 * Baudrate)) / (16 * Baudrate) + * Let's make it to be the ratio DivVal / MulVal + */ + dval = uClk % rate16; + + /* The PCLK / (16 * Baudrate) is fractional + * => dval = pclk % rate16 + * mval = rate16; + * now mormalize the ratio + * dval / mval = 1 / new_mval + * new_mval = mval / dval + * new_dval = 1 + */ + if (dval > 0) { + mval = rate16 / dval; + dval = 1; + + /* In case mval still bigger then 4 bits + * no adjustment require + */ + if (mval > 12) { + dval = 0; + } + } + dval &= 0xf; + mval &= 0xf; + dl = uClk / (rate16 + rate16 * dval / mval); + + /* Update UART registers */ + Chip_UART0_EnableDivisorAccess(pUART); + Chip_UART0_SetDivisorLatches(pUART, UART0_LOAD_DLL(dl), UART0_LOAD_DLM(dl)); + Chip_UART0_DisableDivisorAccess(pUART); + + /* Set best fractional divider */ + pUART->FDR = (UART0_FDR_MULVAL(mval) | UART0_FDR_DIVADDVAL(dval)); + + /* Return actual baud rate */ + actualRate = uClk / (16 * dl + 16 * dl * dval / mval); + return actualRate; +} diff --git a/source/lpc_chip_11u6x/src/uart_n_11u6x.c b/source/lpc_chip_11u6x/src/uart_n_11u6x.c new file mode 100644 index 0000000..990325e --- /dev/null +++ b/source/lpc_chip_11u6x/src/uart_n_11u6x.c @@ -0,0 +1,280 @@ +/* + * @brief LPC11u6xx USART0 driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licenser disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/* Counts instances of UART3 and 4 init calls for shared clock handling */ +static uint8_t uart_3_4_cnt; + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/* Return UART clock ID from the UART register address */ +static CHIP_SYSCTL_CLOCK_T getUARTClockID(LPC_USARTN_T *pUART) +{ + if (pUART == LPC_USART1) { + return SYSCTL_CLOCK_USART1; + } + else if (pUART == LPC_USART2) { + return SYSCTL_CLOCK_USART2; + } + + return SYSCTL_CLOCK_USART3_4; +} + +/* UART clock enable */ +static void Chip_UARTN_EnableClock(LPC_USARTN_T *pUART) +{ + CHIP_SYSCTL_CLOCK_T clk = getUARTClockID(pUART); + + /* Special handling for shared UART 3/4 clock */ + if (clk == SYSCTL_CLOCK_USART3_4) { + /* Does not handle unbalanced Init() and DeInit() calls */ + uart_3_4_cnt++; + } + + Chip_Clock_EnablePeriphClock(clk); +} + +/* UART clock disable */ +static void Chip_UARTN_DisableClock(LPC_USARTN_T *pUART) +{ + CHIP_SYSCTL_CLOCK_T clk = getUARTClockID(pUART); + + /* Special handling for shared UART 3/4 clock */ + if (clk != SYSCTL_CLOCK_USART3_4) { + Chip_Clock_DisablePeriphClock(clk); + } + else { + /* Does not handle unbalanced Init() and DeInit() calls */ + uart_3_4_cnt--; + if (uart_3_4_cnt == 0) { + Chip_Clock_DisablePeriphClock(clk); + } + } +} + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize the UART peripheral */ +void Chip_UARTN_Init(LPC_USARTN_T *pUART) +{ + CHIP_SYSCTL_PERIPH_RESET_T resetID; + + /* Enable USART clock */ + Chip_UARTN_EnableClock(pUART); + + /* Select UART reset */ + if (pUART == LPC_USART1) { + resetID = RESET_USART1; + } + else if (pUART == LPC_USART2) { + resetID = RESET_USART2; + } + else if (pUART == LPC_USART3) { + resetID = RESET_USART3; + } + else { + resetID = RESET_USART4; + } + + Chip_SYSCTL_PeriphReset(resetID); +} + +/* Initialize the UART peripheral */ +void Chip_UARTN_DeInit(LPC_USARTN_T *pUART) +{ + /* Disable USART clock */ + Chip_UARTN_DisableClock(pUART); +} + +/* Transmit a byte array through the UART peripheral (non-blocking) */ +int Chip_UARTN_Send(LPC_USARTN_T *pUART, const void *data, int numBytes) +{ + int sent = 0; + uint8_t *p8 = (uint8_t *) data; + + /* Send until the transmit FIFO is full or out of bytes */ + while ((sent < numBytes) && + ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_TXRDY) != 0)) { + Chip_UARTN_SendByte(pUART, *p8); + p8++; + sent++; + } + + return sent; +} + +/* Transmit a byte array through the UART peripheral (blocking) */ +int Chip_UARTN_SendBlocking(LPC_USARTN_T *pUART, const void *data, int numBytes) +{ + int pass, sent = 0; + uint8_t *p8 = (uint8_t *) data; + + while (numBytes > 0) { + pass = Chip_UARTN_Send(pUART, p8, numBytes); + numBytes -= pass; + sent += pass; + p8 += pass; + } + + return sent; +} + +/* Read data through the UART peripheral (non-blocking) */ +int Chip_UARTN_Read(LPC_USARTN_T *pUART, void *data, int numBytes) +{ + int readBytes = 0; + uint8_t *p8 = (uint8_t *) data; + + /* Send until the transmit FIFO is full or out of bytes */ + while ((readBytes < numBytes) && + ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_RXRDY) != 0)) { + *p8 = Chip_UARTN_ReadByte(pUART); + p8++; + readBytes++; + } + + return readBytes; +} + +/* Read data through the UART peripheral (blocking) */ +int Chip_UARTN_ReadBlocking(LPC_USARTN_T *pUART, void *data, int numBytes) +{ + int pass, readBytes = 0; + uint8_t *p8 = (uint8_t *) data; + + while (readBytes < numBytes) { + pass = Chip_UARTN_Read(pUART, p8, numBytes); + numBytes -= pass; + readBytes += pass; + p8 += pass; + } + + return readBytes; +} + +/* Set baud rate for UART */ +void Chip_UARTN_SetBaud(LPC_USARTN_T *pUART, uint32_t baudrate) +{ + uint32_t baudRateGenerator; + baudRateGenerator = Chip_Clock_GetUSARTNBaseClockRate() / (16 * baudrate); + pUART->BRG = baudRateGenerator - 1; /* baud rate */ +} + +/* Set baud rate for UART using RTC32K oscillator */ +void Chip_UARTN_SetBaudWithRTC32K(LPC_USARTN_T *pUART, uint32_t baudrate) +{ + /* Simple integer divide. 9600 is maximum baud rate. */ + pUART->BRG = (9600 / baudrate) - 1; + + pUART->CFG |= UARTN_MODE_32K; +} + +/* UART receive-only interrupt handler for ring buffers */ +void Chip_UARTN_RXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB) +{ + /* New data will be ignored if data not popped in time */ + while ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_RXRDY) != 0) { + uint8_t ch = Chip_UARTN_ReadByte(pUART); + RingBuffer_Insert(pRB, &ch); + } +} + +/* UART transmit-only interrupt handler for ring buffers */ +void Chip_UARTN_TXIntHandlerRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB) +{ + uint8_t ch; + + /* Fill FIFO until full or until TX ring buffer is empty */ + while (((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_TXRDY) != 0) && + RingBuffer_Pop(pRB, &ch)) { + Chip_UARTN_SendByte(pUART, ch); + } +} + +/* Populate a transmit ring buffer and start UART transmit */ +uint32_t Chip_UARTN_SendRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, const void *data, int count) +{ + uint32_t ret; + uint8_t *p8 = (uint8_t *) data; + + /* Don't let UART transmit ring buffer change in the UART IRQ handler */ + Chip_UARTN_IntDisable(pUART, UARTN_INTEN_TXRDY); + + /* Move as much data as possible into transmit ring buffer */ + ret = RingBuffer_InsertMult(pRB, p8, count); + Chip_UARTN_TXIntHandlerRB(pUART, pRB); + + /* Add additional data to transmit ring buffer if possible */ + ret += RingBuffer_InsertMult(pRB, (p8 + ret), (count - ret)); + + /* Enable UART transmit interrupt */ + Chip_UARTN_IntEnable(pUART, UARTN_INTEN_TXRDY); + + return ret; +} + +/* Copy data from a receive ring buffer */ +int Chip_UARTN_ReadRB(LPC_USARTN_T *pUART, RINGBUFF_T *pRB, void *data, int bytes) +{ + (void) pUART; + + return RingBuffer_PopMult(pRB, (uint8_t *) data, bytes); +} + +/* UART receive/transmit interrupt handler for ring buffers */ +void Chip_UARTN_IRQRBHandler(LPC_USARTN_T *pUART, RINGBUFF_T *pRXRB, RINGBUFF_T *pTXRB) +{ + /* Handle transmit interrupt if enabled */ + if ((Chip_UARTN_GetStatus(pUART) & UARTN_STAT_TXRDY) != 0) { + Chip_UARTN_TXIntHandlerRB(pUART, pTXRB); + + /* Disable transmit interrupt if the ring buffer is empty */ + if (RingBuffer_IsEmpty(pTXRB)) { + Chip_UARTN_IntDisable(pUART, UARTN_INTEN_TXRDY); + } + } + + /* Handle receive interrupt */ + Chip_UARTN_RXIntHandlerRB(pUART, pRXRB); +} diff --git a/source/lpc_chip_11u6x/src/wwdt_11u6x.c b/source/lpc_chip_11u6x/src/wwdt_11u6x.c new file mode 100644 index 0000000..6ccb09e --- /dev/null +++ b/source/lpc_chip_11u6x/src/wwdt_11u6x.c @@ -0,0 +1,78 @@ +/* + * @brief LPC11u6x WWDT chip driver + * + * @note + * Copyright(C) NXP Semiconductors, 2013 + * All rights reserved. + * + * @par + * Software that is described herein is for illustrative purposes only + * which provides customers with programming information regarding the + * LPC products. This software is supplied "AS IS" without any warranties of + * any kind, and NXP Semiconductors and its licensor disclaim any and + * all warranties, express or implied, including all implied warranties of + * merchantability, fitness for a particular purpose and non-infringement of + * intellectual property rights. NXP Semiconductors assumes no responsibility + * or liability for the use of the software, conveys no license or rights under any + * patent, copyright, mask work right, or any other intellectual property rights in + * or to any products. NXP Semiconductors reserves the right to make changes + * in the software without notification. NXP Semiconductors also makes no + * representation or warranty that such application will be suitable for the + * specified use without further testing or modification. + * + * @par + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, under NXP Semiconductors' and its + * licensor's relevant copyrights in the software, without fee, provided that it + * is used in conjunction with NXP Semiconductors microcontrollers. This + * copyright, permission, and disclaimer notice must appear in all copies of + * this code. + */ + +#include "chip.h" + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Initialize the Watchdog timer */ +void Chip_WWDT_Init(LPC_WWDT_T *pWWDT) +{ + Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_WDT); + + /* Disable watchdog */ + pWWDT->MOD = 0; + pWWDT->TC = 0xFF; + pWWDT->WARNINT = 0x3FF; + pWWDT->WINDOW = 0xFFFFFF; +} + +/* Shutdown the Watchdog timer */ +void Chip_WWDT_DeInit(LPC_WWDT_T *pWWDT) +{ + Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_WDT); +} + +/* Clear WWDT interrupt status flags */ +void Chip_WWDT_ClearStatusFlag(LPC_WWDT_T *pWWDT, uint32_t status) +{ + if (status & WWDT_WDMOD_WDTOF) { + pWWDT->MOD &= (~WWDT_WDMOD_WDTOF) & WWDT_WDMOD_BITMASK; + } + + if (status & WWDT_WDMOD_WDINT) { + pWWDT->MOD |= WWDT_WDMOD_WDINT; + } +} diff --git a/source/test/.cproject b/source/test/.cproject new file mode 100644 index 0000000..ff59d90 --- /dev/null +++ b/source/test/.cproject @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <?xml version="1.0" encoding="UTF-8"?> +<TargetConfig> +<Properties property_2="LPC11U6x_256K.cfx" property_3="NXP" property_4="LPC11U68" property_count="5" version="100300"/> +<infoList vendor="NXP"> +<info chip="LPC11U68" flash_driver="LPC11U6x_256K.cfx" match_id="0x0" name="LPC11U68" stub="crt_emu_cm3_gen"> +<chip> +<name>LPC11U68</name> +<family>LPC11U6x</family> +<vendor>NXP (formerly Philips)</vendor> +<reset board="None" core="Real" sys="Real"/> +<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/> +<memory can_program="true" id="Flash" is_ro="true" type="Flash"/> +<memory id="RAM" type="RAM"/> +<memory id="Periph" is_volatile="true" type="Peripheral"/> +<memoryInstance derived_from="Flash" id="MFlash256" location="0x0" size="0x40000"/> +<memoryInstance derived_from="RAM" id="Ram0_32" location="0x10000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="Ram1_2" location="0x20000000" size="0x800"/> +<memoryInstance derived_from="RAM" id="Ram2USB_2" location="0x20004000" size="0x800"/> +</chip> +<processor> +<name gcc_name="cortex-m0">Cortex-M0</name> +<family>Cortex-M</family> +</processor> +</info> +</infoList> +</TargetConfig> + + + LPCXpresso11U68 + + \ No newline at end of file diff --git a/source/test/.project b/source/test/.project new file mode 100644 index 0000000..76b91cc --- /dev/null +++ b/source/test/.project @@ -0,0 +1,29 @@ + + + test + + + lpc_board_nxp_lpcxpresso_11u68 + lpc_chip_11u6x + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/source/test/.settings/language.settings.xml b/source/test/.settings/language.settings.xml new file mode 100644 index 0000000..ae948ae --- /dev/null +++ b/source/test/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/test/src/aeabi_romdiv_patch.s b/source/test/src/aeabi_romdiv_patch.s new file mode 100644 index 0000000..549630c --- /dev/null +++ b/source/test/src/aeabi_romdiv_patch.s @@ -0,0 +1,82 @@ +//***************************************************************************** +// aeabi_romdiv_patch.s +// - Provides "patch" versions of the aeabi integer divide functions to +// replace the standard ones pulled in from the C library, which vector +// integer divides onto the rom division functions contained in +// specific NXP MCUs such as LPC8xx, LPC11Uxx and LPC12xx. +// - Note that this patching will only occur if "__USE_ROMDIVIDE" is +// defined for the project build for both the compiler and assembler. +//***************************************************************************** +// +// Copyright 2013-2017, 2019, 2020 NXP +// All rights reserved. +// +// NXP Confidential. This software is owned or controlled by NXP and may only be +// used strictly in accordance with the applicable license terms. +// +// By expressly accepting such terms or by downloading, installing, activating +// and/or otherwise using the software, you are agreeing that you have read, and +// that you agree to comply with and are bound by, such license terms. +// +// If you do not agree to be bound by the applicable license terms, then you may not +// retain, install, activate or otherwise use the software. +//***************************************************************************** +#if defined(__USE_ROMDIVIDE) + +// Note that the romdivide "divmod" functions are not actually called from +// the below code, as these functions are actually just wrappers to the +// main romdivide "div" functions which push the quotient and remainder onto +// the stack, so as to be compatible with the way that C returns structures. +// +// This is not needed for the aeabi "divmod" functions, as the compiler +// automatically generates code that handles the return values being passed +// back in registers when it generates inline calls to __aeabi_idivmod and +// __aeabi_uidivmod routines. + + .syntax unified + .text + +// ========= __aeabi_idiv & __aeabi_idivmod ========= + .align 2 + .section .text.__aeabi_idiv + + .global __aeabi_idiv + .set __aeabi_idivmod, __aeabi_idiv // make __aeabi_uidivmod an alias + .global __aeabi_idivmod + .global pDivRom_idiv // pointer to the romdivide 'idiv' functione + .func + .thumb_func + .type __aeabi_idiv, %function + +__aeabi_idiv: + push {r4, lr} + ldr r3, =pDivRom_idiv + ldr r3, [r3, #0] // Load address of function + blx r3 // Call divide function + pop {r4, pc} + + .endfunc + +// ======== __aeabi_uidiv & __aeabi_uidivmod ======== + .align 2 + + .section .text.__aeabi_uidiv + + .global __aeabi_uidiv + .set __aeabi_uidivmod, __aeabi_uidiv // make __aeabi_uidivmod an alias + .global __aeabi_uidivmod + .global pDivRom_uidiv // pointer to the romdivide 'uidiv' function + .func + .thumb_func + .type __aeabi_uidiv, %function + +__aeabi_uidiv: + push {r4, lr} + ldr r3, =pDivRom_uidiv + ldr r3, [r3, #0] // Load address of function + blx r3 // Call divide function + pop {r4, pc} + + .endfunc + +#endif // (__USE_ROMDIVIDE) diff --git a/source/test/src/cr_cpp_config.cpp b/source/test/src/cr_cpp_config.cpp new file mode 100644 index 0000000..ba7308e --- /dev/null +++ b/source/test/src/cr_cpp_config.cpp @@ -0,0 +1,91 @@ +//***************************************************************************** +// +--+ +// | ++----+ +// +-++ | +// | | +// +-+--+ | +// | +--+--+ +// +----+ Copyright (c) 2009-2012 Code Red Technologies Ltd. +// +----+ Copyright 2013, 2019 NXP +// +// Minimal implementations of the new/delete operators and the verbose +// terminate handler for exceptions suitable for embedded use, +// plus optional "null" stubs for malloc/free (only used if symbol +// CPP_NO_HEAP is defined). +// +// +// Version : 120126 +// +// Software License Agreement +// +// The software is owned by Code Red Technologies and/or its suppliers, and is +// protected under applicable copyright laws. All rights are reserved. Any +// use in violation of the foregoing restrictions may subject the user to criminal +// sanctions under applicable laws, as well as to civil liability for the breach +// of the terms and conditions of this license. +// +// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT +// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH +// CODE RED TECHNOLOGIES LTD. +// +//***************************************************************************** + +#include + +void *operator new(size_t size) +{ + return malloc(size); +} + +void *operator new[](size_t size) +{ + return malloc(size); +} + +void operator delete(void *p) +{ + free(p); +} + +void operator delete[](void *p) +{ + free(p); +} + +extern "C" int __aeabi_atexit(void *object, + void (*destructor)(void *), + void *dso_handle) +{ + return 0; +} + +#ifdef CPP_NO_HEAP +extern "C" void *malloc(size_t) { + return (void *)0; +} + +extern "C" void free(void *) { +} +#endif + +#ifndef CPP_USE_CPPLIBRARY_TERMINATE_HANDLER +/****************************************************************** + * __verbose_terminate_handler() + * + * This is the function that is called when an uncaught C++ + * exception is encountered. The default version within the C++ + * library prints the name of the uncaught exception, but to do so + * it must demangle its name - which causes a large amount of code + * to be pulled in. The below minimal implementation can reduce + * code size noticeably. Note that this function should not return. + ******************************************************************/ +namespace __gnu_cxx { +void __verbose_terminate_handler() +{ + while(1); +} +} +#endif diff --git a/source/test/src/cr_startup_lpc11u6x.cpp b/source/test/src/cr_startup_lpc11u6x.cpp new file mode 100644 index 0000000..36c4588 --- /dev/null +++ b/source/test/src/cr_startup_lpc11u6x.cpp @@ -0,0 +1,348 @@ +//***************************************************************************** +// LPC11U6x Microcontroller Startup code for use with LPCXpresso IDE +// +// Version : 150706 +//***************************************************************************** +// +// Copyright(C) NXP Semiconductors, 2014-2015, 2020 +// All rights reserved. +// +// NXP Confidential. This software is owned or controlled by NXP and may only be +// used strictly in accordance with the applicable license terms. +// +// By expressly accepting such terms or by downloading, installing, activating +// and/or otherwise using the software, you are agreeing that you have read, and +// that you agree to comply with and are bound by, such license terms. +// +// If you do not agree to be bound by the applicable license terms, then you may not +// retain, install, activate or otherwise use the software. +//***************************************************************************** + +#if defined (__cplusplus) +#ifdef __REDLIB__ +#error Redlib does not support C++ +#else +//***************************************************************************** +// +// The entry point for the C++ library startup +// +//***************************************************************************** +extern "C" { + extern void __libc_init_array(void); +} +#endif +#endif + +#define WEAK __attribute__ ((weak)) +#define ALIAS(f) __attribute__ ((weak, alias (#f))) + +//***************************************************************************** +#if defined (__cplusplus) +extern "C" { +#endif + +//***************************************************************************** +#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN) +// Declaration of external SystemInit function +extern void SystemInit(void); +#endif + +// Patch the AEABI integer divide functions to use MCU's romdivide library +#ifdef __USE_ROMDIVIDE +// Location in memory that holds the address of the ROM Driver table +#define PTR_ROM_DRIVER_TABLE ((unsigned int *)(0x1FFF1FF8)) +// Variables to store addresses of idiv and udiv functions within MCU ROM +unsigned int *pDivRom_idiv; +unsigned int *pDivRom_uidiv; +#endif + +//***************************************************************************** +// +// Forward declaration of the default handlers. These are aliased. +// When the application defines a handler (with the same name), this will +// automatically take precedence over these weak definitions +// +//***************************************************************************** + void ResetISR(void); +WEAK void NMI_Handler(void); +WEAK void HardFault_Handler(void); +WEAK void SVC_Handler(void); +WEAK void PendSV_Handler(void); +WEAK void SysTick_Handler(void); +WEAK void IntDefaultHandler(void); +//***************************************************************************** +// +// Forward declaration of the specific IRQ handlers. These are aliased +// to the IntDefaultHandler, which is a 'forever' loop. When the application +// defines a handler (with the same name), this will automatically take +// precedence over these weak definitions +// +//***************************************************************************** +void PIN_INT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT2_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT3_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT4_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT5_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT6_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIN_INT7_IRQHandler (void) ALIAS(IntDefaultHandler); +void GINT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void GINT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void I2C1_IRQHandler (void) ALIAS(IntDefaultHandler); +void USART1_4_IRQHandler (void) ALIAS(IntDefaultHandler); +void USART2_3_IRQHandler (void) ALIAS(IntDefaultHandler); +void SCT0_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP1_IRQHandler (void) ALIAS(IntDefaultHandler); +void I2C0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP0_IRQHandler (void) ALIAS(IntDefaultHandler); +void USART0_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_FIQHandler (void) ALIAS(IntDefaultHandler); +void ADCA_IRQHandler (void) ALIAS(IntDefaultHandler); +void RTC_IRQHandler (void) ALIAS(IntDefaultHandler); +void BOD_WDT_IRQHandler (void) ALIAS(IntDefaultHandler); +void FMC_IRQHandler (void) ALIAS(IntDefaultHandler); +void DMA_IRQHandler (void) ALIAS(IntDefaultHandler); +void ADCB_IRQHandler (void) ALIAS(IntDefaultHandler); +void USBWakeup_IRQHandler (void) ALIAS(IntDefaultHandler); + +//***************************************************************************** +// The entry point for the application. +// __main() is the entry point for redlib based applications +// main() is the entry point for newlib based applications +//***************************************************************************** +#if defined (__REDLIB__) +extern void __main(void); +#endif +extern int main(void); +//***************************************************************************** +// +// External declaration for the pointer to the stack top from the Linker Script +// +//***************************************************************************** +extern void _vStackTop(void); + +//***************************************************************************** +// +// External declaration for LPC MCU vector table checksum from Linker Script +// +//***************************************************************************** +WEAK extern void __valid_user_code_checksum(); + +//***************************************************************************** +#if defined (__cplusplus) +} // extern "C" +#endif +//***************************************************************************** +// +// The vector table. Note that the proper constructs must be placed on this to +// ensure that it ends up at physical address 0x0000.0000. +// +//***************************************************************************** +extern void (* const g_pfnVectors[])(void); +__attribute__ ((used,section(".isr_vector"))) +void (* const g_pfnVectors[])(void) = { + &_vStackTop, // The initial stack pointer + ResetISR, // The reset handler + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + __valid_user_code_checksum, // LPC MCU Checksum + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler + 0, // Reserved + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler + + // LPC11U6x specific handlers + PIN_INT0_IRQHandler, // 0 - GPIO pin interrupt 0 + PIN_INT1_IRQHandler, // 1 - GPIO pin interrupt 1 + PIN_INT2_IRQHandler, // 2 - GPIO pin interrupt 2 + PIN_INT3_IRQHandler, // 3 - GPIO pin interrupt 3 + PIN_INT4_IRQHandler, // 4 - GPIO pin interrupt 4 + PIN_INT5_IRQHandler, // 5 - GPIO pin interrupt 5 + PIN_INT6_IRQHandler, // 6 - GPIO pin interrupt 6 + PIN_INT7_IRQHandler, // 7 - GPIO pin interrupt 7 + GINT0_IRQHandler, // 8 - GPIO GROUP0 interrupt + GINT1_IRQHandler, // 9 - GPIO GROUP1 interrupt + I2C1_IRQHandler, // 10 - I2C1 + USART1_4_IRQHandler, // 11 - combined USART1 & 4 interrupt + USART2_3_IRQHandler, // 12 - combined USART2 & 3 interrupt + SCT0_1_IRQHandler, // 13 - combined SCT0 and 1 interrupt + SSP1_IRQHandler, // 14 - SPI/SSP1 Interrupt + I2C0_IRQHandler, // 15 - I2C0 + TIMER16_0_IRQHandler, // 16 - CT16B0 (16-bit Timer 0) + TIMER16_1_IRQHandler, // 17 - CT16B1 (16-bit Timer 1) + TIMER32_0_IRQHandler, // 18 - CT32B0 (32-bit Timer 0) + TIMER32_1_IRQHandler, // 19 - CT32B1 (32-bit Timer 1) + SSP0_IRQHandler, // 20 - SPI/SSP0 Interrupt + USART0_IRQHandler, // 21 - USART0 + USB_IRQHandler, // 22 - USB IRQ + USB_FIQHandler, // 23 - USB FIQ + ADCA_IRQHandler, // 24 - ADC A(A/D Converter) + RTC_IRQHandler, // 25 - Real Time CLock interrpt + BOD_WDT_IRQHandler, // 25 - Combined Brownout/Watchdog interrupt + FMC_IRQHandler, // 27 - IP2111 Flash Memory Controller + DMA_IRQHandler, // 28 - DMA interrupt + ADCB_IRQHandler, // 24 - ADC B (A/D Converter) + USBWakeup_IRQHandler, // 30 - USB wake-up interrupt + 0, // 31 - Reserved +}; + +//***************************************************************************** +// Functions to carry out the initialization of RW and BSS data sections. These +// are written as separate functions rather than being inlined within the +// ResetISR() function in order to cope with MCUs with multiple banks of +// memory. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void data_init(unsigned int romstart, unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int *pulSrc = (unsigned int*) romstart; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = *pulSrc++; +} + +__attribute__ ((section(".after_vectors"))) +void bss_init(unsigned int start, unsigned int len) { + unsigned int *pulDest = (unsigned int*) start; + unsigned int loop; + for (loop = 0; loop < len; loop = loop + 4) + *pulDest++ = 0; +} + +//***************************************************************************** +// The following symbols are constructs generated by the linker, indicating +// the location of various points in the "Global Section Table". This table is +// created by the linker via the Code Red managed linker script mechanism. It +// contains the load address, execution address and length of each RW data +// section and the execution and length of each BSS (zero initialized) section. +//***************************************************************************** +extern unsigned int __data_section_table; +extern unsigned int __data_section_table_end; +extern unsigned int __bss_section_table; +extern unsigned int __bss_section_table_end; + +//***************************************************************************** +// Reset entry point for your code. +// Sets up a simple runtime environment and initializes the C/C++ +// library. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void +ResetISR(void) { + + // Optionally enable RAM banks that may be off by default at reset +#if !defined (DONT_ENABLE_DISABLED_RAMBANKS) + volatile unsigned int *SYSCON_SYSAHBCLKCTRL = (unsigned int *) 0x40048080; + // Ensure that RAM1(26) and USBSRAM(27) bits in SYSAHBCLKCTRL are set + *SYSCON_SYSAHBCLKCTRL |= (1 << 26) | (1 <<27); +#endif + + // + // Copy the data sections from flash to SRAM. + // + unsigned int LoadAddr, ExeAddr, SectionLen; + unsigned int *SectionTableAddr; + + // Load base address of Global Section Table + SectionTableAddr = &__data_section_table; + + // Copy the data sections from flash to SRAM. + while (SectionTableAddr < &__data_section_table_end) { + LoadAddr = *SectionTableAddr++; + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + data_init(LoadAddr, ExeAddr, SectionLen); + } + // At this point, SectionTableAddr = &__bss_section_table; + // Zero fill the bss segment + while (SectionTableAddr < &__bss_section_table_end) { + ExeAddr = *SectionTableAddr++; + SectionLen = *SectionTableAddr++; + bss_init(ExeAddr, SectionLen); + } + + // Patch the AEABI integer divide functions to use MCU's romdivide library +#ifdef __USE_ROMDIVIDE + // Get address of Integer division routines function table in ROM + unsigned int *div_ptr = (unsigned int *)((unsigned int *)*(PTR_ROM_DRIVER_TABLE))[4]; + // Get addresses of integer divide routines in ROM + // These address are then used by the code in aeabi_romdiv_patch.s + pDivRom_idiv = (unsigned int *)div_ptr[0]; + pDivRom_uidiv = (unsigned int *)div_ptr[1]; +#endif + +#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN) + SystemInit(); +#endif + +#if defined (__cplusplus) + // + // Call C++ library initialisation + // + __libc_init_array(); +#endif + +#if defined (__REDLIB__) + // Call the Redlib library, which in turn calls main() + __main() ; +#else + main(); +#endif + // + // main() shouldn't return, but if it does, we'll just enter an infinite loop + // + while (1) { + ; + } +} + +//***************************************************************************** +// Default exception handlers. Override the ones here by defining your own +// handler routines in your application code. +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void NMI_Handler(void) +{ while(1) { } +} +__attribute__ ((section(".after_vectors"))) +void HardFault_Handler(void) +{ while(1) { } +} + +__attribute__ ((section(".after_vectors"))) +void SVC_Handler(void) +{ while(1) { } +} + +__attribute__ ((section(".after_vectors"))) +void PendSV_Handler(void) +{ while(1) { } +} + +__attribute__ ((section(".after_vectors"))) +void SysTick_Handler(void) +{ while(1) { } +} + +//***************************************************************************** +// +// Processor ends up here if an unexpected interrupt occurs or a specific +// handler is not present in the application code. +// +//***************************************************************************** +__attribute__ ((section(".after_vectors"))) +void IntDefaultHandler(void) +{ while(1) { } +} diff --git a/source/test/src/crp.c b/source/test/src/crp.c new file mode 100644 index 0000000..7043d32 --- /dev/null +++ b/source/test/src/crp.c @@ -0,0 +1,27 @@ +//***************************************************************************** +// crp.c +// +// Source file to create CRP word expected by LPCXpresso IDE linker +//***************************************************************************** +// +// Copyright(C) NXP Semiconductors, 2013, 2020 +// All rights reserved. +// +// NXP Confidential. This software is owned or controlled by NXP and may only be +// used strictly in accordance with the applicable license terms. +// +// By expressly accepting such terms or by downloading, installing, activating +// and/or otherwise using the software, you are agreeing that you have read, and +// that you agree to comply with and are bound by, such license terms. +// +// If you do not agree to be bound by the applicable license terms, then you may not +// retain, install, activate or otherwise use the software. +//***************************************************************************** + +#if defined (__CODE_RED) +#include +// Variable to store CRP value in. Will be placed automatically +// by the linker when "Enable Code Read Protect" selected. +// See crp.h header for more information +__CRP const unsigned int CRP_WORD = CRP_NO_CRP ; +#endif diff --git a/source/test/src/mtb.c b/source/test/src/mtb.c new file mode 100644 index 0000000..4a65389 --- /dev/null +++ b/source/test/src/mtb.c @@ -0,0 +1,86 @@ +//***************************************************************************** +// +--+ +// | ++----+ +// +-++ | +// | | +// +-+--+ | +// | +--+--+ +// +----+ Copyright (c) 2013 Code Red Technologies Ltd. +// +// mtb.c +// +// Optionally defines an array to be used as a buffer for Micro Trace +// Buffer (MTB) instruction trace on Cortex-M0+ parts +// +// Version : 130502 +// +// Software License Agreement +// +// The software is owned by Code Red Technologies and/or its suppliers, and is +// protected under applicable copyright laws. All rights are reserved. Any +// use in violation of the foregoing restrictions may subject the user to criminal +// sanctions under applicable laws, as well as to civil liability for the breach +// of the terms and conditions of this license. +// +// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT +// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH +// CODE RED TECHNOLOGIES LTD. +// +//***************************************************************************** + +/******************************************************************* + * Symbols controlling behavior of this code... + * + * __MTB_DISABLE + * If this symbol is defined, then the buffer array for the MTB + * will not be created. + * + * __MTB_BUFFER_SIZE + * Symbol specifying the sizer of the buffer array for the MTB. + * This must be a power of 2 in size, and fit into the available + * RAM. The MTB buffer will also be aligned to its 'size' + * boundary and be placed at the start of a RAM bank (which + * should ensure minimal or zero padding due to alignment). + * + * __MTB_RAM_BANK + * Allows MTB Buffer to be placed into specific RAM bank. When + * this is not defined, the "default" (first if there are + * several) RAM bank is used. + *******************************************************************/ + +// Ignore with none Code Red tools +#if defined (__CODE_RED) + +// Allow MTB to be removed by setting a define (via command line) +#if !defined (__MTB_DISABLE) + + // Allow for MTB buffer size being set by define set via command line + // Otherwise provide small default buffer + #if !defined (__MTB_BUFFER_SIZE) + #define __MTB_BUFFER_SIZE 128 + #endif + + // Check that buffer size requested is >0 bytes in size + #if (__MTB_BUFFER_SIZE > 0) + // Pull in MTB related macros + #include + + // Check if MYTB buffer is to be placed in specific RAM bank + #if defined(__MTB_RAM_BANK) + // Place MTB buffer into explicit bank of RAM + __CR_MTB_BUFFER_EXT(__MTB_BUFFER_SIZE,__MTB_RAM_BANK); + #else + // Place MTB buffer into 'default' bank of RAM + __CR_MTB_BUFFER(__MTB_BUFFER_SIZE); + + #endif // defined(__MTB_RAM_BANK) + + #endif // (__MTB_BUFFER_SIZE > 0) + +#endif // !defined (__MTB_DISABLE) + +#endif // defined (__CODE_RED) + diff --git a/source/test/src/sysinit.c b/source/test/src/sysinit.c new file mode 100644 index 0000000..1b4bf14 --- /dev/null +++ b/source/test/src/sysinit.c @@ -0,0 +1,57 @@ +/* + * @brief Common SystemInit function for LPC11u6x chips + * + * @note + * Copyright 2013-2014, 2019, 2020 NXP + * All rights reserved. + * + * @par + * NXP Confidential. This software is owned or controlled by NXP and may only be + * used strictly in accordance with the applicable license terms. + * + * By expressly accepting such terms or by downloading, installing, activating + * and/or otherwise using the software, you are agreeing that you have read, and + * that you agree to comply with and are bound by, such license terms. + * + * If you do not agree to be bound by the applicable license terms, then you may not + * retain, install, activate or otherwise use the software. + */ + + #if defined(NO_BOARD_LIB) + #include "chip.h" + #else + #include "board.h" + #endif + +/***************************************************************************** + * Private types/enumerations/variables + ****************************************************************************/ + +/***************************************************************************** + * Public types/enumerations/variables + ****************************************************************************/ + +#if defined(NO_BOARD_LIB) +const uint32_t OscRateIn = 12000000; +const uint32_t RTCOscRateIn = 32768; +#endif + +/***************************************************************************** + * Private functions + ****************************************************************************/ + +/***************************************************************************** + * Public functions + ****************************************************************************/ + +/* Set up and initialize hardware prior to call to main */ +void SystemInit(void) +{ +#if defined(NO_BOARD_LIB) + /* Chip specific SystemInit */ + Chip_SystemInit(); +#else + /* Setup system clocking and muxing */ + Board_SystemInit(); +#endif +} diff --git a/source/test/src/test.cpp b/source/test/src/test.cpp new file mode 100644 index 0000000..b602ec6 --- /dev/null +++ b/source/test/src/test.cpp @@ -0,0 +1,51 @@ +/* +=============================================================================== + Name : main.c + Author : $(author) + Version : + Copyright : $(copyright) + Description : main definition +=============================================================================== +*/ + +#if defined (__USE_LPCOPEN) +#if defined(NO_BOARD_LIB) +#include "chip.h" +#else +#include "board.h" +#endif +#endif + +#include + +// TODO: insert other include files here + +// TODO: insert other definitions and declarations here + +int main(void) { + +#if defined (__USE_LPCOPEN) + // Read clock settings and update SystemCoreClock variable + SystemCoreClockUpdate(); +#if !defined(NO_BOARD_LIB) + // Set up and initialize all required blocks and + // functions related to the board hardware + Board_Init(); + // Set the LED to the state of "On" + Board_LED_Set(0, true); +#endif +#endif + + // TODO: insert code here + + // Force the counter to be placed into memory + volatile static int i = 0 ; + // Enter an infinite loop, just incrementing a counter + while(1) { + i++ ; + // "Dummy" NOP to allow source level single + // stepping of tight while() loop + __asm volatile ("nop"); + } + return 0 ; +}