mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
Check in compilation files for OSX simulation. Update to work on revolution
tree.
This commit is contained in:
parent
5827e3f565
commit
7ba32f8735
9
Makefile
9
Makefile
@ -117,6 +117,8 @@ help:
|
||||
@echo " sim_posix - Build OpenPilot simulation firmware for"
|
||||
@echo " a POSIX compatible system (Linux, Mac OS X, ...)"
|
||||
@echo " sim_posix_clean - Delete all build output for the POSIX simulation"
|
||||
@echo " sim_osx - Build OpenPilot simulation firmware for OSX"
|
||||
@echo " sim_osx_clean - Delete all build output for the osx simulation"
|
||||
@echo " sim_win32 - Build OpenPilot simulation firmware for"
|
||||
@echo " Windows using mingw and msys"
|
||||
@echo " sim_win32_clean - Delete all build output for the win32 simulation"
|
||||
@ -709,6 +711,13 @@ sim_win32_%: uavobjects_flight
|
||||
$(V1) $(MAKE) --no-print-directory \
|
||||
-C $(ROOT_DIR)/flight/OpenPilot --file=$(ROOT_DIR)/flight/OpenPilot/Makefile.win32 $*
|
||||
|
||||
.PHONY: sim_osx
|
||||
sim_osx: sim_osx_elf
|
||||
|
||||
sim_osx_%: uavobjects_flight
|
||||
$(V1) mkdir -p $(BUILD_DIR)/sim_osx
|
||||
$(V1) $(MAKE) --no-print-directory \
|
||||
-C $(ROOT_DIR)/flight/Revolution --file=$(ROOT_DIR)/flight/Revolution/Makefile.osx $*
|
||||
##############################
|
||||
#
|
||||
# Packaging components
|
||||
|
107
flight/PiOS.osx/inc/FreeRTOSConfig.h
Normal file
107
flight/PiOS.osx/inc/FreeRTOSConfig.h
Normal file
@ -0,0 +1,107 @@
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* 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.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Notes: We use 5 task priorities */
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define COND_SIGNALING
|
||||
#define CHECK_TASK_RESUMES
|
||||
#define RUNNING_THREAD_MUTEX
|
||||
// #define TICK_SIGNAL
|
||||
// #define TICK_SIGWAIT
|
||||
#define IDLE_SLEEPS
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configIDLE_SHOULD_YIELD 0
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
#define COND_SIGNALING
|
||||
#define CHECK_TASK_RESUMES
|
||||
// #define RUNNING_THREAD_MUTEX
|
||||
// #define TICK_SIGNAL
|
||||
#define TICK_SIGWAIT
|
||||
#define IDLE_SLEEPS
|
||||
|
||||
#define configUSE_PREEMPTION 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#define COND_SIGNALING
|
||||
#define CHECK_TASK_RESUMES
|
||||
#define RUNNING_THREAD_MUTEX
|
||||
// #define TICK_SIGNAL
|
||||
// #define TICK_SIGWAIT
|
||||
#define IDLE_SLEEPS
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configIDLE_SHOULD_YIELD 0
|
||||
#endif
|
||||
|
||||
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ ( ( unsigned long ) 72000000 )
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 45 * 1024 ) )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_TRACE_FACILITY 0
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configUSE_MUTEXES 1
|
||||
#define configUSE_RECURSIVE_MUTEXES 1
|
||||
#define configUSE_COUNTING_SEMAPHORES 0
|
||||
#define configUSE_ALTERNATIVE_API 0
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 2
|
||||
#define configQUEUE_REGISTRY_SIZE 10
|
||||
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 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 0
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetSchedulerState 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 0
|
||||
|
||||
|
||||
|
||||
|
||||
/* This is the raw value as per the Cortex-M3 NVIC. Values can be 255
|
||||
(lowest) to 1 (highest maskable) to 0 (highest non-maskable). */
|
||||
#define configKERNEL_INTERRUPT_PRIORITY 15 << 4 /* equivalent to NVIC priority 15 */
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 3 << 4 /* equivalent to NVIC priority 3 */
|
||||
|
||||
|
||||
/* This is the value being used as per the ST library which permits 16
|
||||
priority values, 0 to 15. This must correspond to the
|
||||
configKERNEL_INTERRUPT_PRIORITY setting. Here 15 corresponds to the lowest
|
||||
NVIC value of 255. */
|
||||
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY 15
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
|
65
flight/PiOS.osx/inc/pios_com.h
Normal file
65
flight/PiOS.osx/inc/pios_com.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_COM COM layer functions
|
||||
* @brief Hardware communication layer
|
||||
* @{
|
||||
*
|
||||
* @file pios_com.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief COM layer functions header
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_COM_H
|
||||
#define PIOS_COM_H
|
||||
|
||||
typedef uint16_t (*pios_com_callback)(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * task_woken);
|
||||
|
||||
struct pios_com_driver {
|
||||
void (*init)(uint32_t id);
|
||||
void (*set_baud)(uint32_t id, uint32_t baud);
|
||||
void (*tx_start)(uint32_t id, uint16_t tx_bytes_avail);
|
||||
void (*rx_start)(uint32_t id, uint16_t rx_bytes_avail);
|
||||
void (*bind_rx_cb)(uint32_t id, pios_com_callback rx_in_cb, uint32_t context);
|
||||
void (*bind_tx_cb)(uint32_t id, pios_com_callback tx_out_cb, uint32_t context);
|
||||
};
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_COM_Init(uint32_t * com_id, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t * rx_buffer, uint16_t rx_buffer_len, uint8_t * tx_buffer, uint16_t tx_buffer_len);
|
||||
extern int32_t PIOS_COM_ChangeBaud(uint32_t com_id, uint32_t baud);
|
||||
extern int32_t PIOS_COM_SendCharNonBlocking(uint32_t com_id, char c);
|
||||
extern int32_t PIOS_COM_SendChar(uint32_t com_id, char c);
|
||||
extern int32_t PIOS_COM_SendBufferNonBlocking(uint32_t com_id, const uint8_t *buffer, uint16_t len);
|
||||
extern int32_t PIOS_COM_SendBuffer(uint32_t com_id, const uint8_t *buffer, uint16_t len);
|
||||
extern int32_t PIOS_COM_SendStringNonBlocking(uint32_t com_id, const char *str);
|
||||
extern int32_t PIOS_COM_SendString(uint32_t com_id, const char *str);
|
||||
extern int32_t PIOS_COM_SendFormattedStringNonBlocking(uint32_t com_id, const char *format, ...);
|
||||
extern int32_t PIOS_COM_SendFormattedString(uint32_t com_id, const char *format, ...);
|
||||
extern uint16_t PIOS_COM_ReceiveBuffer(uint32_t com_id, uint8_t * buf, uint16_t buf_len, uint32_t timeout_ms);
|
||||
extern int32_t PIOS_COM_ReceiveBufferUsed(uint32_t com_id);
|
||||
|
||||
#endif /* PIOS_COM_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
44
flight/PiOS.osx/inc/pios_com_priv.h
Normal file
44
flight/PiOS.osx/inc/pios_com_priv.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_COM COM layer functions
|
||||
* @brief Hardware communication layer
|
||||
* @{
|
||||
*
|
||||
* @file pios_com_priv.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief COM private definitions.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_COM_PRIV_H
|
||||
#define PIOS_COM_PRIV_H
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
extern int32_t PIOS_COM_ReceiveHandler(uint32_t com_id);
|
||||
|
||||
#endif /* PIOS_COM_PRIV_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
31
flight/PiOS.osx/inc/pios_crc.h
Normal file
31
flight/PiOS.osx/inc/pios_crc.h
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_CRC CRC Functions
|
||||
* @{
|
||||
*
|
||||
* @file pios_crc.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief CRC functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
uint8_t PIOS_CRC_updateByte(uint8_t crc, const uint8_t data);
|
||||
uint8_t PIOS_CRC_updateCRC(uint8_t crc, const uint8_t* data, int32_t length);
|
56
flight/PiOS.osx/inc/pios_debug.h
Normal file
56
flight/PiOS.osx/inc/pios_debug.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @defgroup PIOS_DEBUG Debugging Functions
|
||||
* @brief Debugging functionality
|
||||
* @{
|
||||
*
|
||||
* @file pios_i2c.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Debug helper functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_DEBUG_H
|
||||
#define PIOS_DEBUG_H
|
||||
|
||||
extern const char *PIOS_DEBUG_AssertMsg;
|
||||
|
||||
void PIOS_DEBUG_Init(void);
|
||||
void PIOS_DEBUG_PinHigh(uint8_t pin);
|
||||
void PIOS_DEBUG_PinLow(uint8_t pin);
|
||||
void PIOS_DEBUG_PinValue8Bit(uint8_t value);
|
||||
void PIOS_DEBUG_PinValue4BitL(uint8_t value);
|
||||
void PIOS_DEBUG_Panic(const char *msg);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PIOS_DEBUG_Assert(test) if (!(test)) PIOS_DEBUG_Panic(PIOS_DEBUG_AssertMsg);
|
||||
#define PIOS_Assert(test) PIOS_DEBUG_Assert(test)
|
||||
#else
|
||||
#define PIOS_DEBUG_Assert(test)
|
||||
#define PIOS_Assert(test) if (!(test)) while (1);
|
||||
#endif
|
||||
|
||||
#endif /* PIOS_DEBUG_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
48
flight/PiOS.osx/inc/pios_delay.h
Normal file
48
flight/PiOS.osx/inc/pios_delay.h
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_DELAY Delay Functions
|
||||
* @brief PiOS Delay functionality
|
||||
* @{
|
||||
*
|
||||
* @file pios_settings.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||
* @brief Settings functions header
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_DELAY_H
|
||||
#define PIOS_DELAY_H
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_DELAY_Init(void);
|
||||
extern int32_t PIOS_DELAY_WaituS(uint32_t uS);
|
||||
extern int32_t PIOS_DELAY_WaitmS(uint32_t mS);
|
||||
extern uint32_t PIOS_DELAY_GetuS();
|
||||
extern uint32_t PIOS_DELAY_GetuSSince(uint32_t t);
|
||||
extern uint32_t PIOS_DELAY_GetRaw();
|
||||
extern uint32_t PIOS_DELAY_DiffuS(uint32_t raw);
|
||||
|
||||
#endif /* PIOS_DELAY_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
72
flight/PiOS.osx/inc/pios_initcall.h
Normal file
72
flight/PiOS.osx/inc/pios_initcall.h
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Initcall infrastructure
|
||||
* @{
|
||||
* @addtogroup PIOS_INITCALL Generic Initcall Macros
|
||||
* @brief Initcall Macros
|
||||
* @{
|
||||
*
|
||||
* @file pios_initcall.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2011.
|
||||
* @brief Initcall header
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_INITCALL_H
|
||||
#define PIOS_INITCALL_H
|
||||
|
||||
/**
|
||||
* Just a stub define to make things compile.
|
||||
* Automatically link based initialization currently doesn't work
|
||||
* since posix really runs on a multitude of architectures
|
||||
* and we cannot define a linker script for each of them atm
|
||||
*/
|
||||
|
||||
|
||||
typedef int32_t (*initcall_t)(void);
|
||||
typedef struct {
|
||||
initcall_t fn_minit;
|
||||
initcall_t fn_tinit;
|
||||
} initmodule_t;
|
||||
|
||||
/* Init module section */
|
||||
extern initmodule_t __module_initcall_start[], __module_initcall_end[];
|
||||
|
||||
extern void InitModules();
|
||||
extern void StartModules();
|
||||
|
||||
#define MODULE_INITCALL(ifn, sfn)
|
||||
|
||||
#define MODULE_TASKCREATE_ALL { \
|
||||
/* Start all module threads */ \
|
||||
StartModules(); \
|
||||
}
|
||||
|
||||
#define MODULE_INITIALISE_ALL { \
|
||||
/* Initialize modules */ \
|
||||
InitModules(); \
|
||||
/* Initialize the system thread */ \
|
||||
SystemModInitialize();}
|
||||
|
||||
#endif /* PIOS_INITCALL_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
38
flight/PiOS.osx/inc/pios_irq.h
Normal file
38
flight/PiOS.osx/inc/pios_irq.h
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_IRQ IRQ Setup Functions
|
||||
* @{
|
||||
*
|
||||
* @file pios_irq.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief IRQ functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_IRQ_H
|
||||
#define PIOS_IRQ_H
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_IRQ_Disable(void);
|
||||
extern int32_t PIOS_IRQ_Enable(void);
|
||||
|
||||
#endif /* PIOS_IRQ_H */
|
39
flight/PiOS.osx/inc/pios_led.h
Normal file
39
flight/PiOS.osx/inc/pios_led.h
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_LED LED Functions
|
||||
* @{
|
||||
*
|
||||
* @file pios_led.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief LED functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_LED_H
|
||||
#define PIOS_LED_H
|
||||
|
||||
/* Public Functions */
|
||||
extern void PIOS_LED_Init();
|
||||
extern void PIOS_LED_On(uint32_t led_id);
|
||||
extern void PIOS_LED_Off(uint32_t led_id);
|
||||
extern void PIOS_LED_Toggle(uint32_t led_id);
|
||||
|
||||
#endif /* PIOS_LED_H */
|
44
flight/PiOS.osx/inc/pios_posix.h
Normal file
44
flight/PiOS.osx/inc/pios_posix.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file posix.h
|
||||
* @author Corvus Corax Copyright (C) 2010.
|
||||
* @brief Definitions to run PiOS on posix
|
||||
* @see The GNU Public License (GPL) Version 2
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_POSIX_H
|
||||
#define PIOS_POSIX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {FALSE = 0, TRUE = !FALSE} bool;
|
||||
|
||||
#ifndef false
|
||||
#define false FALSE
|
||||
#define true TRUE
|
||||
#endif
|
||||
|
||||
#define FILEINFO FILE*
|
||||
|
||||
#define PIOS_SERVO_NUM_OUTPUTS 8
|
||||
#define PIOS_SERVO_NUM_TIMERS PIOS_SERVO_NUM_OUTPUTS
|
||||
|
||||
#endif
|
||||
|
64
flight/PiOS.osx/inc/pios_rcvr.h
Normal file
64
flight/PiOS.osx/inc/pios_rcvr.h
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_RCVR RCVR layer functions
|
||||
* @brief Hardware communication layer
|
||||
* @{
|
||||
*
|
||||
* @file pios_rcvr.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief RCVR layer functions header
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_RCVR_H
|
||||
#define PIOS_RCVR_H
|
||||
|
||||
struct pios_rcvr_channel_map {
|
||||
uint32_t id;
|
||||
uint8_t channel;
|
||||
};
|
||||
|
||||
extern struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[];
|
||||
|
||||
struct pios_rcvr_driver {
|
||||
void (*init)(uint32_t id);
|
||||
int32_t (*read)(uint32_t id, uint8_t channel);
|
||||
};
|
||||
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel);
|
||||
|
||||
/*! Define error codes for PIOS_RCVR_Get */
|
||||
enum PIOS_RCVR_errors {
|
||||
/*! Indicates that a failsafe condition or missing receiver detected for that channel */
|
||||
PIOS_RCVR_TIMEOUT = 0,
|
||||
/*! Channel is invalid for this driver (usually out of range supported) */
|
||||
PIOS_RCVR_INVALID = -1,
|
||||
/*! Indicates that the driver for this channel has not been initialized */
|
||||
PIOS_RCVR_NODRIVER = -2
|
||||
};
|
||||
|
||||
#endif /* PIOS_RCVR_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
48
flight/PiOS.osx/inc/pios_rcvr_priv.h
Normal file
48
flight/PiOS.osx/inc/pios_rcvr_priv.h
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_RCVR RCVR Functions
|
||||
* @brief PIOS interface for RCVR drivers
|
||||
* @{
|
||||
*
|
||||
* @file pios_rcvr_priv.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief USART private definitions.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_RCVR_PRIV_H
|
||||
#define PIOS_RCVR_PRIV_H
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
extern uint32_t pios_rcvr_max_channel;
|
||||
|
||||
extern int32_t PIOS_RCVR_Init(uint32_t * rcvr_id, const struct pios_rcvr_driver * driver, const uint32_t lower_id);
|
||||
|
||||
extern void PIOS_RCVR_IRQ_Handler(uint32_t rcvr_id);
|
||||
|
||||
#endif /* PIOS_RCVR_PRIV_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
113
flight/PiOS.osx/inc/pios_sdcard.h
Normal file
113
flight/PiOS.osx/inc/pios_sdcard.h
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_sdcard.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief System and hardware Init functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_SDCARD_H
|
||||
#define PIOS_SDCARD_H
|
||||
|
||||
#if defined(PIOS_INCLUDE_SDCARD)
|
||||
|
||||
/* Public Functions */
|
||||
typedef struct {
|
||||
uint8_t CSDStruct; /* CSD structure */
|
||||
uint8_t SysSpecVersion; /* System specification version */
|
||||
uint8_t Reserved1; /* Reserved */
|
||||
uint8_t TAAC; /* Data read access-time 1 */
|
||||
uint8_t NSAC; /* Data read access-time 2 in CLK cycles */
|
||||
uint8_t MaxBusClkFrec; /* Max. bus clock frequency */
|
||||
uint16_t CardComdClasses; /* Card command classes */
|
||||
uint8_t RdBlockLen; /* Max. read data block length */
|
||||
uint8_t PartBlockRead; /* Partial blocks for read allowed */
|
||||
uint8_t WrBlockMisalign; /* Write block misalignment */
|
||||
uint8_t RdBlockMisalign; /* Read block misalignment */
|
||||
uint8_t DSRImpl; /* DSR implemented */
|
||||
uint8_t Reserved2; /* Reserved */
|
||||
uint16_t DeviceSize; /* Device Size */
|
||||
uint8_t MaxRdCurrentVDDMin; /* Max. read current @ VDD min */
|
||||
uint8_t MaxRdCurrentVDDMax; /* Max. read current @ VDD max */
|
||||
uint8_t MaxWrCurrentVDDMin; /* Max. write current @ VDD min */
|
||||
uint8_t MaxWrCurrentVDDMax; /* Max. write current @ VDD max */
|
||||
uint8_t DeviceSizeMul; /* Device size multiplier */
|
||||
uint8_t EraseGrSize; /* Erase group size */
|
||||
uint8_t EraseGrMul; /* Erase group size multiplier */
|
||||
uint8_t WrProtectGrSize; /* Write protect group size */
|
||||
uint8_t WrProtectGrEnable; /* Write protect group enable */
|
||||
uint8_t ManDeflECC; /* Manufacturer default ECC */
|
||||
uint8_t WrSpeedFact; /* Write speed factor */
|
||||
uint8_t MaxWrBlockLen; /* Max. write data block length */
|
||||
uint8_t WriteBlockPaPartial; /* Partial blocks for write allowed */
|
||||
uint8_t Reserved3; /* Reserved */
|
||||
uint8_t ContentProtectAppli; /* Content protection application */
|
||||
uint8_t FileFormatGrouop; /* File format group */
|
||||
uint8_t CopyFlag; /* Copy flag (OTP) */
|
||||
uint8_t PermWrProtect; /* Permanent write protection */
|
||||
uint8_t TempWrProtect; /* Temporary write protection */
|
||||
uint8_t FileFormat; /* File Format */
|
||||
uint8_t ECC; /* ECC code */
|
||||
uint8_t msd_CRC; /* CRC */
|
||||
uint8_t Reserved4; /* always 1*/
|
||||
} SDCARDCsdTypeDef;
|
||||
|
||||
/* Structure taken from Mass Storage Driver example provided by STM */
|
||||
typedef struct {
|
||||
uint8_t ManufacturerID; /* ManufacturerID */
|
||||
uint16_t OEM_AppliID; /* OEM/Application ID */
|
||||
char ProdName[6]; /* Product Name */
|
||||
uint8_t ProdRev; /* Product Revision */
|
||||
uint32_t ProdSN; /* Product Serial Number */
|
||||
uint8_t Reserved1; /* Reserved1 */
|
||||
uint16_t ManufactDate; /* Manufacturing Date */
|
||||
uint8_t msd_CRC; /* CRC */
|
||||
uint8_t Reserved2; /* always 1*/
|
||||
} SDCARDCidTypeDef;
|
||||
|
||||
/* Global Variables */
|
||||
//extern VOLINFO PIOS_SDCARD_VolInfo;
|
||||
//extern uint8_t PIOS_SDCARD_Sector[SECTOR_SIZE];
|
||||
|
||||
/* Prototypes */
|
||||
extern int32_t PIOS_SDCARD_Init(void);
|
||||
extern int32_t PIOS_SDCARD_PowerOn(void);
|
||||
extern int32_t PIOS_SDCARD_PowerOff(void);
|
||||
extern int32_t PIOS_SDCARD_CheckAvailable(uint8_t was_available);
|
||||
extern int32_t PIOS_SDCARD_SendSDCCmd(uint8_t cmd, uint32_t addr, uint8_t crc);
|
||||
extern int32_t PIOS_SDCARD_SectorRead(uint32_t sector, uint8_t *buffer);
|
||||
extern int32_t PIOS_SDCARD_SectorWrite(uint32_t sector, uint8_t *buffer);
|
||||
extern int32_t PIOS_SDCARD_CIDRead(SDCARDCidTypeDef *cid);
|
||||
extern int32_t PIOS_SDCARD_CSDRead(SDCARDCsdTypeDef *csd);
|
||||
|
||||
extern int32_t PIOS_SDCARD_StartupLog(void);
|
||||
extern int32_t PIOS_SDCARD_IsMounted();
|
||||
extern int32_t PIOS_SDCARD_MountFS(uint32_t StartupLog);
|
||||
extern int32_t PIOS_SDCARD_GetFree(void);
|
||||
|
||||
//extern int32_t PIOS_SDCARD_ReadBuffer(PFILEINFO fileinfo, uint8_t *buffer, uint32_t len);
|
||||
//extern int32_t PIOS_SDCARD_ReadLine(PFILEINFO fileinfo, uint8_t *buffer, uint32_t max_len);
|
||||
extern int32_t PIOS_SDCARD_FileCopy(char *Source, char *Destination);
|
||||
extern int32_t PIOS_SDCARD_FileDelete(char *Filename);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PIOS_SDCARD_H */
|
43
flight/PiOS.osx/inc/pios_servo.h
Normal file
43
flight/PiOS.osx/inc/pios_servo.h
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_SERVO RC Servo Functions
|
||||
* @{
|
||||
*
|
||||
* @file pios_servo.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief RC Servo functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_SERVO_H
|
||||
#define PIOS_SERVO_H
|
||||
|
||||
/* Public Functions */
|
||||
extern void PIOS_Servo_Init(void);
|
||||
extern void PIOS_Servo_SetHz(uint16_t * speeds, uint8_t num_banks);
|
||||
extern void PIOS_Servo_Set(uint8_t Servo, uint16_t Position);
|
||||
|
||||
#endif /* PIOS_SERVO_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
13
flight/PiOS.osx/inc/pios_sim.h
Normal file
13
flight/PiOS.osx/inc/pios_sim.h
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
#ifndef PIOS_SIM_H
|
||||
#define PIOS_SIM_H
|
||||
|
||||
int PIOS_SIM_Init();
|
||||
int PIOS_SIM_Step(float dT);
|
||||
void PIOS_SIM_SetActuator(float * actuator_int, int nchannels);
|
||||
void PIOS_SIM_GetAccels(float *);
|
||||
void PIOS_SIM_GetGyros(float *);
|
||||
void PIOS_SIM_GetAttitude(float *);
|
||||
void PIOS_SIM_GetPosition(float *);
|
||||
|
||||
#endif /* PIOS_SIM_H */
|
19
flight/PiOS.osx/inc/pios_sim_priv.h
Normal file
19
flight/PiOS.osx/inc/pios_sim_priv.h
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
#ifndef PIOS_SIM_PRIV_H
|
||||
#define PIOS_SIM_PRIV_H
|
||||
|
||||
/**
|
||||
* State of inputs and outputs to the simulation model
|
||||
*/
|
||||
struct pios_sim_state {
|
||||
float accels[3];
|
||||
float gyros[3];
|
||||
float mag[3];
|
||||
float baro[1];
|
||||
float q[4];
|
||||
float velocity[3];
|
||||
float position[3];
|
||||
float actuator[8];
|
||||
};
|
||||
|
||||
#endif /* PIOS_SIM_PRIV */
|
35
flight/PiOS.osx/inc/pios_sys.h
Normal file
35
flight/PiOS.osx/inc/pios_sys.h
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_sys.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief System and hardware Init functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_SYS_H
|
||||
#define PIOS_SYS_H
|
||||
|
||||
/* Public Functions */
|
||||
extern void PIOS_SYS_Init(void);
|
||||
extern int32_t PIOS_SYS_Reset(void);
|
||||
extern int32_t PIOS_SYS_SerialNumberGet(char *str);
|
||||
|
||||
#endif /* PIOS_SYS_H */
|
35
flight/PiOS.osx/inc/pios_udp.h
Normal file
35
flight/PiOS.osx/inc/pios_udp.h
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_usart.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief UDP functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_UDP_H
|
||||
#define PIOS_UDP_H
|
||||
|
||||
|
||||
/* Global Types */
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
#endif /* PIOS_UDP_H */
|
71
flight/PiOS.osx/inc/pios_udp_priv.h
Normal file
71
flight/PiOS.osx/inc/pios_udp_priv.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_udp_priv.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief UDP private definitions.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_UDP_PRIV_H
|
||||
#define PIOS_UDP_PRIV_H
|
||||
|
||||
#include <pios.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct pios_udp_cfg {
|
||||
const char * ip;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const struct pios_udp_cfg * cfg;
|
||||
pthread_t rxThread;
|
||||
|
||||
int socket;
|
||||
struct sockaddr_in server;
|
||||
struct sockaddr_in client;
|
||||
uint32_t clientLength;
|
||||
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
pios_com_callback tx_out_cb;
|
||||
uint32_t tx_out_context;
|
||||
pios_com_callback rx_in_cb;
|
||||
uint32_t rx_in_context;
|
||||
|
||||
uint8_t rx_buffer[PIOS_UDP_RX_BUFFER_SIZE];
|
||||
uint8_t tx_buffer[PIOS_UDP_RX_BUFFER_SIZE];
|
||||
} pios_udp_dev;
|
||||
|
||||
extern int32_t PIOS_UDP_Init(uint32_t * udp_id, const struct pios_udp_cfg * cfg);
|
||||
|
||||
|
||||
|
||||
#endif /* PIOS_UDP_PRIV_H */
|
45
flight/PiOS.osx/inc/pios_wdg.h
Normal file
45
flight/PiOS.osx/inc/pios_wdg.h
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_WDG Watchdog Functions
|
||||
* @{
|
||||
*
|
||||
* @file pios_wdg.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief SPI functions header.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_WDG
|
||||
#define PIOS_WDG
|
||||
|
||||
void PIOS_WDG_Init();
|
||||
bool PIOS_WDG_RegisterFlag(uint16_t flag_requested);
|
||||
bool PIOS_WDG_UpdateFlag(uint16_t flag);
|
||||
uint16_t PIOS_WDG_GetBootupFlags();
|
||||
uint16_t PIOS_WDG_GetActiveFlags();
|
||||
void PIOS_WDG_Clear(void);
|
||||
|
||||
#define PIOS_WDG_ACTUATOR 0x0001
|
||||
#define PIOS_WDG_STABILIZATION 0x0002
|
||||
#define PIOS_WDG_MANUAL 0x0008
|
||||
|
||||
#endif
|
6
flight/PiOS.osx/inc/sim_model.h
Normal file
6
flight/PiOS.osx/inc/sim_model.h
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
#include "pios_sim_priv.h"
|
||||
|
||||
extern int sim_model_init();
|
||||
extern int sim_model_terminate();
|
||||
extern int sim_model_step(float dT, struct pios_sim_state * state);
|
BIN
flight/PiOS.osx/osx/.pios_rcvr.c.swp
Normal file
BIN
flight/PiOS.osx/osx/.pios_rcvr.c.swp
Normal file
Binary file not shown.
371
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/croutine.c
Normal file
371
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/croutine.c
Normal file
@ -0,0 +1,371 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "croutine.h"
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
#endif
|
||||
|
||||
|
||||
/* Lists for ready and blocked co-routines. --------------------*/
|
||||
static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
|
||||
static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */
|
||||
static xList xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
|
||||
static xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
|
||||
static xList * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
|
||||
static xList xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
|
||||
|
||||
/* Other file private variables. --------------------------------*/
|
||||
corCRCB * pxCurrentCoRoutine = NULL;
|
||||
static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0;
|
||||
static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
|
||||
|
||||
/* The initial state of the co-routine when it is created. */
|
||||
#define corINITIAL_STATE ( 0 )
|
||||
|
||||
/*
|
||||
* Place the co-routine represented by pxCRCB into the appropriate ready queue
|
||||
* for the priority. It is inserted at the end of the list.
|
||||
*
|
||||
* This macro accesses the co-routine ready lists and therefore must not be
|
||||
* used from within an ISR.
|
||||
*/
|
||||
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
|
||||
{ \
|
||||
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
|
||||
{ \
|
||||
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility to ready all the lists used by the scheduler. This is called
|
||||
* automatically upon the creation of the first co-routine.
|
||||
*/
|
||||
static void prvInitialiseCoRoutineLists( void );
|
||||
|
||||
/*
|
||||
* Co-routines that are readied by an interrupt cannot be placed directly into
|
||||
* the ready lists (there is no mutual exclusion). Instead they are placed in
|
||||
* in the pending ready list in order that they can later be moved to the ready
|
||||
* list by the co-routine scheduler.
|
||||
*/
|
||||
static void prvCheckPendingReadyList( void );
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of co-routines that are currently delayed to
|
||||
* see if any require waking.
|
||||
*
|
||||
* Co-routines are stored in the queue in the order of their wake time -
|
||||
* meaning once one co-routine has been found whose timer has not expired
|
||||
* we need not look any further down the list.
|
||||
*/
|
||||
static void prvCheckDelayedList( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
corCRCB *pxCoRoutine;
|
||||
|
||||
/* Allocate the memory that will store the co-routine control block. */
|
||||
pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) );
|
||||
if( pxCoRoutine )
|
||||
{
|
||||
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
|
||||
be created and the co-routine data structures need initialising. */
|
||||
if( pxCurrentCoRoutine == NULL )
|
||||
{
|
||||
pxCurrentCoRoutine = pxCoRoutine;
|
||||
prvInitialiseCoRoutineLists();
|
||||
}
|
||||
|
||||
/* Check the priority is within limits. */
|
||||
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
|
||||
{
|
||||
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
/* Fill out the co-routine control block from the function parameters. */
|
||||
pxCoRoutine->uxState = corINITIAL_STATE;
|
||||
pxCoRoutine->uxPriority = uxPriority;
|
||||
pxCoRoutine->uxIndex = uxIndex;
|
||||
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
|
||||
|
||||
/* Initialise all the other co-routine control block parameters. */
|
||||
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
|
||||
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
|
||||
|
||||
/* Set the co-routine control block as a link back from the xListItem.
|
||||
This is so we can get back to the containing CRCB from a generic item
|
||||
in a list. */
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
|
||||
|
||||
/* Event lists are always in priority order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
|
||||
|
||||
/* Now the co-routine has been initialised it can be added to the ready
|
||||
list at the correct priority. */
|
||||
prvAddCoRoutineToReadyQueue( pxCoRoutine );
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
|
||||
/* Calculate the time to wake - this may overflow but this is
|
||||
not a problem. */
|
||||
xTimeToWake = xCoRoutineTickCount + 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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
|
||||
/* The list item will be inserted in wake time order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xCoRoutineTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the
|
||||
overflow list. */
|
||||
vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
|
||||
if( pxEventList )
|
||||
{
|
||||
/* Also add the co-routine to an event list. If this is done then the
|
||||
function must be called with interrupts disabled. */
|
||||
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckPendingReadyList( void )
|
||||
{
|
||||
/* Are there any co-routines waiting to get moved to the ready list? These
|
||||
are co-routines that have been readied by an ISR. The ISR cannot access
|
||||
the ready lists itself. */
|
||||
while( !listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) )
|
||||
{
|
||||
corCRCB *pxUnblockedCRCB;
|
||||
|
||||
/* The pending ready list can be accessed by an ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
|
||||
vListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
vListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
|
||||
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckDelayedList( void )
|
||||
{
|
||||
corCRCB *pxCRCB;
|
||||
|
||||
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
|
||||
while( xPassedTicks )
|
||||
{
|
||||
xCoRoutineTickCount++;
|
||||
xPassedTicks--;
|
||||
|
||||
/* If the tick count has overflowed we need to swap the ready lists. */
|
||||
if( xCoRoutineTickCount == 0 )
|
||||
{
|
||||
xList * pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists. If there are
|
||||
any items in pxDelayedCoRoutineList here then there is an error! */
|
||||
pxTemp = pxDelayedCoRoutineList;
|
||||
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
|
||||
pxOverflowDelayedCoRoutineList = pxTemp;
|
||||
}
|
||||
|
||||
/* See if this tick has made a timeout expire. */
|
||||
while( ( pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ) ) != NULL )
|
||||
{
|
||||
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
|
||||
{
|
||||
/* Timeout not yet expired. */
|
||||
break;
|
||||
}
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* The event could have occurred just before this critical
|
||||
section. If this is the case then the generic list item will
|
||||
have been moved to the pending ready list and the following
|
||||
line is still valid. Also the pvContainer parameter will have
|
||||
been set to NULL so the following lines are also valid. */
|
||||
vListRemove( &( pxCRCB->xGenericListItem ) );
|
||||
|
||||
/* Is the co-routine waiting on an event also? */
|
||||
if( pxCRCB->xEventListItem.pvContainer )
|
||||
{
|
||||
vListRemove( &( pxCRCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
prvAddCoRoutineToReadyQueue( pxCRCB );
|
||||
}
|
||||
}
|
||||
|
||||
xLastTickCount = xCoRoutineTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineSchedule( void )
|
||||
{
|
||||
/* See if any co-routines readied by events need moving to the ready lists. */
|
||||
prvCheckPendingReadyList();
|
||||
|
||||
/* See if any delayed co-routines have timed out. */
|
||||
prvCheckDelayedList();
|
||||
|
||||
/* Find the highest priority queue that contains ready co-routines. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
|
||||
{
|
||||
if( uxTopCoRoutineReadyPriority == 0 )
|
||||
{
|
||||
/* No more co-routines to check. */
|
||||
return;
|
||||
}
|
||||
--uxTopCoRoutineReadyPriority;
|
||||
}
|
||||
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
|
||||
of the same priority get an equal share of the processor time. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
|
||||
|
||||
/* Call the co-routine. */
|
||||
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
|
||||
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseCoRoutineLists( void )
|
||||
{
|
||||
unsigned portBASE_TYPE uxPriority;
|
||||
|
||||
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
|
||||
{
|
||||
vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
|
||||
}
|
||||
|
||||
vListInitialise( ( xList * ) &xDelayedCoRoutineList1 );
|
||||
vListInitialise( ( xList * ) &xDelayedCoRoutineList2 );
|
||||
vListInitialise( ( xList * ) &xPendingReadyCoRoutineList );
|
||||
|
||||
/* Start with pxDelayedCoRoutineList using list1 and the
|
||||
pxOverflowDelayedCoRoutineList using list2. */
|
||||
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
|
||||
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList )
|
||||
{
|
||||
corCRCB *pxUnblockedCRCB;
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* This function is called from within an interrupt. It can only access
|
||||
event lists and the pending ready list. */
|
||||
pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
vListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
|
||||
|
||||
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
420
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/FreeRTOS.h
Normal file
420
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/FreeRTOS.h
Normal file
@ -0,0 +1,420 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 INC_FREERTOS_H
|
||||
#define INC_FREERTOS_H
|
||||
|
||||
|
||||
/*
|
||||
* Include the generic headers required for the FreeRTOS port being used.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
|
||||
/* Basic FreeRTOS definitions. */
|
||||
#include "projdefs.h"
|
||||
|
||||
/* Application specific configuration options. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/* 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_vTaskCleanUpResources
|
||||
#error Missing definition: INCLUDE_vTaskCleanUpResources 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 configUSE_APPLICATION_TASK_TAG
|
||||
#define configUSE_APPLICATION_TASK_TAG 0
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_uxTaskGetStackHighWaterMark
|
||||
#define INCLUDE_uxTaskGetStackHighWaterMark 0
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_RECURSIVE_MUTEXES
|
||||
#define configUSE_RECURSIVE_MUTEXES 0
|
||||
#endif
|
||||
|
||||
#ifndef configUSE_MUTEXES
|
||||
#define configUSE_MUTEXES 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
|
||||
#undef configMAX_TASK_NAME_LEN
|
||||
#define configMAX_TASK_NAME_LEN 1
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_xTaskResumeFromISR
|
||||
#define INCLUDE_xTaskResumeFromISR 1
|
||||
#endif
|
||||
|
||||
#ifndef INCLUDE_xTaskGetSchedulerState
|
||||
#define INCLUDE_xTaskGetSchedulerState 0
|
||||
#endif
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
/* xTaskGetCurrentTaskHandle is used by the priority inheritance mechanism
|
||||
within the mutex implementation so must be available if mutexes are used. */
|
||||
#undef INCLUDE_xTaskGetCurrentTaskHandle
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
#else
|
||||
#ifndef INCLUDE_xTaskGetCurrentTaskHandle
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 0
|
||||
#endif
|
||||
#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 configQUEUE_REGISTRY_SIZE
|
||||
#define configQUEUE_REGISTRY_SIZE 0
|
||||
#endif
|
||||
|
||||
#if configQUEUE_REGISTRY_SIZE < 1
|
||||
#define configQUEUE_REGISTRY_SIZE 0
|
||||
#define vQueueAddToRegistry( xQueue, pcName )
|
||||
#define vQueueUnregisterQueue( xQueue )
|
||||
#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 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 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 traceQUEUE_CREATE
|
||||
#define traceQUEUE_CREATE( pxNewQueue )
|
||||
#endif
|
||||
|
||||
#ifndef traceQUEUE_CREATE_FAILED
|
||||
#define traceQUEUE_CREATE_FAILED()
|
||||
#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 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_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_DELETE
|
||||
#define traceQUEUE_DELETE( pxQueue )
|
||||
#endif
|
||||
|
||||
#ifndef traceTASK_CREATE
|
||||
#define traceTASK_CREATE( pxNewTCB )
|
||||
#endif
|
||||
|
||||
#ifndef traceTASK_CREATE_FAILED
|
||||
#define traceTASK_CREATE_FAILED( pxNewTCB )
|
||||
#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 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
|
||||
#error If configGENERATE_RUN_TIME_STATS is defined then portGET_RUN_TIME_COUNTER_VALUE must also be defined. portGET_RUN_TIME_COUNTER_VALUE should evaluate to the counter value of the timer/counter peripheral used as the run time counter time base.
|
||||
#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
|
||||
|
||||
#endif /* INC_FREERTOS_H */
|
||||
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 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() \
|
||||
{ \
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ); \
|
||||
\
|
||||
/* 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() \
|
||||
{ \
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ); \
|
||||
\
|
||||
/* 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() \
|
||||
{ \
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ); \
|
||||
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() \
|
||||
{ \
|
||||
extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName ); \
|
||||
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 */
|
||||
|
749
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/croutine.h
Normal file
749
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/croutine.h
Normal file
@ -0,0 +1,749 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 INC_FREERTOS_H
|
||||
#error "#include FreeRTOS.h" must appear in source files before "#include croutine.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef CO_ROUTINE_H
|
||||
#define CO_ROUTINE_H
|
||||
|
||||
#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
|
||||
*<pre>
|
||||
portBASE_TYPE xCoRoutineCreate(
|
||||
crCOROUTINE_CODE pxCoRoutineCode,
|
||||
unsigned portBASE_TYPE uxPriority,
|
||||
unsigned portBASE_TYPE uxIndex
|
||||
);</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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 xTimeToDelay[ 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 );
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xCoRoutineCreate xCoRoutineCreate
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex );
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
void vCoRoutineSchedule( void );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
void vCoRoutineSchedule( void );
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crSTART( xCoRoutineHandle xHandle );</pre>
|
||||
*
|
||||
* This macro MUST always be called at the start of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// 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();
|
||||
}</pre>
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0:
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crEND();</pre>
|
||||
*
|
||||
* This macro MUST always be called at the end of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// 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();
|
||||
}</pre>
|
||||
* \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
|
||||
*<pre>
|
||||
crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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();
|
||||
}</pre>
|
||||
* \defgroup crDELAY crDELAY
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crDELAY( xHandle, xTicksToDelay ) \
|
||||
if( xTicksToDelay > 0 ) \
|
||||
{ \
|
||||
vCoRoutineAddToDelayedList( xTicksToDelay, NULL ); \
|
||||
} \
|
||||
crSET_STATE0( xHandle );
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
crQUEUE_SEND(
|
||||
xCoRoutineHandle xHandle,
|
||||
xQueueHandle pxQueue,
|
||||
void *pvItemToQueue,
|
||||
portTickType xTicksToWait,
|
||||
portBASE_TYPE *pxResult
|
||||
)</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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();
|
||||
}</pre>
|
||||
* \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
|
||||
* <pre>
|
||||
crQUEUE_RECEIVE(
|
||||
xCoRoutineHandle xHandle,
|
||||
xQueueHandle pxQueue,
|
||||
void *pvBuffer,
|
||||
portTickType xTicksToWait,
|
||||
portBASE_TYPE *pxResult
|
||||
)</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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();
|
||||
}</pre>
|
||||
* \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
|
||||
* <pre>
|
||||
crQUEUE_SEND_FROM_ISR(
|
||||
xQueueHandle pxQueue,
|
||||
void *pvItemToQueue,
|
||||
portBASE_TYPE xCoRoutinePreviouslyWoken
|
||||
)</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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 );
|
||||
}
|
||||
}</pre>
|
||||
* \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
|
||||
* <pre>
|
||||
crQUEUE_SEND_FROM_ISR(
|
||||
xQueueHandle pxQueue,
|
||||
void *pvBuffer,
|
||||
portBASE_TYPE * pxCoRoutineWoken
|
||||
)</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
}</pre>
|
||||
* \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 */
|
305
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/list.h
Normal file
305
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/list.h
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V4.3.1
|
||||
|
||||
+ Included local const within listGET_OWNER_OF_NEXT_ENTRY() to assist
|
||||
compiler with optimisation. Thanks B.R.
|
||||
*/
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Definition of the only type of object that a list can contain.
|
||||
*/
|
||||
struct xLIST_ITEM
|
||||
{
|
||||
portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
|
||||
volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */
|
||||
volatile struct xLIST_ITEM * 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 * 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
|
||||
{
|
||||
portTickType xItemValue;
|
||||
volatile struct xLIST_ITEM *pxNext;
|
||||
volatile struct xLIST_ITEM *pxPrevious;
|
||||
};
|
||||
typedef struct xMINI_LIST_ITEM xMiniListItem;
|
||||
|
||||
/*
|
||||
* Definition of the type of queue used by the scheduler.
|
||||
*/
|
||||
typedef struct xLIST
|
||||
{
|
||||
volatile unsigned portBASE_TYPE uxNumberOfItems;
|
||||
volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
|
||||
volatile 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 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 the 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 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 ) ( ( 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( ( pxConstList )->pxIndex == ( xListItem * ) &( ( 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->uxNumberOfItems != ( unsigned portBASE_TYPE ) 0 ) ? ( (&( pxList->xListEnd ))->pxNext->pvOwner ) : ( NULL ) )
|
||||
|
||||
/*
|
||||
* 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 ) ( ( pxListItem )->pvContainer == ( void * ) pxList )
|
||||
|
||||
/*
|
||||
* 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 *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 *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 *pxList, xListItem *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 *pxList, xListItem *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 vListRemove The item to be removed. The item will remove itself from
|
||||
* the list pointed to by it's pxContainer parameter.
|
||||
*
|
||||
* \page vListRemove vListRemove
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListRemove( xListItem *pxItemToRemove );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 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 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 vTaskStartTrace MPU_vTaskStartTrace
|
||||
#define ulTaskEndTrace MPU_ulTaskEndTrace
|
||||
#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 xQueueCreate MPU_xQueueCreate
|
||||
#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 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")))
|
||||
//#define 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 */
|
||||
|
391
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/portable.h
Normal file
391
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/portable.h
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* 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 "../../Source/portable/GCC/Posix/portmacro.h"
|
||||
//#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 );
|
||||
#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 */
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 PROJDEFS_H
|
||||
#define PROJDEFS_H
|
||||
|
||||
/* Defines the prototype to which task functions must conform. */
|
||||
typedef void (*pdTASK_CODE)( void * );
|
||||
|
||||
#define pdTRUE ( 1 )
|
||||
#define pdFALSE ( 0 )
|
||||
|
||||
#define pdPASS ( 1 )
|
||||
#define pdFAIL ( 0 )
|
||||
#define errQUEUE_EMPTY ( 0 )
|
||||
#define errQUEUE_FULL ( 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 */
|
||||
|
||||
|
||||
|
1261
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/queue.h
Normal file
1261
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/queue.h
Normal file
@ -0,0 +1,1261 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 INC_FREERTOS_H
|
||||
#error "#include FreeRTOS.h" must appear in source files before "#include queue.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef QUEUE_H
|
||||
#define QUEUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
|
||||
typedef void * xQueueHandle;
|
||||
|
||||
|
||||
/* For internal use only. */
|
||||
#define queueSEND_TO_BACK ( 0 )
|
||||
#define queueSEND_TO_FRONT ( 1 )
|
||||
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
xQueueHandle xQueueCreate(
|
||||
unsigned portBASE_TYPE uxQueueLength,
|
||||
unsigned portBASE_TYPE uxItemSize
|
||||
);
|
||||
* </pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueCreate xQueueCreate
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueSendToToFront(
|
||||
xQueueHandle xQueue,
|
||||
const void * pvItemToQueue,
|
||||
portTickType xTicksToWait
|
||||
);
|
||||
* </pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueSend xQueueSend
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT )
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueSendToBack(
|
||||
xQueueHandle xQueue,
|
||||
const void * pvItemToQueue,
|
||||
portTickType xTicksToWait
|
||||
);
|
||||
* </pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueSend xQueueSend
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueSend(
|
||||
xQueueHandle xQueue,
|
||||
const void * pvItemToQueue,
|
||||
portTickType xTicksToWait
|
||||
);
|
||||
* </pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueSend xQueueSend
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )
|
||||
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueGenericSend(
|
||||
xQueueHandle xQueue,
|
||||
const void * pvItemToQueue,
|
||||
portTickType xTicksToWait
|
||||
portBASE_TYPE xCopyPosition
|
||||
);
|
||||
* </pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueSend xQueueSend
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueuePeek(
|
||||
xQueueHandle xQueue,
|
||||
void *pvBuffer,
|
||||
portTickType xTicksToWait
|
||||
);</pre>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param pxQueue 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueReceive xQueueReceive
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE )
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueReceive(
|
||||
xQueueHandle xQueue,
|
||||
void *pvBuffer,
|
||||
portTickType xTicksToWait
|
||||
);</pre>
|
||||
*
|
||||
* 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 pxQueue 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueReceive xQueueReceive
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE )
|
||||
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueGenericReceive(
|
||||
xQueueHandle xQueue,
|
||||
void *pvBuffer,
|
||||
portTickType xTicksToWait
|
||||
portBASE_TYPE xJustPeek
|
||||
);</pre>
|
||||
*
|
||||
* 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 pxQueue 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueReceive xQueueReceive
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek );
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );</pre>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \page uxQueueMessagesWaiting uxQueueMessagesWaiting
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>void vQueueDelete( xQueueHandle xQueue );</pre>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \page vQueueDelete vQueueDelete
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
void vQueueDelete( xQueueHandle xQueue );
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueSendToFrontFromISR(
|
||||
xQueueHandle pxQueue,
|
||||
const void *pvItemToQueue,
|
||||
portBASE_TYPE *pxHigherPriorityTaskWoken
|
||||
);
|
||||
</pre>
|
||||
*
|
||||
* 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):
|
||||
<pre>
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
*
|
||||
* \defgroup xQueueSendFromISR xQueueSendFromISR
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueSendToFrontFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_FRONT )
|
||||
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueSendToBackFromISR(
|
||||
xQueueHandle pxQueue,
|
||||
const void *pvItemToQueue,
|
||||
portBASE_TYPE *pxHigherPriorityTaskWoken
|
||||
);
|
||||
</pre>
|
||||
*
|
||||
* 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):
|
||||
<pre>
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
*
|
||||
* \defgroup xQueueSendFromISR xQueueSendFromISR
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueSendFromISR(
|
||||
xQueueHandle pxQueue,
|
||||
const void *pvItemToQueue,
|
||||
portBASE_TYPE *pxHigherPriorityTaskWoken
|
||||
);
|
||||
</pre>
|
||||
*
|
||||
* 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):
|
||||
<pre>
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
*
|
||||
* \defgroup xQueueSendFromISR xQueueSendFromISR
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
#define xQueueSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueGenericSendFromISR(
|
||||
xQueueHandle pxQueue,
|
||||
const void *pvItemToQueue,
|
||||
portBASE_TYPE *pxHigherPriorityTaskWoken,
|
||||
portBASE_TYPE xCopyPosition
|
||||
);
|
||||
</pre>
|
||||
*
|
||||
* 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):
|
||||
<pre>
|
||||
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();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
*
|
||||
* \defgroup xQueueSendFromISR xQueueSendFromISR
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition );
|
||||
|
||||
/**
|
||||
* queue. h
|
||||
* <pre>
|
||||
portBASE_TYPE xQueueReceiveFromISR(
|
||||
xQueueHandle pxQueue,
|
||||
void *pvBuffer,
|
||||
portBASE_TYPE *pxTaskWoken
|
||||
);
|
||||
* </pre>
|
||||
*
|
||||
* Receive an item from a queue. It is safe to use this function from within an
|
||||
* interrupt service routine.
|
||||
*
|
||||
* @param pxQueue 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:
|
||||
<pre>
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
|
||||
* \ingroup QueueManagement
|
||||
*/
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
|
||||
|
||||
/*
|
||||
* Utilities to query queue 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 pxQueue );
|
||||
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue );
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue );
|
||||
|
||||
|
||||
/*
|
||||
* 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 pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
|
||||
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, 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 pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
|
||||
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
|
||||
signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );
|
||||
signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
|
||||
|
||||
/*
|
||||
* For internal use only. Use xSemaphoreCreateMutex() or
|
||||
* xSemaphoreCreateCounting() instead of calling these functions directly.
|
||||
*/
|
||||
xQueueHandle xQueueCreateMutex( void );
|
||||
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );
|
||||
|
||||
/*
|
||||
* For internal use only. Use xSemaphoreTakeMutexRecursive() or
|
||||
* xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
|
||||
*/
|
||||
portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime );
|
||||
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );
|
||||
|
||||
/*
|
||||
* 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 );
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* QUEUE_H */
|
||||
|
711
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/semphr.h
Normal file
711
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/semphr.h
Normal file
@ -0,0 +1,711 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 INC_FREERTOS_H
|
||||
#error "#include FreeRTOS.h" must appear in source files before "#include semphr.h"
|
||||
#endif
|
||||
|
||||
#ifndef SEMAPHORE_H
|
||||
#define SEMAPHORE_H
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
typedef xQueueHandle xSemaphoreHandle;
|
||||
|
||||
#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1 )
|
||||
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0 )
|
||||
#define semGIVE_BLOCK_TIME ( ( portTickType ) 0 )
|
||||
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define vSemaphoreCreateBinary( xSemaphore ) { \
|
||||
xSemaphore = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \
|
||||
if( xSemaphore != NULL ) \
|
||||
{ \
|
||||
xSemaphoreGive( xSemaphore ); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>xSemaphoreTake(
|
||||
* xSemaphoreHandle xSemaphore,
|
||||
* portTickType xBlockTime
|
||||
* )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xSemaphoreTake xSemaphoreTake
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* xSemaphoreTakeRecursive(
|
||||
* xSemaphoreHandle xMutex,
|
||||
* portTickType xBlockTime
|
||||
* )
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \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
|
||||
* <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xSemaphoreGive xSemaphoreGive
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \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
|
||||
* <pre>
|
||||
xSemaphoreGiveFromISR(
|
||||
xSemaphoreHandle xSemaphore,
|
||||
signed portBASE_TYPE *pxHigherPriorityTaskWoken
|
||||
)</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
\#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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) xSemaphore, NULL, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>xSemaphoreHandle xSemaphoreCreateMutex( void )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreCreateMutex() xQueueCreateMutex()
|
||||
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex()
|
||||
|
||||
/**
|
||||
* semphr. h
|
||||
* <pre>xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )</pre>
|
||||
*
|
||||
* <i>Macro</i> 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
|
||||
* \ingroup Semaphores
|
||||
*/
|
||||
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount )
|
||||
|
||||
|
||||
#endif /* SEMAPHORE_H */
|
||||
|
||||
|
1263
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/task.h
Normal file
1263
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/include/task.h
Normal file
@ -0,0 +1,1263 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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 INC_FREERTOS_H
|
||||
#error "#include FreeRTOS.h" must appear in source files before "#include task.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef TASK_H
|
||||
#define TASK_H
|
||||
|
||||
#include "portable.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* MACROS AND DEFINITIONS
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#define tskKERNEL_VERSION_NUMBER "V6.0.4"
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* \page xTaskHandle xTaskHandle
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
typedef void * xTaskHandle;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Defines the priority used by the idle task. This must not be modified.
|
||||
*
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0 )
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*
|
||||
* Macro for forcing a context switch.
|
||||
*
|
||||
* \page 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!
|
||||
*
|
||||
* \page 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!
|
||||
*
|
||||
* \page taskEXIT_CRITICAL taskEXIT_CRITICAL
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*
|
||||
* Macro to disable all maskable interrupts.
|
||||
*
|
||||
* \page taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*
|
||||
* Macro to enable microcontroller interrupts.
|
||||
*
|
||||
* \page taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
|
||||
|
||||
/* Definitions returned by xTaskGetSchedulerState(). */
|
||||
#define taskSCHEDULER_NOT_STARTED 0
|
||||
#define taskSCHEDULER_RUNNING 1
|
||||
#define taskSCHEDULER_SUSPENDED 2
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CREATION API
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*<pre>
|
||||
portBASE_TYPE xTaskCreate(
|
||||
pdTASK_CODE pvTaskCode,
|
||||
const char * const pcName,
|
||||
unsigned short usStackDepth,
|
||||
void *pvParameters,
|
||||
unsigned portBASE_TYPE uxPriority,
|
||||
xTaskHandle *pvCreatedTask
|
||||
);</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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 );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xTaskCreate xTaskCreate
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) )
|
||||
|
||||
/**
|
||||
* task. h
|
||||
*<pre>
|
||||
portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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( ;; );
|
||||
}
|
||||
</pre>
|
||||
* \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
|
||||
*<pre>
|
||||
void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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).
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xTaskCreateRestricted xTaskCreateRestricted
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskDelete( xTaskHandle pxTask );</pre>
|
||||
*
|
||||
* 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 pxTask The handle of the task to be deleted. Passing NULL will
|
||||
* cause the calling task to be deleted.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
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 );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vTaskDelete vTaskDelete
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
void vTaskDelete( xTaskHandle pxTask ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CONTROL API
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskDelay( portTickType xTicksToDelay );</pre>
|
||||
*
|
||||
* 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
|
||||
* <pre>void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
// 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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vTaskDelayUntil vTaskDelayUntil
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );</pre>
|
||||
*
|
||||
* 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 pxTask 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 pxTask.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup uxTaskPriorityGet uxTaskPriorityGet
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );</pre>
|
||||
*
|
||||
* 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 pxTask 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:
|
||||
<pre>
|
||||
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 );
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vTaskPrioritySet vTaskPrioritySet
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskSuspend( xTaskHandle pxTaskToSuspend );</pre>
|
||||
*
|
||||
* 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 pxTaskToSuspend Handle to the task being suspended. Passing a NULL
|
||||
* handle will cause the calling task to be suspended.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vTaskSuspend vTaskSuspend
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
void vTaskSuspend( xTaskHandle pxTaskToSuspend ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskResume( xTaskHandle pxTaskToResume );</pre>
|
||||
*
|
||||
* 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 pxTaskToResume Handle to the task being readied.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vTaskResume vTaskResume
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
void vTaskResume( xTaskHandle pxTaskToResume ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void xTaskResumeFromISR( xTaskHandle pxTaskToResume );</pre>
|
||||
*
|
||||
* 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 pxTaskToResume Handle to the task being readied.
|
||||
*
|
||||
* \defgroup vTaskResumeFromISR vTaskResumeFromISR
|
||||
* \ingroup TaskCtrl
|
||||
*/
|
||||
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* SCHEDULER CONTROL
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskStartScheduler( void );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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 ()
|
||||
}
|
||||
</pre>
|
||||
*
|
||||
* \defgroup vTaskStartScheduler vTaskStartScheduler
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
void vTaskStartScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskEndScheduler( void );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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.
|
||||
}
|
||||
</pre>
|
||||
*
|
||||
* \defgroup vTaskEndScheduler vTaskEndScheduler
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
void vTaskEndScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>void vTaskSuspendAll( void );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vTaskSuspendAll vTaskSuspendAll
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>char xTaskResumeAll( void );</pre>
|
||||
*
|
||||
* 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:
|
||||
<pre>
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xTaskResumeAll xTaskResumeAll
|
||||
* \ingroup SchedulerControl
|
||||
*/
|
||||
signed portBASE_TYPE xTaskResumeAll( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <pre>signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask );</pre>
|
||||
*
|
||||
* 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
|
||||
* <PRE>volatile portTickType xTaskGetTickCount( void );</PRE>
|
||||
*
|
||||
* @return The count of ticks since vTaskStartScheduler was called.
|
||||
*
|
||||
* \page xTaskGetTickCount xTaskGetTickCount
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
portTickType xTaskGetTickCount( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <PRE>unsigned short uxTaskGetNumberOfTasks( void );</PRE>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \page uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <PRE>void vTaskList( char *pcWriteBuffer );</PRE>
|
||||
*
|
||||
* configUSE_TRACE_FACILITY must be defined as 1 for this function to be
|
||||
* available. See the configuration section for more information.
|
||||
*
|
||||
* NOTE: 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').
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \page vTaskList vTaskList
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
void vTaskList( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <PRE>void vTaskGetRunTimeStats( char *pcWriteBuffer );</PRE>
|
||||
*
|
||||
* configGENERATE_RUN_TIME_STATS must 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: 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* \page vTaskGetRunTimeStats vTaskGetRunTimeStats
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <PRE>void vTaskStartTrace( char * pcBuffer, unsigned portBASE_TYPE uxBufferSize );</PRE>
|
||||
*
|
||||
* Starts a real time kernel activity trace. The trace logs the identity of
|
||||
* which task is running when.
|
||||
*
|
||||
* The trace file is stored in binary format. A separate DOS utility called
|
||||
* convtrce.exe is used to convert this into a tab delimited text file which
|
||||
* can be viewed and plotted in a spread sheet.
|
||||
*
|
||||
* @param pcBuffer The buffer into which the trace will be written.
|
||||
*
|
||||
* @param ulBufferSize The size of pcBuffer in bytes. The trace will continue
|
||||
* until either the buffer in full, or ulTaskEndTrace () is called.
|
||||
*
|
||||
* \page vTaskStartTrace vTaskStartTrace
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task. h
|
||||
* <PRE>unsigned long ulTaskEndTrace( void );</PRE>
|
||||
*
|
||||
* Stops a kernel activity trace. See vTaskStartTrace ().
|
||||
*
|
||||
* @return The number of bytes that have been written into the trace buffer.
|
||||
*
|
||||
* \page usTaskEndTrace usTaskEndTrace
|
||||
* \ingroup TaskUtils
|
||||
*/
|
||||
unsigned long ulTaskEndTrace( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task.h
|
||||
* <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );</PRE>
|
||||
*
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
* task.h
|
||||
* <pre>void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );</pre>
|
||||
*
|
||||
* 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
|
||||
* <pre>void xTaskGetApplicationTaskTag( xTaskHandle xTask );</pre>
|
||||
*
|
||||
* Returns the pxHookFunction value assigned to the task xTask.
|
||||
*/
|
||||
pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* task.h
|
||||
* <pre>portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );</pre>
|
||||
*
|
||||
* 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;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* 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.
|
||||
*/
|
||||
void vTaskIncrementTick( 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( const 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 AN
|
||||
* INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
|
||||
*
|
||||
* INCLUDE_vTaskCleanUpResources and INCLUDE_vTaskSuspend must be defined as 1
|
||||
* for this function to be available.
|
||||
* See the configuration section for more information.
|
||||
*
|
||||
* Empties the ready and delayed queues of task control blocks, freeing the
|
||||
* memory allocated for the task control block and task stacks as it goes.
|
||||
*/
|
||||
void vTaskCleanUpResources( void ) 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 pvTaskCode, 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;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* TASK_H */
|
||||
|
||||
|
||||
|
191
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/list.c
Normal file
191
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/list.c
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC LIST API documented in list.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
void vListInitialise( xList *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 );
|
||||
|
||||
/* 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 );
|
||||
pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd );
|
||||
|
||||
pxList->uxNumberOfItems = 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInitialiseItem( xListItem *pxItem )
|
||||
{
|
||||
/* Make sure the list item is not recorded as being on a list. */
|
||||
pxItem->pvContainer = NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsertEnd( xList *pxList, xListItem *pxNewListItem )
|
||||
{
|
||||
volatile 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. This means it has to be the item pointed to by
|
||||
the pxIndex member. */
|
||||
pxIndex = pxList->pxIndex;
|
||||
|
||||
pxNewListItem->pxNext = pxIndex->pxNext;
|
||||
pxNewListItem->pxPrevious = pxList->pxIndex;
|
||||
pxIndex->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem;
|
||||
pxIndex->pxNext = ( volatile xListItem * ) pxNewListItem;
|
||||
pxList->pxIndex = ( volatile xListItem * ) pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. */
|
||||
pxNewListItem->pvContainer = ( void * ) pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsert( xList *pxList, xListItem *pxNewListItem )
|
||||
{
|
||||
volatile 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.
|
||||
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 )
|
||||
{
|
||||
/* There is nothing to do here, we are just iterating to the
|
||||
wanted insertion position. */
|
||||
}
|
||||
}
|
||||
|
||||
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||
pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem;
|
||||
pxNewListItem->pxPrevious = pxIterator;
|
||||
pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. This allows fast removal of the
|
||||
item later. */
|
||||
pxNewListItem->pvContainer = ( void * ) pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListRemove( xListItem *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 )--;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
@ -0,0 +1,1098 @@
|
||||
/*
|
||||
Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk
|
||||
Contributed to FreeRTOS.org V5.3.0.
|
||||
|
||||
This file is part of the FreeRTOS.org distribution.
|
||||
|
||||
FreeRTOS.org 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.
|
||||
|
||||
FreeRTOS.org 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 along
|
||||
with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
A special exception to the GPL is included to allow you to distribute a
|
||||
combined work that includes FreeRTOS.org without being obliged to provide
|
||||
the source code for any proprietary components. See the licensing section
|
||||
of http://www.FreeRTOS.org for full details.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* This is a concise, step by step, 'hands on' guide that describes both *
|
||||
* general multitasking concepts and FreeRTOS specifics. It presents and *
|
||||
* explains numerous examples that are written using the FreeRTOS API. *
|
||||
* Full source code for all the examples is provided in an accompanying *
|
||||
* .zip file. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
Please ensure to read the configuration and relevant port sections of the
|
||||
online documentation.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Posix port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/times.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
// #define COND_SIGNALING
|
||||
// #define CHECK_TASK_RESUMES
|
||||
#define RUNNING_THREAD_MUTEX
|
||||
#endif
|
||||
|
||||
/* Parameters to pass to the newly created pthread. */
|
||||
typedef struct XPARAMS
|
||||
{
|
||||
pdTASK_CODE pxCode;
|
||||
void *pvParams;
|
||||
} xParams;
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting variable. */
|
||||
typedef struct THREAD_SUSPENSIONS
|
||||
{
|
||||
pthread_t hThread;
|
||||
pthread_cond_t * hCond;
|
||||
pthread_mutex_t * hMutex;
|
||||
xTaskHandle hTask;
|
||||
portBASE_TYPE xThreadState;
|
||||
unsigned portBASE_TYPE uxCriticalNesting;
|
||||
} xThreadState;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static xThreadState *pxThreads;
|
||||
static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT;
|
||||
static pthread_attr_t xThreadAttributes;
|
||||
#ifdef RUNNING_THREAD_MUTEX
|
||||
static pthread_mutex_t xRunningThread = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t xSwappingThreadMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t xIrqMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_t hMainThread = ( pthread_t )NULL;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static volatile portBASE_TYPE xSentinel = 0;
|
||||
static volatile portBASE_TYPE xRunning = pdFALSE;
|
||||
static volatile portBASE_TYPE xSuspended = pdFALSE;
|
||||
static volatile portBASE_TYPE xStarted = pdFALSE;
|
||||
static volatile portBASE_TYPE xHandover = 0;
|
||||
static volatile portBASE_TYPE xSchedulerEnd = pdFALSE;
|
||||
static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE;
|
||||
static volatile portBASE_TYPE xServicingTick = pdFALSE;
|
||||
static volatile portBASE_TYPE xPendYield = pdFALSE;
|
||||
static volatile portLONG lIndexOfLastAddedTask = 0;
|
||||
static volatile unsigned portBASE_TYPE uxCriticalNesting;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void *prvWaitForStart( void * pvParams );
|
||||
static void prvSuspendSignalHandler(int sig);
|
||||
static void prvSetupSignalsAndSchedulerPolicy( void );
|
||||
static void pauseThread( portBASE_TYPE pauseMode );
|
||||
static pthread_t prvGetThreadHandle( xTaskHandle hTask );
|
||||
#ifdef COND_SIGNALING
|
||||
static pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask );
|
||||
static pthread_mutex_t * prvGetMutexHandle( xTaskHandle hTask );
|
||||
#endif
|
||||
static xTaskHandle prvGetTaskHandle( pthread_t hThread );
|
||||
static portLONG prvGetFreeThreadState( void );
|
||||
static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting );
|
||||
static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId );
|
||||
static void prvDeleteThread( void *xThreadId );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void vPortYield( void );
|
||||
void vPortSystemTickHandler( int sig );
|
||||
|
||||
#define THREAD_PAUSE_CREATED 0
|
||||
#define THREAD_PAUSE_YIELD 1
|
||||
#define THREAD_PAUSE_INTERRUPT 2
|
||||
|
||||
FILE * fid;
|
||||
|
||||
//#define DEBUG_OUTPUT
|
||||
#define ERROR_OUTPUT
|
||||
#ifdef DEBUG_OUTPUT
|
||||
|
||||
static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \
|
||||
( \
|
||||
(NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \
|
||||
(fprintf( fid, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \
|
||||
(fprintf( fid, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \
|
||||
|1)?( \
|
||||
((fprintf( fid, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \
|
||||
):0 ):0 )
|
||||
|
||||
#define debug_error debug_printf
|
||||
|
||||
int real_pthread_mutex_lock(pthread_mutex_t* mutex) {
|
||||
return pthread_mutex_lock(mutex);
|
||||
}
|
||||
int real_pthread_mutex_unlock(pthread_mutex_t* mutex) {
|
||||
return pthread_mutex_unlock(mutex);
|
||||
}
|
||||
#define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 )
|
||||
#define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 )
|
||||
#define pthread_kill(thread,signal) ( (debug_printf("Sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 )
|
||||
#define pthread_cond_signal( hCond ) (debug_printf( "pthread_cond_signals(%li)\r\n", *((long int *) hCond) ) ? 1 : pthread_cond_signal( hCond ) )
|
||||
#define pthread_cond_timedwait( hCond, hMutex, it ) (debug_printf( "pthread_cond_timedwait(%li,%li)\r\n", *((long int *) hCond), *((long int *) hMutex )) ? 1 : pthread_cond_timedwait( hCond, hMutex, it ) )
|
||||
#define pthread_sigmask( how, set, out ) (debug_printf( "pthread_sigmask( %i, %li )\r\n", how, *((long int*) set) ) ? 1 : pthread_sigmask( how, set, out ) )
|
||||
|
||||
#else
|
||||
#ifdef ERROR_OUTPUT
|
||||
static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define debug_error(...) ( (pthread_mutex_lock( &xPrintfMutex )|1)?( \
|
||||
( \
|
||||
(NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \
|
||||
(fprintf( fid, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \
|
||||
(fprintf( fid, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \
|
||||
|1)?( \
|
||||
((fprintf( fid, __VA_ARGS__ )|1)?pthread_mutex_unlock( &xPrintfMutex ):0) \
|
||||
):0 ):0 )
|
||||
|
||||
#define debug_printf(...)
|
||||
#else
|
||||
#define debug_printf(...)
|
||||
#define debug_error(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
void vPortStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
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 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 STRUCT. */
|
||||
#endif
|
||||
|
||||
xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */
|
||||
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */
|
||||
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 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; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
|
||||
#endif
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
unsigned portBASE_TYPE uxCriticalNesting;
|
||||
#endif
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
|
||||
#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; /*< Used for calculating how much CPU time each task is utilising. */
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
||||
tskTCB *debug_task_handle;
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
|
||||
{
|
||||
/* Should actually keep this struct on the stack. */
|
||||
xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) );
|
||||
|
||||
debug_printf("pxPortInitialiseStack\r\n");
|
||||
|
||||
(void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy );
|
||||
|
||||
if ( (pthread_t)NULL == hMainThread )
|
||||
{
|
||||
hMainThread = pthread_self();
|
||||
}
|
||||
|
||||
/* No need to join the threads. */
|
||||
pthread_attr_init( &xThreadAttributes );
|
||||
pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED );
|
||||
|
||||
/* Add the task parameters. */
|
||||
pxThisThreadParams->pxCode = pxCode;
|
||||
pxThisThreadParams->pvParams = pvParameters;
|
||||
|
||||
vPortEnterCritical();
|
||||
|
||||
lIndexOfLastAddedTask = prvGetFreeThreadState();
|
||||
|
||||
debug_printf( "Got index for new task %i\r\n", lIndexOfLastAddedTask );
|
||||
|
||||
#ifdef COND_SIGNALING
|
||||
/* Create a condition signal for this thread */
|
||||
pxThreads[ lIndexOfLastAddedTask ].hCond = ( pthread_cond_t *) malloc( sizeof( pthread_cond_t ) );
|
||||
assert( 0 == pthread_cond_init( pxThreads[ lIndexOfLastAddedTask ].hCond , NULL ) ); //&condAttr ) );
|
||||
debug_printf("Cond: %li\r\n", *( (long int *) &pxThreads[ lIndexOfLastAddedTask ].hCond) );
|
||||
|
||||
/* Create a condition mutex for this thread */
|
||||
pxThreads[ lIndexOfLastAddedTask ].hMutex = ( pthread_mutex_t *) malloc( sizeof( pthread_mutex_t ) );
|
||||
assert( 0 == pthread_mutex_init( pxThreads[ lIndexOfLastAddedTask ].hMutex, NULL ) ); //&mutexAttr ) );
|
||||
debug_printf("Mutex: %li\r\n", *( (long int *) &pxThreads[ lIndexOfLastAddedTask ].hMutex) );
|
||||
#endif
|
||||
|
||||
/* Create a thread and store it's handle number */
|
||||
xSentinel = 0;
|
||||
assert( 0 == pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) );
|
||||
|
||||
/* Wait until the task suspends. */
|
||||
while ( xSentinel == 0 );
|
||||
vPortExitCritical();
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortStartFirstTask( void )
|
||||
{
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
debug_printf("vPortStartFirstTask\r\n");
|
||||
|
||||
/* Start the first task. */
|
||||
vPortEnableInterrupts();
|
||||
xRunning = 1;
|
||||
|
||||
/* Start the first task. */
|
||||
#ifdef COND_SIGNALING
|
||||
pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() );
|
||||
assert( pthread_cond_signal( hCond ) == 0 );
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
portBASE_TYPE xPortStartScheduler( void )
|
||||
{
|
||||
portBASE_TYPE xResult;
|
||||
sigset_t xSignalToBlock;
|
||||
portLONG lIndex;
|
||||
|
||||
debug_printf( "xPortStartScheduler\r\n" );
|
||||
|
||||
/* Establish the signals to block before they are needed. */
|
||||
sigfillset( &xSignalToBlock );
|
||||
sigaddset( &xSignalToBlock, SIG_SUSPEND );
|
||||
|
||||
/* Block until the end */
|
||||
(void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL );
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
pxThreads[ lIndex ].uxCriticalNesting = 0;
|
||||
}
|
||||
|
||||
fid = fopen("log.txt", "w");
|
||||
|
||||
/* Start the first task. Will not return unless all threads are killed. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
int i = 0;
|
||||
struct timespec x;
|
||||
usleep(1000000);
|
||||
while( pdTRUE != xSchedulerEnd ) {
|
||||
x.tv_sec=0;
|
||||
x.tv_nsec=portTICK_RATE_MICROSECONDS * 1000;
|
||||
nanosleep(&x,NULL);
|
||||
i++;
|
||||
// if(i % 1000 == 0) {
|
||||
// printf("."); fflush(stdout);
|
||||
// }
|
||||
while(xInterruptsEnabled == pdFALSE){ // Don't call while in interrupt
|
||||
printf("."); fflush(stdout);
|
||||
}
|
||||
vPortSystemTickHandler(SIG_TICK);
|
||||
}
|
||||
|
||||
debug_printf( "Cleaning Up, Exiting.\n" );
|
||||
/* Cleanup the mutexes */
|
||||
xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex );
|
||||
xResult = pthread_mutex_destroy( &xSwappingThreadMutex );
|
||||
vPortFree( (void *)pxThreads );
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
portBASE_TYPE xNumberOfThreads;
|
||||
portBASE_TYPE xResult;
|
||||
|
||||
|
||||
for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ )
|
||||
{
|
||||
if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread )
|
||||
{
|
||||
/* Kill all of the threads, they are in the detached state. */
|
||||
xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread );
|
||||
}
|
||||
}
|
||||
|
||||
/* Signal the scheduler to exit its loop. */
|
||||
xSchedulerEnd = pdTRUE;
|
||||
(void)pthread_kill( hMainThread, SIG_RESUME );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYieldFromISR( void )
|
||||
{
|
||||
/* Calling Yield from a Interrupt/Signal handler often doesn't work because the
|
||||
* xSwappingThreadMutex is already owned by an original call to Yield. Therefore,
|
||||
* simply indicate that a yield is required soon.
|
||||
*/
|
||||
|
||||
xPendYield = pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
vPortDisableInterrupts();
|
||||
uxCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
/* Check for unmatched exits. */
|
||||
if ( uxCriticalNesting > 0 )
|
||||
{
|
||||
uxCriticalNesting--;
|
||||
}
|
||||
|
||||
/* If we have reached 0 then re-enable the interrupts. */
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
/* Have we missed ticks? This is the equivalent of pending an interrupt. */
|
||||
if ( pdTRUE == xPendYield )
|
||||
{
|
||||
xPendYield = pdFALSE;
|
||||
vPortYield();
|
||||
}
|
||||
vPortEnableInterrupts();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void )
|
||||
{
|
||||
pthread_t xTaskToSuspend;
|
||||
pthread_t xTaskToResume;
|
||||
sigset_t xSignals;
|
||||
tskTCB * oldTask, * newTask;
|
||||
|
||||
/* We must mask the suspend signal here, because otherwise there can be an */
|
||||
/* interrupt while in pthread_mutex_lock and that will cause the next thread */
|
||||
/* to deadlock when it tries to get this mutex */
|
||||
|
||||
debug_printf( "Entering\r\n" );
|
||||
|
||||
sigemptyset( &xSignals );
|
||||
sigaddset( &xSignals, SIG_SUSPEND );
|
||||
pthread_sigmask( SIG_SETMASK, &xSignals, NULL );
|
||||
|
||||
assert( pthread_mutex_lock( &xSwappingThreadMutex ) == 0);
|
||||
|
||||
oldTask = xTaskGetCurrentTaskHandle();
|
||||
xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() );
|
||||
if(xTaskToSuspend != pthread_self() ) {
|
||||
/* This means between masking the interrupt and getting the lock, there was an interrupt */
|
||||
/* and this task should suspend. Release the lock, then unmask interrupts to go ahead and */
|
||||
/* service the signal */
|
||||
|
||||
assert( 0 == pthread_mutex_unlock( &xSwappingThreadMutex ) );
|
||||
debug_printf( "The current task isn't even us, letting interrupt happen. Watch for swap.\r\n" );
|
||||
/* Now we are resuming, want to be able to catch this interrupt again */
|
||||
sigemptyset( &xSignals );
|
||||
pthread_sigmask( SIG_SETMASK, &xSignals, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
xStarted = pdFALSE;
|
||||
|
||||
/* Get new task then release the task switching mutex */
|
||||
vTaskSwitchContext();
|
||||
newTask = xTaskGetCurrentTaskHandle();
|
||||
xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
if ( pthread_self() != xTaskToResume )
|
||||
{
|
||||
/* Remember and switch the critical nesting. */
|
||||
prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting );
|
||||
uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume );
|
||||
|
||||
debug_error( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName);
|
||||
|
||||
#ifdef COND_SIGNALING
|
||||
/* Set resume condition for specific thread */
|
||||
pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() );
|
||||
assert( pthread_cond_signal( hCond ) == 0 );
|
||||
#endif
|
||||
#ifdef CHECK_TASK_RESUMES
|
||||
while( xStarted == pdFALSE )
|
||||
debug_printf( "Waiting for task to resume\r\n" );
|
||||
#endif
|
||||
|
||||
debug_printf( "Detected task resuming. Pausing this task\r\n" );
|
||||
|
||||
/* Release swapping thread mutex and pause self */
|
||||
assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0);
|
||||
pauseThread( THREAD_PAUSE_YIELD );
|
||||
}
|
||||
else {
|
||||
assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0);
|
||||
}
|
||||
|
||||
/* Now we are resuming, want to be able to catch this interrupt again */
|
||||
sigemptyset( &xSignals );
|
||||
pthread_sigmask( SIG_SETMASK, &xSignals, NULL);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDisableInterrupts( void )
|
||||
{
|
||||
//debug_printf("\r\n");
|
||||
assert( pthread_mutex_lock( &xIrqMutex ) == 0);
|
||||
xInterruptsEnabled = pdFALSE;
|
||||
assert( pthread_mutex_unlock( &xIrqMutex) == 0);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnableInterrupts( void )
|
||||
{
|
||||
//debug_printf("\r\n");
|
||||
assert( pthread_mutex_lock( &xIrqMutex ) == 0);
|
||||
xInterruptsEnabled = pdTRUE;
|
||||
assert( pthread_mutex_unlock( &xIrqMutex) == 0);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portBASE_TYPE xPortSetInterruptMask( void )
|
||||
{
|
||||
portBASE_TYPE xReturn = xInterruptsEnabled;
|
||||
debug_printf("\r\n");
|
||||
xInterruptsEnabled = pdFALSE;
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( portBASE_TYPE xMask )
|
||||
{
|
||||
debug_printf("\r\n");
|
||||
xInterruptsEnabled = xMask;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
void vPortSystemTickHandler( int sig )
|
||||
{
|
||||
pthread_t xTaskToSuspend;
|
||||
pthread_t xTaskToResume;
|
||||
tskTCB * oldTask, * newTask;
|
||||
|
||||
debug_printf( "\r\n\r\n" );
|
||||
debug_printf( "(xInterruptsEnabled = %i, xServicingTick = %i)\r\n", (int) xInterruptsEnabled != 0, (int) xServicingTick != 0);
|
||||
if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) )
|
||||
{
|
||||
// debug_printf( "Checking for lock ...\r\n" );
|
||||
if ( 0 == pthread_mutex_trylock( &xSwappingThreadMutex ) )
|
||||
{
|
||||
debug_printf( "Handling\r\n");
|
||||
xServicingTick = pdTRUE;
|
||||
|
||||
oldTask = xTaskGetCurrentTaskHandle();
|
||||
xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
/* Tick Increment. */
|
||||
vTaskIncrementTick();
|
||||
|
||||
/* Select Next Task. */
|
||||
#if ( configUSE_PREEMPTION == 1 )
|
||||
vTaskSwitchContext();
|
||||
#endif
|
||||
|
||||
newTask = xTaskGetCurrentTaskHandle();
|
||||
xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
debug_printf( "Want %s running\r\n", newTask->pcTaskName );
|
||||
/* The only thread that can process this tick is the running thread. */
|
||||
if ( xTaskToSuspend != xTaskToResume )
|
||||
{
|
||||
xSuspended = pdFALSE;
|
||||
xStarted = pdFALSE;
|
||||
|
||||
/* Remember and switch the critical nesting. */
|
||||
prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting );
|
||||
uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume );
|
||||
|
||||
debug_printf( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName);
|
||||
|
||||
#ifdef CHECK_TASK_RESUMES
|
||||
/* It shouldn't be possible for a second task swap to happen while waiting for this because */
|
||||
/* they can't get the xSwappingThreadMutex */
|
||||
while( xSuspended == pdFALSE )
|
||||
#endif
|
||||
{
|
||||
assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0);
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
#ifdef CHECK_TASK_RESUMES
|
||||
while( xStarted == pdFALSE)
|
||||
#endif
|
||||
{
|
||||
|
||||
#ifdef COND_SIGNALING
|
||||
// Set resume condition for specific thread
|
||||
pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() );
|
||||
assert( pthread_cond_signal( hCond ) == 0 );
|
||||
#endif
|
||||
assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0);
|
||||
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
debug_printf( "Swapped From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); }
|
||||
else
|
||||
{
|
||||
// debug_error ("Want %s running \r\n", newTask->pcTaskName );
|
||||
}
|
||||
xServicingTick = pdFALSE;
|
||||
(void)pthread_mutex_unlock( &xSwappingThreadMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_error( "Pending yield here (portYield has lock - hopefully)\r\n" );
|
||||
xPendYield = pdTRUE;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf( "Pending yield or here\r\n");
|
||||
xPendYield = pdTRUE;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortForciblyEndThread( void *pxTaskToDelete )
|
||||
{
|
||||
xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete;
|
||||
pthread_t xTaskToDelete;
|
||||
pthread_t xTaskToResume;
|
||||
portBASE_TYPE xResult;
|
||||
|
||||
printf("vPortForciblyEndThread\r\n");
|
||||
|
||||
if ( 0 == pthread_mutex_lock( &xSwappingThreadMutex ) )
|
||||
{
|
||||
xTaskToDelete = prvGetThreadHandle( hTaskToDelete );
|
||||
xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() );
|
||||
|
||||
if ( xTaskToResume == xTaskToDelete )
|
||||
{
|
||||
/* This is a suicidal thread, need to select a different task to run. */
|
||||
vTaskSwitchContext();
|
||||
xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() );
|
||||
}
|
||||
|
||||
if ( pthread_self() != xTaskToDelete )
|
||||
{
|
||||
/* Cancelling a thread that is not me. */
|
||||
if ( xTaskToDelete != ( pthread_t )NULL )
|
||||
{
|
||||
/* Send a signal to wake the task so that it definitely cancels. */
|
||||
pthread_testcancel();
|
||||
xResult = pthread_cancel( xTaskToDelete );
|
||||
/* Pthread Clean-up function will note the cancellation. */
|
||||
}
|
||||
(void)pthread_mutex_unlock( &xSwappingThreadMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Resume the other thread. */
|
||||
/* Assert zero - I never fixed this functionality */
|
||||
assert( 0 );
|
||||
|
||||
/* Pthread Clean-up function will note the cancellation. */
|
||||
/* Release the execution. */
|
||||
uxCriticalNesting = 0;
|
||||
vPortEnableInterrupts();
|
||||
(void)pthread_mutex_unlock( &xSwappingThreadMutex );
|
||||
/* Commit suicide */
|
||||
pthread_exit( (void *)1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *prvWaitForStart( void * pvParams )
|
||||
{
|
||||
xParams * pxParams = ( xParams * )pvParams;
|
||||
pdTASK_CODE pvCode = pxParams->pxCode;
|
||||
void * pParams = pxParams->pvParams;
|
||||
vPortFree( pvParams );
|
||||
|
||||
pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() );
|
||||
|
||||
/* want to block suspend when not the active thread */
|
||||
sigset_t xSignals;
|
||||
sigemptyset( &xSignals );
|
||||
sigaddset( &xSignals, SIG_SUSPEND );
|
||||
assert( pthread_sigmask( SIG_BLOCK, &xSignals, NULL ) == 0);
|
||||
|
||||
/* Because the FreeRTOS creates the TCB stack, which in this implementation */
|
||||
/* creates a thread, we need to wait until the task handle is added before */
|
||||
/* trying to pause. Must set xSentinel high so the creating task knows we're */
|
||||
/* here */
|
||||
|
||||
debug_printf("Thread started, waiting till handle is added\r\n");
|
||||
|
||||
xSentinel = 1;
|
||||
|
||||
while( prvGetTaskHandle( pthread_self() ) == NULL ){
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
debug_printf("Handle added, pausing\r\n");
|
||||
|
||||
/* Want to delay briefly until we have explicit resume signal as otherwise the */
|
||||
/* current task variable might be in the wrong state */
|
||||
pauseThread( THREAD_PAUSE_CREATED );
|
||||
debug_printf("Starting first run\r\n");
|
||||
|
||||
sigemptyset( &xSignals );
|
||||
assert( pthread_sigmask( SIG_SETMASK, &xSignals, NULL ) == 0);
|
||||
|
||||
pvCode( pParams );
|
||||
|
||||
pthread_cleanup_pop( 1 );
|
||||
return (void *)NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void pauseThread( portBASE_TYPE pauseMode )
|
||||
{
|
||||
debug_printf( "Pausing thread %li. Set xSuspended false\r\n", (long int) pthread_self() );
|
||||
|
||||
//assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) );
|
||||
|
||||
#ifdef RUNNING_THREAD_MUTEX
|
||||
if( pauseMode != THREAD_PAUSE_CREATED )
|
||||
assert( 0 == pthread_mutex_unlock( &xRunningThread ) );
|
||||
#endif
|
||||
|
||||
#ifdef COND_SIGNALING
|
||||
int xResult;
|
||||
xTaskHandle hTask = prvGetTaskHandle( pthread_self() );
|
||||
pthread_cond_t * hCond = prvGetConditionHandle( hTask );
|
||||
pthread_mutex_t * hMutex = prvGetMutexHandle( hTask );
|
||||
debug_printf("Cond: %li\r\n", *( (long int *) hCond) );
|
||||
debug_printf("Mutex: %li\r\n", *( (long int *) hMutex) );
|
||||
|
||||
struct timeval tv;
|
||||
struct timespec ts;
|
||||
gettimeofday( &tv, NULL );
|
||||
ts.tv_sec = tv.tv_sec + 0;
|
||||
#endif
|
||||
|
||||
xSuspended = pdTRUE;
|
||||
|
||||
while (1) {
|
||||
if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) && xRunning )
|
||||
{
|
||||
|
||||
xStarted = pdTRUE;
|
||||
|
||||
#ifdef RUNNING_THREAD_MUTEX
|
||||
assert( 0 == pthread_mutex_lock( &xRunningThread ) );
|
||||
#endif
|
||||
debug_error("Resuming\r\n");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
#ifdef COND_SIGNALING
|
||||
gettimeofday( &tv, NULL );
|
||||
ts.tv_sec = ts.tv_sec + 1;
|
||||
ts.tv_nsec = 0;
|
||||
xResult = pthread_cond_timedwait( hCond, hMutex, &ts );
|
||||
assert( xResult != EINVAL );
|
||||
#else
|
||||
/* For windows where conditional signaling is buggy */
|
||||
/* It would be wonderful to put a nanosleep here, but since its not reentrant safe */
|
||||
/* and there may be a sleep in the main code (this can be called from an ISR) we must */
|
||||
/* check this */
|
||||
if( pauseMode != THREAD_PAUSE_INTERRUPT )
|
||||
usleep(100);
|
||||
sched_yield();
|
||||
|
||||
#endif
|
||||
// debug_error( "Checked my status\r\n" );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void prvSuspendSignalHandler(int sig)
|
||||
{
|
||||
sigset_t xBlockSignals;
|
||||
|
||||
/* This signal is set here instead of pauseThread because it is checked by the tick handler */
|
||||
/* which means if there were a swap it should result in a suspend interrupt */
|
||||
|
||||
debug_error( "Caught signal %i\r\n", sig );
|
||||
/* Check that we aren't suspending when we should be running. This bug would need tracking down */
|
||||
//assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) );
|
||||
if( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) )
|
||||
{
|
||||
debug_printf( "Suspend ISR called while this thread still marked active. Reflects buggy behavior in scheduler\r\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Block further suspend signals. They need to go to their thread */
|
||||
sigemptyset( &xBlockSignals );
|
||||
sigaddset( &xBlockSignals, SIG_SUSPEND );
|
||||
assert( pthread_sigmask( SIG_BLOCK, &xBlockSignals, NULL ) == 0);
|
||||
|
||||
pauseThread( THREAD_PAUSE_INTERRUPT );
|
||||
|
||||
// assert( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) );
|
||||
while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) )
|
||||
{
|
||||
debug_printf( "Incorrectly woke up. Repausing\r\n" );
|
||||
pauseThread( THREAD_PAUSE_INTERRUPT );
|
||||
}
|
||||
|
||||
/* Make sure the right thread is resuming */
|
||||
assert( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) );
|
||||
|
||||
/* Old synchronization code, may still be required
|
||||
while( !xHandover );
|
||||
assert( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ); */
|
||||
|
||||
/* Respond to signals again */
|
||||
sigemptyset( &xBlockSignals );
|
||||
pthread_sigmask( SIG_SETMASK, &xBlockSignals, NULL );
|
||||
|
||||
debug_printf( "Resuming %li from signal %i\r\n", (long int) pthread_self(), sig );
|
||||
|
||||
/* Will resume here when the SIG_RESUME signal is received. */
|
||||
/* Need to set the interrupts based on the task's critical nesting. */
|
||||
if ( uxCriticalNesting == 0 )
|
||||
{
|
||||
vPortEnableInterrupts();
|
||||
}
|
||||
else
|
||||
{
|
||||
vPortDisableInterrupts();
|
||||
}
|
||||
debug_printf("Exit\r\n");
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void prvSetupSignalsAndSchedulerPolicy( void )
|
||||
{
|
||||
/* The following code would allow for configuring the scheduling of this task as a Real-time task.
|
||||
* The process would then need to be run with higher privileges for it to take affect.
|
||||
int iPolicy;
|
||||
int iResult;
|
||||
int iSchedulerPriority;
|
||||
iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority );
|
||||
iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO );
|
||||
iPolicy = SCHED_FIFO;
|
||||
iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */
|
||||
|
||||
struct sigaction sigsuspendself;
|
||||
portLONG lIndex;
|
||||
|
||||
debug_printf("prvSetupSignalAndSchedulerPolicy\r\n");
|
||||
|
||||
pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS );
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
pxThreads[ lIndex ].hThread = ( pthread_t )NULL;
|
||||
pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL;
|
||||
pxThreads[ lIndex ].uxCriticalNesting = 0;
|
||||
}
|
||||
|
||||
sigsuspendself.sa_flags = 0;
|
||||
sigsuspendself.sa_handler = prvSuspendSignalHandler;
|
||||
sigfillset( &sigsuspendself.sa_mask );
|
||||
|
||||
assert ( 0 == sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
pthread_mutex_t * prvGetMutexHandle( xTaskHandle hTask )
|
||||
{
|
||||
pthread_mutex_t * hMutex;
|
||||
portLONG lIndex;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hTask == hTask )
|
||||
{
|
||||
hMutex = pxThreads[ lIndex ].hMutex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hMutex;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
xTaskHandle prvGetTaskHandle( pthread_t hThread )
|
||||
{
|
||||
xTaskHandle hTask = NULL;
|
||||
portLONG lIndex;
|
||||
|
||||
/* If not initialized yet */
|
||||
if( pxThreads == NULL ) return NULL;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hThread == hThread )
|
||||
{
|
||||
hTask = pxThreads[ lIndex ].hTask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hTask;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask )
|
||||
{
|
||||
pthread_cond_t * hCond;
|
||||
portLONG lIndex;
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hTask == hTask )
|
||||
{
|
||||
debug_printf( "Found condition on %i task\r\n", lIndex );
|
||||
return pxThreads[ lIndex ].hCond;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf( "Failed to get handle, pausing then recursing\r\n" );
|
||||
usleep(1000);
|
||||
return prvGetConditionHandle( hTask );
|
||||
assert(0);
|
||||
return hCond;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
pthread_t prvGetThreadHandle( xTaskHandle hTask )
|
||||
{
|
||||
pthread_t hThread = ( pthread_t )NULL;
|
||||
portLONG lIndex;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hTask == hTask )
|
||||
{
|
||||
hThread = pxThreads[ lIndex ].hThread;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hThread;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portLONG prvGetFreeThreadState( void )
|
||||
{
|
||||
portLONG lIndex;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( MAX_NUMBER_OF_TASKS == lIndex )
|
||||
{
|
||||
printf( "No more free threads, please increase the maximum.\n" );
|
||||
lIndex = 0;
|
||||
vPortEndScheduler();
|
||||
}
|
||||
|
||||
return lIndex;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting )
|
||||
{
|
||||
portLONG lIndex;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hThread == xThreadId )
|
||||
{
|
||||
pxThreads[ lIndex ].uxCriticalNesting = uxNesting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId )
|
||||
{
|
||||
unsigned portBASE_TYPE uxNesting = 0;
|
||||
portLONG lIndex;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hThread == xThreadId )
|
||||
{
|
||||
uxNesting = pxThreads[ lIndex ].uxCriticalNesting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return uxNesting;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void prvDeleteThread( void *xThreadId )
|
||||
{
|
||||
portLONG lIndex;
|
||||
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId )
|
||||
{
|
||||
pxThreads[ lIndex ].hThread = (pthread_t)NULL;
|
||||
pxThreads[ lIndex ].hTask = (xTaskHandle)NULL;
|
||||
if ( pxThreads[ lIndex ].uxCriticalNesting > 0 )
|
||||
{
|
||||
uxCriticalNesting = 0;
|
||||
vPortEnableInterrupts();
|
||||
}
|
||||
pxThreads[ lIndex ].uxCriticalNesting = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAddTaskHandle( void *pxTaskHandle )
|
||||
{
|
||||
portLONG lIndex;
|
||||
|
||||
debug_printf("vPortAddTaskHandle\r\n");
|
||||
|
||||
pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle;
|
||||
for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread )
|
||||
{
|
||||
if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask )
|
||||
{
|
||||
pxThreads[ lIndex ].hThread = ( pthread_t )NULL;
|
||||
pxThreads[ lIndex ].hTask = NULL;
|
||||
pxThreads[ lIndex ].uxCriticalNesting = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
usleep(10000);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFindTicksPerSecond( void )
|
||||
{
|
||||
|
||||
/* Needs to be reasonably high for accuracy. */
|
||||
unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK);
|
||||
printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned long ulPortGetTimerValue( void )
|
||||
{
|
||||
struct tms xTimes;
|
||||
|
||||
unsigned long ulTotalTime = times( &xTimes );
|
||||
/* Return the application code times.
|
||||
* The timer only increases when the application code is actually running
|
||||
* which means that the total execution times should add up to 100%.
|
||||
*/
|
||||
return ( unsigned long ) xTimes.tms_utime;
|
||||
|
||||
/* Should check ulTotalTime for being clock_t max minus 1. */
|
||||
(void)ulTotalTime;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -0,0 +1,188 @@
|
||||
File: port.c.documentation.txt
|
||||
Author: Corvus Corax
|
||||
Desc: Description of port.c Functions and Directions about porting.
|
||||
See FreeRTOS documentation ebook for details.
|
||||
|
||||
|
||||
FreeRTOS is an architecture independent real time operating system.
|
||||
Most architecture dependant code sits in a single file: port.c
|
||||
Architecture dependant definitions sit in: portmacro.h
|
||||
|
||||
Other important files:
|
||||
|
||||
Source/portable/MemMang/head_3.c - memory management - very simple. Provides
|
||||
functions like malloc and free - very easy to make a wrapper for on any system
|
||||
that provides memory management.
|
||||
|
||||
FreeRTOS has internal scheduling. The real time scheduler sits in Source/task.c and calls low level functions of port.c for thread management.
|
||||
|
||||
For that port.c needs to provide functions to switch between threads on
|
||||
request, as well as a tick handler that preempts threads on a periodic basis.
|
||||
|
||||
Only one FreeRTOS thread is active at any time!
|
||||
|
||||
|
||||
port.c provides the API defined in portmacro.h.
|
||||
|
||||
Only a subset of the functions is explained here (with the naming from the
|
||||
posix port. Their macros are sometimes named a bit different)
|
||||
|
||||
|
||||
void vPortEnterCritical(void);
|
||||
|
||||
This function is called if a thread enters a "critical section".
|
||||
In a critical sections the thread must not be preempted.
|
||||
|
||||
(To preempt a thread means to halt its execution when a timer interrupt comes
|
||||
in, and give execution to another thread)
|
||||
This function should increase a counter for that thread, since several
|
||||
"Critical Sections" could be cascaded. Only if the outermost critical section
|
||||
is exited, is preemtion allowed again.
|
||||
|
||||
void vPortExitCritical(void);
|
||||
This function is called if a thread leaves a "critical section".
|
||||
If a thread leaves the outermost critical section, the scheduler is allowed to
|
||||
preempt it on timer interrupt (or other interrupts)
|
||||
|
||||
|
||||
void vPortEnableInterrupts(void);
|
||||
void vPortDisableInterrupts(void);
|
||||
|
||||
functions to enable and disable interrupts. On "real systems" this means all
|
||||
interrupts including IO. When "simulating" this means the tick handler/ timer
|
||||
/ timer interrupt. The tick handler is supposed to not do anything if interrupts are disabled.
|
||||
|
||||
|
||||
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack,
|
||||
pdTASK_CODE pxCode, void *pvParameters );
|
||||
|
||||
Used to initialize a new thread. The stack memory area, command line
|
||||
parameters for this task and the entry function (pxCode) are given
|
||||
|
||||
This function needs to initialize the new task/thread, but suspend it
|
||||
immediately. It is only to be executed later if the scheduler says so.
|
||||
|
||||
returns pxTopOfStack if success and 0 on failure.
|
||||
|
||||
THIS WILL BE THE FIRST FUNCTION FreeRTOS CALLS.
|
||||
The first thread to be created is likely the idle thread. At this time the
|
||||
scheduler has not been started yet. Therefore it's important to start all
|
||||
threads in suspended state!
|
||||
|
||||
void vPortEndScheduler(void);
|
||||
|
||||
Needs to end the scheduler (and as such all Tasks/threads) This means FreeRTOS
|
||||
terminates - as in (simulated) system shutdown.
|
||||
|
||||
|
||||
portBASE_TYPE xPortStartScheduler(void);
|
||||
|
||||
This function doesn't return until someone (another thread) calls
|
||||
vPortEndScheduler(). You can set up your timer and tick handler here and start
|
||||
the first thread. Then do what a scheduler does (manage threads)
|
||||
|
||||
|
||||
vPortYield()
|
||||
|
||||
Sometimes threads go sleeping on purpose (for example during one of FreeRTOS
|
||||
system calls - including sleep() )
|
||||
This function should send the thread that calls it into suspended state and
|
||||
not return until the scheduler gives back execution to this thread.
|
||||
|
||||
|
||||
===========
|
||||
The scheduler.
|
||||
|
||||
What your scheduler needs to do:
|
||||
|
||||
Basically what your self written scheduler is allowed to do is the "dirty
|
||||
work" for the high level scheduler logic provided by FreeRTOS task.c
|
||||
|
||||
The scheduler is supposed to run a timer interrupt/tick handler that gets
|
||||
called every portTICK_RATE_MICROSECONDS microseconds.
|
||||
That value is defined somewhere in OpenPilot and has to be exact as well as
|
||||
the same on all architectures.
|
||||
|
||||
If you cannot set up a timer with that accuracy you are screwed!
|
||||
|
||||
Anyway. Every time the timer tick happens, you have to
|
||||
|
||||
- check whether you are allowed to execute the tick handler.
|
||||
If interrupts are disabled and/or the thread is in a critical section, the
|
||||
tick handler should do nothing
|
||||
|
||||
- Tell FreeRTOS that the tick has happened
|
||||
Increment the Tick Count using the FreeRTOS function
|
||||
vTaskIncrementTick();
|
||||
|
||||
- If preemption is enabled (and in OpenPilot it is!)
|
||||
Tell the high level Scheduler of FreeRTOS to do its magic, using the
|
||||
function
|
||||
vTaskSwitchContext();
|
||||
|
||||
- You can find out which thread is SUPPOSED to be running with the function
|
||||
xTaskGetCurrentTaskHandle();
|
||||
|
||||
- If this is for some reason not the currently running thread, SUSPEND that
|
||||
thread with whatever method possible (signals, events, operating system
|
||||
thread.suspend() - I don't know how to do that in Qt.
|
||||
|
||||
- Make the thread returned by xTaskGetCurrentTaskHandle() resume operation as
|
||||
normal.
|
||||
|
||||
- Make sure that when you return from the tick handler, exactly one thread is
|
||||
running and that is the one by xTaskGetCurrentTaskHandle() and all others
|
||||
are suspended!
|
||||
|
||||
|
||||
|
||||
On top of that, threads can suspend themselves just like that. That happens
|
||||
every time they call any blocking FreeRTOS function.
|
||||
|
||||
They do that with above mentioned function
|
||||
|
||||
vPortYield()
|
||||
|
||||
When vPortYield is called your scheduler must:
|
||||
|
||||
- Tell the high level Scheduler of FreeRTOS to do its magic, using the
|
||||
function
|
||||
vTaskSwitchContext();
|
||||
|
||||
- You can then find out which thread is SUPPOSED to be running with the function
|
||||
xTaskGetCurrentTaskHandle();
|
||||
|
||||
- Make sure that the thread calling this function SUSPENDS and the thread
|
||||
returned by xTaskGetCurrentTaskHandle() gets executed. Be aware that they
|
||||
could be the same in which case vPortYield does exactly NOTHING!
|
||||
|
||||
- This function does not return (since the current thread is sent to sleep)
|
||||
until the scheduler makes it wake up - either by the tick handler, or by
|
||||
another thread calling vPortYield().
|
||||
|
||||
- So it must not ever return until xTaskGetCurrentTaskHandle() says the
|
||||
calling thread is the current task handle.
|
||||
|
||||
- Then it returns to the caller.
|
||||
|
||||
|
||||
|
||||
=====
|
||||
|
||||
What emthod you use to send threads/tasks to sleep and wake them up again is
|
||||
up to you.
|
||||
|
||||
The posix implementation uses signals and a signal handler in each thread that
|
||||
sleeps until a resume signal is received
|
||||
|
||||
The native STM32 implementation manually switches contexts by and uses actual
|
||||
system interrupts
|
||||
(so does the native x86 implementation)
|
||||
|
||||
The native Win32 implementation uses win32 API calls to manipulate windows
|
||||
threads (windows actually provides a call to remote-suspend and resume a
|
||||
thread - posix doesn't)
|
||||
|
||||
I have no clue what measures for thread control and suspension/interruption Qt
|
||||
offers. (I hope there are some)
|
||||
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
FreeRTOS.org V5.2.0 - Copyright (C) 2003-2009 Richard Barry.
|
||||
|
||||
This file is part of the FreeRTOS.org distribution.
|
||||
|
||||
FreeRTOS.org 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.
|
||||
|
||||
FreeRTOS.org 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 along
|
||||
with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
A special exception to the GPL is included to allow you to distribute a
|
||||
combined work that includes FreeRTOS.org without being obliged to provide
|
||||
the source code for any proprietary components. See the licensing section
|
||||
of http://www.FreeRTOS.org for full details.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* This is a concise, step by step, 'hands on' guide that describes both *
|
||||
* general multitasking concepts and FreeRTOS specifics. It presents and *
|
||||
* explains numerous examples that are written using the FreeRTOS API. *
|
||||
* Full source code for all the examples is provided in an accompanying *
|
||||
* .zip file. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
Please ensure to read the configuration and relevant port sections of the
|
||||
online documentation.
|
||||
|
||||
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 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 int
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE unsigned long
|
||||
#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 portTICK_RATE_MICROSECONDS ( ( portTickType ) 1000000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portREMOVE_STATIC_QUALIFIER
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vPortYieldFromISR( void );
|
||||
extern void vPortYield( void );
|
||||
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortDisableInterrupts( void );
|
||||
extern void vPortEnableInterrupts( void );
|
||||
#define portSET_INTERRUPT_MASK() ( vPortDisableInterrupts() )
|
||||
#define portCLEAR_INTERRUPT_MASK() ( vPortEnableInterrupts() )
|
||||
|
||||
extern portBASE_TYPE xPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( portBASE_TYPE xMask );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
|
||||
#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()
|
||||
|
||||
#define portOUTPUT_BYTE( a, b )
|
||||
|
||||
extern void vPortForciblyEndThread( void *pxTaskToDelete );
|
||||
#define traceTASK_DELETE( pxTaskToDelete ) vPortForciblyEndThread( pxTaskToDelete )
|
||||
|
||||
extern void vPortAddTaskHandle( void *pxTaskHandle );
|
||||
#define traceTASK_CREATE( pxNewTCB ) vPortAddTaskHandle( pxNewTCB )
|
||||
|
||||
/* Posix Signal definitions that can be changed or read as appropriate. */
|
||||
#define SIG_SUSPEND SIGUSR1
|
||||
#define SIG_RESUME SIGUSR2
|
||||
|
||||
/* Enable the following hash defines to make use of the real-time tick where time progresses at real-time. */
|
||||
#define SIG_TICK SIGALRM
|
||||
#define TIMER_TYPE ITIMER_REAL
|
||||
/* Enable the following hash defines to make use of the process tick where time progresses only when the process is executing.
|
||||
#define SIG_TICK SIGVTALRM
|
||||
#define TIMER_TYPE ITIMER_VIRTUAL */
|
||||
/* Enable the following hash defines to make use of the profile tick where time progresses when the process or system calls are executing.
|
||||
#define SIG_TICK SIGPROF
|
||||
#define TIMER_TYPE ITIMER_PROF */
|
||||
|
||||
/* Make use of times(man 2) to gather run-time statistics on the tasks. */
|
||||
extern void vPortFindTicksPerSecond( void );
|
||||
#undef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
|
||||
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vPortFindTicksPerSecond() /* Nothing to do because the timer is already present. */
|
||||
extern unsigned long ulPortGetTimerValue( void );
|
||||
#undef portGET_RUN_TIME_COUNTER_VALUE
|
||||
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetTimerValue() /* Query the System time stats for this process. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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_2.c and heap_1.c for alternative implementations, and the memory
|
||||
* management pages of http://www.FreeRTOS.org for more information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
Each real time kernel port consists of three files that contain the core kernel
|
||||
components and are common to every port, and one or more files that are
|
||||
specific to a particular microcontroller and/or compiler.
|
||||
|
||||
|
||||
+ The FreeRTOS/Source/Portable/MemMang directory contains the three sample
|
||||
memory allocators as described on the http://www.FreeRTOS.org WEB site.
|
||||
|
||||
+ The other directories each contain files specific to a particular
|
||||
microcontroller or compiler.
|
||||
|
||||
|
||||
|
||||
For example, if you are interested in the GCC port for the ATMega323
|
||||
microcontroller then the port specific files are contained in
|
||||
FreeRTOS/Source/Portable/GCC/ATMega323 directory. If this is the only
|
||||
port you are interested in then all the other directories can be
|
||||
ignored.
|
||||
|
1465
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/queue.c
Normal file
1465
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/queue.c
Normal file
@ -0,0 +1,1465 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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 "croutine.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC LIST API documented in list.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants used with the cRxLock and cTxLock structure members. */
|
||||
#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
|
||||
#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
|
||||
|
||||
#define queueERRONEOUS_UNBLOCK ( -1 )
|
||||
|
||||
/* For internal use only. */
|
||||
#define queueSEND_TO_BACK ( 0 )
|
||||
#define queueSEND_TO_FRONT ( 1 )
|
||||
|
||||
/* Effectively make a union out of the xQUEUE structure. */
|
||||
#define pxMutexHolder pcTail
|
||||
#define uxQueueType pcHead
|
||||
#define uxRecursiveCallCount pcReadFrom
|
||||
#define queueQUEUE_IS_MUTEX NULL
|
||||
|
||||
/* Semaphores do not actually store or copy data, so have an items size of
|
||||
zero. */
|
||||
#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
|
||||
#define queueDONT_BLOCK ( ( portTickType ) 0 )
|
||||
#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */
|
||||
|
||||
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. */
|
||||
|
||||
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. */
|
||||
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. */
|
||||
|
||||
} xQUEUE;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Inside this file xQueueHandle is a pointer to a xQUEUE structure.
|
||||
* To keep the definition private the API header file defines it as a
|
||||
* pointer to void.
|
||||
*/
|
||||
typedef xQUEUE * xQueueHandle;
|
||||
|
||||
/*
|
||||
* Prototypes for public functions are included here so we don't have to
|
||||
* include the API header file (as it defines xQueueHandle differently). These
|
||||
* functions are documented in the API header file.
|
||||
*/
|
||||
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
|
||||
void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;
|
||||
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
|
||||
portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
|
||||
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Co-routine queue functions differ from task queue functions. Co-routines are
|
||||
* an optional component.
|
||||
*/
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 ];
|
||||
|
||||
/* Removes a queue from the registry by simply setting the pcQueueName
|
||||
member to NULL. */
|
||||
static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
|
||||
void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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( xQueueHandle 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 xQueueHandle 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 xQueueHandle 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 *pvBuffer ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 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(); \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC QUEUE MANAGEMENT API documented in queue.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
|
||||
{
|
||||
xQUEUE *pxNewQueue;
|
||||
size_t xQueueSizeInBytes;
|
||||
|
||||
/* 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;
|
||||
|
||||
pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
|
||||
if( pxNewQueue->pcHead != NULL )
|
||||
{
|
||||
/* Initialise the queue members as described above where the
|
||||
queue type is defined. */
|
||||
pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
|
||||
pxNewQueue->uxMessagesWaiting = 0;
|
||||
pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
|
||||
pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
|
||||
pxNewQueue->uxLength = uxQueueLength;
|
||||
pxNewQueue->uxItemSize = uxItemSize;
|
||||
pxNewQueue->xRxLock = queueUNLOCKED;
|
||||
pxNewQueue->xTxLock = queueUNLOCKED;
|
||||
|
||||
/* Likewise ensure the event queues start with the correct state. */
|
||||
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
|
||||
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
|
||||
|
||||
traceQUEUE_CREATE( pxNewQueue );
|
||||
return pxNewQueue;
|
||||
}
|
||||
else
|
||||
{
|
||||
traceQUEUE_CREATE_FAILED();
|
||||
vPortFree( pxNewQueue );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Will only reach here if we could not allocate enough memory or no memory
|
||||
was required. */
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
xQueueHandle xQueueCreateMutex( void )
|
||||
{
|
||||
xQUEUE *pxNewQueue;
|
||||
|
||||
/* 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->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 = 0;
|
||||
pxNewQueue->uxLength = 1;
|
||||
pxNewQueue->uxItemSize = 0;
|
||||
pxNewQueue->xRxLock = queueUNLOCKED;
|
||||
pxNewQueue->xTxLock = queueUNLOCKED;
|
||||
|
||||
/* Ensure the event queues start with the correct state. */
|
||||
vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
|
||||
vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
|
||||
|
||||
/* Start with the semaphore in the expected state. */
|
||||
xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
|
||||
|
||||
traceCREATE_MUTEX( pxNewQueue );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceCREATE_MUTEX_FAILED();
|
||||
}
|
||||
|
||||
return pxNewQueue;
|
||||
}
|
||||
|
||||
#endif /* configUSE_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_RECURSIVE_MUTEXES == 1
|
||||
|
||||
portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
/* 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 == xTaskGetCurrentTaskHandle() )
|
||||
{
|
||||
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->uxRecursiveCallCount )--;
|
||||
|
||||
/* Have we unwound the call count? */
|
||||
if( pxMutex->uxRecursiveCallCount == 0 )
|
||||
{
|
||||
/* Return the mutex. This will automatically unblock any other
|
||||
task that might be waiting to access the mutex. */
|
||||
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 pxMutex, portTickType xBlockTime )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
/* Comments regarding mutual exclusion as per those within
|
||||
xQueueGiveMutexRecursive(). */
|
||||
|
||||
traceTAKE_MUTEX_RECURSIVE( pxMutex );
|
||||
|
||||
if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
|
||||
{
|
||||
( pxMutex->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->uxRecursiveCallCount )++;
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_RECURSIVE_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_COUNTING_SEMAPHORES == 1
|
||||
|
||||
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
|
||||
{
|
||||
xQueueHandle pxHandle;
|
||||
|
||||
pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
|
||||
|
||||
if( pxHandle != NULL )
|
||||
{
|
||||
pxHandle->uxMessagesWaiting = uxInitialCount;
|
||||
|
||||
traceCREATE_COUNTING_SEMAPHORE();
|
||||
}
|
||||
else
|
||||
{
|
||||
traceCREATE_COUNTING_SEMAPHORE_FAILED();
|
||||
}
|
||||
|
||||
return pxHandle;
|
||||
}
|
||||
|
||||
#endif /* configUSE_COUNTING_SEMAPHORES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
|
||||
{
|
||||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
|
||||
/* 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? 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. Yes it is ok to do
|
||||
this from within the critical section - the kernel
|
||||
takes care of that. */
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ) )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
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 pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
|
||||
{
|
||||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
|
||||
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 ) )
|
||||
{
|
||||
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 pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
|
||||
{
|
||||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
signed char *pcOriginalReadPosition;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
/* Remember our read position in case we are just peeking. */
|
||||
pcOriginalReadPosition = pxQueue->pcReadFrom;
|
||||
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
|
||||
if( xJustPeeking == pdFALSE )
|
||||
{
|
||||
traceQUEUE_RECEIVE( pxQueue );
|
||||
|
||||
/* We are actually removing data. */
|
||||
--( 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 = 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->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 ) ) )
|
||||
{
|
||||
/* 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 ) )
|
||||
{
|
||||
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 pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
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( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||
{
|
||||
/* The task waiting has a higher priority so record that a
|
||||
context switch is required. */
|
||||
*pxHigherPriorityTaskWoken = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
|
||||
{
|
||||
signed portBASE_TYPE xEntryTimeSet = pdFALSE;
|
||||
xTimeOutType xTimeOut;
|
||||
signed char *pcOriginalReadPosition;
|
||||
|
||||
/* 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 our read position in case we are just peeking. */
|
||||
pcOriginalReadPosition = pxQueue->pcReadFrom;
|
||||
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
|
||||
if( xJustPeeking == pdFALSE )
|
||||
{
|
||||
traceQUEUE_RECEIVE( pxQueue );
|
||||
|
||||
/* We are actually removing data. */
|
||||
--( 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 = 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->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 ) ) )
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ) )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
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 pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* We cannot block from 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 we will not modify the event list. Instead
|
||||
we 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 ) ) )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
/* The task waiting has a higher priority than us so
|
||||
force a context switch. */
|
||||
*pxTaskWoken = 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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
|
||||
{
|
||||
unsigned portBASE_TYPE uxReturn;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
uxReturn = pxQueue->uxMessagesWaiting;
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
|
||||
{
|
||||
unsigned portBASE_TYPE uxReturn;
|
||||
|
||||
uxReturn = pxQueue->uxMessagesWaiting;
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vQueueDelete( xQueueHandle pxQueue )
|
||||
{
|
||||
traceQUEUE_DELETE( pxQueue );
|
||||
vQueueUnregisterQueue( pxQueue );
|
||||
vPortFree( pxQueue->pcHead );
|
||||
vPortFree( pxQueue );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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
|
||||
}
|
||||
else if( xPosition == queueSEND_TO_BACK )
|
||||
{
|
||||
memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
|
||||
pxQueue->pcWriteTo += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcWriteTo >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcWriteTo = pxQueue->pcHead;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
|
||||
pxQueue->pcReadFrom -= pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom < pxQueue->pcHead )
|
||||
{
|
||||
pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
|
||||
}
|
||||
}
|
||||
|
||||
++( pxQueue->uxMessagesWaiting );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
|
||||
{
|
||||
if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
|
||||
{
|
||||
pxQueue->pcReadFrom += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvUnlockQueue( xQueueHandle 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( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
|
||||
{
|
||||
/* 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 so record that a
|
||||
context switch is required. */
|
||||
vTaskMissedYield();
|
||||
}
|
||||
|
||||
--( pxQueue->xTxLock );
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 ) ) )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
vTaskMissedYield();
|
||||
}
|
||||
|
||||
--( pxQueue->xRxLock );
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pxQueue->xRxLock = queueUNLOCKED;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* 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 ) )
|
||||
{
|
||||
/* 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();
|
||||
|
||||
portNOP();
|
||||
|
||||
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 ) ) )
|
||||
{
|
||||
/* 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* 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();
|
||||
|
||||
portNOP();
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
/* Data is available from the queue. */
|
||||
pxQueue->pcReadFrom += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
--( pxQueue->uxMessagesWaiting );
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
|
||||
|
||||
xReturn = pdPASS;
|
||||
|
||||
/* Were any co-routines waiting for space to become available? */
|
||||
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
|
||||
{
|
||||
/* 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
|
||||
{
|
||||
/* 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 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
|
||||
{
|
||||
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||
{
|
||||
return pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xCoRoutinePreviouslyWoken;
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_CO_ROUTINES == 1
|
||||
signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
|
||||
{
|
||||
signed portBASE_TYPE xReturn;
|
||||
|
||||
/* 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->pcReadFrom += pxQueue->uxItemSize;
|
||||
if( pxQueue->pcReadFrom >= pxQueue->pcTail )
|
||||
{
|
||||
pxQueue->pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
--( pxQueue->uxMessagesWaiting );
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
|
||||
|
||||
if( !( *pxCoRoutineWoken ) )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
|
||||
{
|
||||
if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
|
||||
{
|
||||
*pxCoRoutineWoken = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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 = 0; ux < 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configQUEUE_REGISTRY_SIZE > 0
|
||||
|
||||
static void vQueueUnregisterQueue( xQueueHandle xQueue )
|
||||
{
|
||||
unsigned portBASE_TYPE ux;
|
||||
|
||||
/* See if the handle of the queue being unregistered in actually in the
|
||||
registry. */
|
||||
for( ux = 0; ux < 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
17
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/readme.txt
Normal file
17
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/readme.txt
Normal file
@ -0,0 +1,17 @@
|
||||
Each real time kernel port consists of three files that contain the core kernel
|
||||
components and are common to every port, and one or more files that are
|
||||
specific to a particular microcontroller and or compiler.
|
||||
|
||||
+ The FreeRTOS/Source directory contains the three files that are common to
|
||||
every port - list.c, queue.c and tasks.c. The kernel is contained within these
|
||||
three files. croutine.c implements the optional co-routine functionality - which
|
||||
is normally only used on very memory limited systems.
|
||||
|
||||
+ The FreeRTOS/Source/Portable directory contains the files that are specific to
|
||||
a particular microcontroller and or compiler.
|
||||
|
||||
+ The FreeRTOS/Source/include directory contains the real time kernel header
|
||||
files.
|
||||
|
||||
See the readme file in the FreeRTOS/Source/Portable directory for more
|
||||
information.
|
2332
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/task.c
Normal file
2332
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/task.c
Normal file
@ -0,0 +1,2332 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* 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 "StackMacros.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*
|
||||
* Macro to define the amount of stack available to the idle task.
|
||||
*/
|
||||
#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
/*
|
||||
* Task control block. A task control block (TCB) is allocated to each task,
|
||||
* and stores the context of the task.
|
||||
*/
|
||||
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 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 STRUCT. */
|
||||
#endif
|
||||
|
||||
xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */
|
||||
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */
|
||||
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 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; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
|
||||
#endif
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
unsigned portBASE_TYPE uxCriticalNesting;
|
||||
#endif
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
|
||||
#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; /*< Used for calculating how much CPU time each task is utilising. */
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
#endif
|
||||
|
||||
/*lint -e956 */
|
||||
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 queue when the scheduler is resumed. */
|
||||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
|
||||
PRIVILEGED_DATA static volatile 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 ) 0;
|
||||
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
|
||||
|
||||
#endif
|
||||
|
||||
/* File private variables. --------------------------------*/
|
||||
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0;
|
||||
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;
|
||||
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 uxMissedTicks = ( unsigned portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
||||
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
PRIVILEGED_DATA static char pcStatsString[ 50 ] ;
|
||||
PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
|
||||
static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif
|
||||
|
||||
/* 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 ( 0xa5 )
|
||||
|
||||
/*
|
||||
* 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' )
|
||||
|
||||
/*
|
||||
* Macros and private variables used by the trace facility.
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
#define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )
|
||||
PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;
|
||||
PRIVILEGED_DATA static signed char *pcTraceBufferStart;
|
||||
PRIVILEGED_DATA static signed char *pcTraceBufferEnd;
|
||||
PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;
|
||||
static unsigned portBASE_TYPE uxPreviousTask = 255;
|
||||
PRIVILEGED_DATA static char pcStatusString[ 50 ];
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro that writes a trace of scheduler activity to a buffer. This trace
|
||||
* shows which task is running when and is very useful as a debugging tool.
|
||||
* As this macro is called each context switch it is a good idea to undefine
|
||||
* it if not using the facility.
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
#define vWriteTraceToBuffer() \
|
||||
{ \
|
||||
if( xTracing ) \
|
||||
{ \
|
||||
if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \
|
||||
{ \
|
||||
if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
|
||||
{ \
|
||||
uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
|
||||
*( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \
|
||||
pcTraceBuffer += sizeof( unsigned long ); \
|
||||
*( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \
|
||||
pcTraceBuffer += sizeof( unsigned long ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
xTracing = pdFALSE; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define vWriteTraceToBuffer()
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Place the task represented by pxTCB into the appropriate ready queue for
|
||||
* the task. It is inserted at the end of the list. One quirk of this is
|
||||
* that if the task being inserted is at the same priority as the currently
|
||||
* executing task, then it will only be rescheduled after the currently
|
||||
* executing task has been rescheduled.
|
||||
*/
|
||||
#define prvAddTaskToReadyQueue( pxTCB ) \
|
||||
{ \
|
||||
if( pxTCB->uxPriority > uxTopReadyPriority ) \
|
||||
{ \
|
||||
uxTopReadyPriority = pxTCB->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of tasks that are currently delayed to see if
|
||||
* any require waking.
|
||||
*
|
||||
* Tasks are stored in the queue in the order of their wake time - meaning
|
||||
* once one tasks has been found whose timer has not expired we need not look
|
||||
* any further down the list.
|
||||
*/
|
||||
#define prvCheckDelayedTasks() \
|
||||
{ \
|
||||
register tskTCB *pxTCB; \
|
||||
\
|
||||
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
|
||||
{ \
|
||||
if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
vListRemove( &( pxTCB->xGenericListItem ) ); \
|
||||
/* Is the task waiting on an event also? */ \
|
||||
if( pxTCB->xEventListItem.pvContainer ) \
|
||||
{ \
|
||||
vListRemove( &( pxTCB->xEventListItem ) ); \
|
||||
} \
|
||||
prvAddTaskToReadyQueue( pxTCB ); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 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 )
|
||||
|
||||
|
||||
/* 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 ) || ( INCLUDE_vTaskCleanUpResources == 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;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Called from vTaskList. vListTasks details all the tasks currently under
|
||||
* control of the scheduler. The tasks may be in one of a number of lists.
|
||||
* prvListTaskWithinSingleList accepts a list and details the tasks from
|
||||
* within just that list.
|
||||
*
|
||||
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
|
||||
* NORMAL APPLICATION CODE.
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) 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 usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*lint +e956 */
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CREATION API documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
|
||||
/* 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 ) != 0x00 )
|
||||
{
|
||||
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 - 1 );
|
||||
pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) );
|
||||
}
|
||||
#else
|
||||
{
|
||||
pxTopOfStack = pxNewTCB->pxStack;
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
{
|
||||
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We are going to manipulate the task queues to add this task to a
|
||||
ready list, so must make sure no interrupts occur. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
uxCurrentNumberOfTasks++;
|
||||
if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
|
||||
{
|
||||
/* As this is the first task it must also be the current task. */
|
||||
pxCurrentTCB = pxNewTCB;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the top priority to make context switching faster. Use
|
||||
the priority in pxNewTCB as this has been capped to a valid value. */
|
||||
if( pxNewTCB->uxPriority > uxTopUsedPriority )
|
||||
{
|
||||
uxTopUsedPriority = pxNewTCB->uxPriority;
|
||||
}
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
{
|
||||
/* Add a counter into the TCB for tracing only. */
|
||||
pxNewTCB->uxTCBNumber = uxTaskNumber;
|
||||
}
|
||||
#endif
|
||||
uxTaskNumber++;
|
||||
|
||||
prvAddTaskToReadyQueue( pxNewTCB );
|
||||
|
||||
xReturn = pdPASS;
|
||||
traceTASK_CREATE( pxNewTCB );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
traceTASK_CREATE_FAILED( pxNewTCB );
|
||||
}
|
||||
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 pxTaskToDelete )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
deleted. */
|
||||
if( pxTaskToDelete == pxCurrentTCB )
|
||||
{
|
||||
pxTaskToDelete = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are deleting ourselves. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
|
||||
|
||||
/* 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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
if( pxTCB->xEventListItem.pvContainer )
|
||||
{
|
||||
vListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
||||
vListInsertEnd( ( xList * ) &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 );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Force a reschedule if we have just deleted the current task. */
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( ( void * ) pxTaskToDelete == NULL )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CONTROL API documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskDelayUntil == 1 )
|
||||
|
||||
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Generate the tick time at which the task wants to wake. */
|
||||
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
|
||||
|
||||
if( xTickCount < *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 > xTickCount ) )
|
||||
{
|
||||
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 > xTickCount ) )
|
||||
{
|
||||
xShouldDelay = pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the wake time ready for the next call. */
|
||||
*pxPreviousWakeTime = xTimeToWake;
|
||||
|
||||
if( xShouldDelay )
|
||||
{
|
||||
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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
|
||||
/* 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( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
/* Force a reschedule if xTaskResumeAll has not already done so, we may
|
||||
have put ourselves to sleep. */
|
||||
if( !xAlreadyYielded )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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 ) 0 )
|
||||
{
|
||||
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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
|
||||
/* 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( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
}
|
||||
|
||||
/* Force a reschedule if xTaskResumeAll has not already done so, we may
|
||||
have put ourselves to sleep. */
|
||||
if( !xAlreadyYielded )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_uxTaskPriorityGet == 1 )
|
||||
|
||||
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
unsigned portBASE_TYPE uxReturn;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* If null is passed in here then we are changing the
|
||||
priority of the calling function. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTask );
|
||||
uxReturn = pxTCB->uxPriority;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskPrioritySet == 1 )
|
||||
|
||||
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE;
|
||||
|
||||
/* Ensure the new priority is valid. */
|
||||
if( uxNewPriority >= configMAX_PRIORITIES )
|
||||
{
|
||||
uxNewPriority = configMAX_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
if( pxTask == pxCurrentTCB )
|
||||
{
|
||||
pxTask = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are changing the
|
||||
priority of the calling function. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTask );
|
||||
|
||||
traceTASK_PRIORITY_SET( pxTask, uxNewPriority );
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
uxCurrentPriority = pxTCB->uxBasePriority;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uxCurrentPriority = pxTCB->uxPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( uxCurrentPriority != uxNewPriority )
|
||||
{
|
||||
/* The priority change may have readied a task of higher
|
||||
priority than the calling task. */
|
||||
if( uxNewPriority > uxCurrentPriority )
|
||||
{
|
||||
if( pxTask != NULL )
|
||||
{
|
||||
/* The priority of another task is being raised. If we
|
||||
were raising the priority of the currently running task
|
||||
there would be no need to switch as it must have already
|
||||
been the highest priority task. */
|
||||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
}
|
||||
else if( pxTask == NULL )
|
||||
{
|
||||
/* Setting our own priority down means there may now be another
|
||||
task of higher priority that is ready to execute. */
|
||||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#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 ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );
|
||||
|
||||
/* 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 queue appropriate to its new priority. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
||||
{
|
||||
/* 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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
|
||||
if( xYieldRequired == pdTRUE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
void vTaskSuspend( xTaskHandle pxTaskToSuspend )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
suspended. */
|
||||
if( pxTaskToSuspend == pxCurrentTCB )
|
||||
{
|
||||
pxTaskToSuspend = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are suspending ourselves. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );
|
||||
|
||||
traceTASK_SUSPEND( pxTCB );
|
||||
|
||||
/* Remove task from the ready/delayed list and place in the suspended list. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
if( pxTCB->xEventListItem.pvContainer )
|
||||
{
|
||||
vListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
||||
vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* We may have just suspended the current task. */
|
||||
if( ( void * ) pxTaskToSuspend == NULL )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
|
||||
{
|
||||
portBASE_TYPE xReturn = pdFALSE;
|
||||
const tskTCB * const pxTCB = ( tskTCB * ) 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 ) ) != pdTRUE )
|
||||
{
|
||||
/* 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 ) ) == pdTRUE )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
void vTaskResume( xTaskHandle pxTaskToResume )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
/* Remove the task from whichever list it is currently in, and place
|
||||
it in the ready list. */
|
||||
pxTCB = ( tskTCB * ) pxTaskToResume;
|
||||
|
||||
/* The parameter cannot be NULL as it is impossible to resume the
|
||||
currently executing task. */
|
||||
if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
|
||||
{
|
||||
portENTER_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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
|
||||
|
||||
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
|
||||
{
|
||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||
tskTCB *pxTCB;
|
||||
|
||||
pxTCB = ( tskTCB * ) pxTaskToResume;
|
||||
|
||||
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||
{
|
||||
traceTASK_RESUME_FROM_ISR( pxTCB );
|
||||
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( 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( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
|
||||
return xYieldRequired;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC SCHEDULER CONTROL documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
void vTaskStartScheduler( void )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
/* Add the idle task at the lowest priority. */
|
||||
xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL );
|
||||
|
||||
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.
|
||||
|
||||
STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
|
||||
DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
xSchedulerRunning = pdTRUE;
|
||||
xTickCount = ( portTickType ) 0;
|
||||
|
||||
/* 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() )
|
||||
{
|
||||
/* 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(). */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xTaskResumeAll( void )
|
||||
{
|
||||
register tskTCB *pxTCB;
|
||||
signed portBASE_TYPE xAlreadyYielded = pdFALSE;
|
||||
|
||||
/* 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. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
--uxSchedulerSuspended;
|
||||
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||
|
||||
/* Move any readied tasks from the pending list into the
|
||||
appropriate ready list. */
|
||||
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
|
||||
{
|
||||
vListRemove( &( pxTCB->xEventListItem ) );
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( 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 )
|
||||
{
|
||||
xYieldRequired = 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( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
vTaskIncrementTick();
|
||||
--uxMissedTicks;
|
||||
}
|
||||
|
||||
/* As we have processed some ticks it is appropriate to yield
|
||||
to ensure the highest priority task that is ready to run is
|
||||
the task actually running. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
|
||||
{
|
||||
xAlreadyYielded = pdTRUE;
|
||||
xMissedYield = pdFALSE;
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xAlreadyYielded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC TASK UTILITIES documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
portTickType xTaskGetTickCount( void )
|
||||
{
|
||||
portTickType xTicks;
|
||||
|
||||
/* Critical section required if running on a 16 bit processor. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
xTicks = xTickCount;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xTicks;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
||||
{
|
||||
/* A critical section is not required because the variables are of type
|
||||
portBASE_TYPE. */
|
||||
return uxCurrentNumberOfTasks;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void vTaskList( signed char *pcWriteBuffer )
|
||||
{
|
||||
unsigned portBASE_TYPE uxQueue;
|
||||
|
||||
/* This is a VERY costly function that should be used for debug only.
|
||||
It leaves interrupts disabled for a LONG time. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Run through all the lists that could potentially contain a TCB and
|
||||
report the task name, state and stack high water mark. */
|
||||
|
||||
pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
|
||||
strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
|
||||
|
||||
uxQueue = uxTopUsedPriority + 1;
|
||||
|
||||
do
|
||||
{
|
||||
uxQueue--;
|
||||
|
||||
if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR );
|
||||
}
|
||||
}while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR );
|
||||
}
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR );
|
||||
}
|
||||
|
||||
#if( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
|
||||
{
|
||||
unsigned portBASE_TYPE uxQueue;
|
||||
unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
|
||||
/* This is a VERY costly function that should be used for debug only.
|
||||
It leaves interrupts disabled for a LONG time. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Run through all the lists that could potentially contain a TCB,
|
||||
generating a table of run timer percentages in the provided
|
||||
buffer. */
|
||||
|
||||
pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
|
||||
strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
|
||||
|
||||
uxQueue = uxTopUsedPriority + 1;
|
||||
|
||||
do
|
||||
{
|
||||
uxQueue--;
|
||||
|
||||
if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime );
|
||||
}
|
||||
}while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime );
|
||||
}
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime );
|
||||
}
|
||||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize )
|
||||
{
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
pcTraceBuffer = ( signed char * )pcBuffer;
|
||||
pcTraceBufferStart = pcBuffer;
|
||||
pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE );
|
||||
xTracing = pdTRUE;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
unsigned long ulTaskEndTrace( void )
|
||||
{
|
||||
unsigned long ulBufferLength;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
xTracing = pdFALSE;
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart );
|
||||
|
||||
return ulBufferLength;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
|
||||
* documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
void vTaskIncrementTick( void )
|
||||
{
|
||||
/* 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. */
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
++xTickCount;
|
||||
if( xTickCount == ( portTickType ) 0 )
|
||||
{
|
||||
xList *pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists.
|
||||
If there are any items in pxDelayedTaskList here then there is
|
||||
an error! */
|
||||
pxTemp = pxDelayedTaskList;
|
||||
pxDelayedTaskList = pxOverflowDelayedTaskList;
|
||||
pxOverflowDelayedTaskList = pxTemp;
|
||||
xNumOfOverflows++;
|
||||
}
|
||||
|
||||
/* See if this tick has made a timeout expire. */
|
||||
prvCheckDelayedTasks();
|
||||
}
|
||||
else
|
||||
{
|
||||
++uxMissedTicks;
|
||||
|
||||
/* The tick hook gets called at regular intervals, even if the
|
||||
scheduler is locked. */
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
{
|
||||
extern void vApplicationTickHook( void );
|
||||
|
||||
vApplicationTickHook();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
{
|
||||
extern void vApplicationTickHook( void );
|
||||
|
||||
/* Guard against the tick hook being called when the missed tick
|
||||
count is being unwound (when the scheduler is being unlocked. */
|
||||
if( uxMissedTicks == 0 )
|
||||
{
|
||||
vApplicationTickHook();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
traceTASK_INCREMENT_TICK( xTickCount );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
|
||||
|
||||
void vTaskCleanUpResources( void )
|
||||
{
|
||||
unsigned short usQueue;
|
||||
volatile tskTCB *pxTCB;
|
||||
|
||||
usQueue = ( unsigned short ) uxTopUsedPriority + ( unsigned short ) 1;
|
||||
|
||||
/* Remove any TCB's from the ready queues. */
|
||||
do
|
||||
{
|
||||
usQueue--;
|
||||
|
||||
while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
}while( usQueue > ( unsigned short ) tskIDLE_PRIORITY );
|
||||
|
||||
/* Remove any TCB's from the delayed queue. */
|
||||
while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
|
||||
/* Remove any TCB's from the overflow delayed queue. */
|
||||
while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
|
||||
while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
||||
|
||||
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue )
|
||||
{
|
||||
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. */
|
||||
portENTER_CRITICAL();
|
||||
xTCB->pxTaskTag = pxTagValue;
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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. */
|
||||
portENTER_CRITICAL();
|
||||
xReturn = xTCB->pxTaskTag;
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskSwitchContext( void )
|
||||
{
|
||||
if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
/* The scheduler is currently suspended - do not allow a context
|
||||
switch. */
|
||||
xMissedYield = pdTRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
traceTASK_SWITCHED_OUT();
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
{
|
||||
unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
|
||||
/* 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. Generally
|
||||
this will be about 1 hour assuming a 1uS timer increment. */
|
||||
pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
|
||||
ulTaskSwitchedInTime = ulTempCounter;
|
||||
}
|
||||
#endif
|
||||
|
||||
taskFIRST_CHECK_FOR_STACK_OVERFLOW();
|
||||
taskSECOND_CHECK_FOR_STACK_OVERFLOW();
|
||||
|
||||
/* Find the highest priority queue that contains ready tasks. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
|
||||
{
|
||||
--uxTopReadyPriority;
|
||||
}
|
||||
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY walks 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 ] ) );
|
||||
|
||||
traceTASK_SWITCHED_IN();
|
||||
vWriteTraceToBuffer();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
|
||||
/* 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( ( xList * ) pxEventList, ( xListItem * ) &( 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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
|
||||
|
||||
#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( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( 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;
|
||||
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the overflow list. */
|
||||
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( 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;
|
||||
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the overflow list. */
|
||||
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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. */
|
||||
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
vListRemove( &( pxUnblockedTCB->xEventListItem ) );
|
||||
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
vListRemove( &( pxUnblockedTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( pxUnblockedTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We cannot access the delayed or ready lists, so will hold this
|
||||
task pending until the scheduler is resumed. */
|
||||
vListInsertEnd( ( xList * ) &( 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
|
||||
{
|
||||
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
||||
pxTimeOut->xTimeOnEntering = xTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
#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 ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
|
||||
{
|
||||
/* 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( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )
|
||||
{
|
||||
/* Not a genuine timeout. Adjust parameters for time remaining. */
|
||||
*pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
|
||||
vTaskSetTimeOutState( pxTimeOut );
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskMissedYield( void )
|
||||
{
|
||||
xMissedYield = pdTRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------
|
||||
* 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
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
// call nanosleep for smalles sleep time possible
|
||||
// (depending on kernel settings - around 100 microseconds)
|
||||
// decreases idle thread CPU load from 100 to practically 0
|
||||
#ifndef __CYGWIN__
|
||||
sigset_t xSignals;
|
||||
sigfillset( &xSignals );
|
||||
pthread_sigmask( SIG_SETMASK, &xSignals, NULL );
|
||||
struct timespec x;
|
||||
x.tv_sec=0;
|
||||
x.tv_nsec=10000;
|
||||
nanosleep(&x,NULL);
|
||||
sigemptyset( &xSignals );
|
||||
pthread_sigmask( SIG_SETMASK, &xSignals, NULL );
|
||||
#endif
|
||||
}
|
||||
} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* File private functions documented at the top of the file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
|
||||
{
|
||||
/* Store the function name in the TCB. */
|
||||
#if configMAX_TASK_NAME_LEN > 1
|
||||
{
|
||||
/* Don't bring strncpy into the build unnecessarily. */
|
||||
strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN );
|
||||
}
|
||||
#endif
|
||||
pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = '\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 >= configMAX_PRIORITIES )
|
||||
{
|
||||
uxPriority = configMAX_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
pxTCB->uxPriority = uxPriority;
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
pxTCB->uxBasePriority = uxPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
|
||||
listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
{
|
||||
pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
||||
{
|
||||
pxTCB->pxTaskTag = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
{
|
||||
pxTCB->ulRunTimeCounter = 0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
{
|
||||
vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
|
||||
}
|
||||
#else
|
||||
{
|
||||
( void ) xRegions;
|
||||
( void ) usStackDepth;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
|
||||
void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
if( xTaskToModify == pxCurrentTCB )
|
||||
{
|
||||
xTaskToModify = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are deleting ourselves. */
|
||||
pxTCB = prvGetTCBFromHandle( xTaskToModify );
|
||||
|
||||
vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
static void prvInitialiseTaskLists( void )
|
||||
{
|
||||
unsigned portBASE_TYPE uxPriority;
|
||||
|
||||
for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ )
|
||||
{
|
||||
vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );
|
||||
}
|
||||
|
||||
vListInitialise( ( xList * ) &xDelayedTaskList1 );
|
||||
vListInitialise( ( xList * ) &xDelayedTaskList2 );
|
||||
vListInitialise( ( xList * ) &xPendingReadyList );
|
||||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
vListInitialise( ( xList * ) &xTasksWaitingTermination );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
vListInitialise( ( xList * ) &xSuspendedTaskList );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
|
||||
xTaskResumeAll();
|
||||
|
||||
if( !xListIsEmpty )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
--uxCurrentNumberOfTasks;
|
||||
--uxTasksDeleted;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
prvDeleteTCB( pxTCB );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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 );
|
||||
|
||||
if( pxNewTCB->pxStack == NULL )
|
||||
{
|
||||
/* Could not allocate the stack. Delete the allocated TCB. */
|
||||
vPortFree( pxNewTCB );
|
||||
pxNewTCB = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just to help debugging. */
|
||||
memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) );
|
||||
}
|
||||
}
|
||||
|
||||
return pxNewTCB;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus )
|
||||
{
|
||||
volatile tskTCB *pxNextTCB, *pxFirstTCB;
|
||||
unsigned short usStackRemaining;
|
||||
|
||||
/* Write the details of all the TCB's in pxList into the buffer. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
||||
do
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
||||
#if ( portSTACK_GROWTH > 0 )
|
||||
{
|
||||
usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
|
||||
}
|
||||
#else
|
||||
{
|
||||
usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
|
||||
}
|
||||
#endif
|
||||
|
||||
sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );
|
||||
strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
|
||||
|
||||
} while( pxNextTCB != pxFirstTCB );
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime )
|
||||
{
|
||||
volatile tskTCB *pxNextTCB, *pxFirstTCB;
|
||||
unsigned long ulStatsAsPercentage;
|
||||
|
||||
/* Write the run time stats of all the TCB's in pxList into the buffer. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
||||
do
|
||||
{
|
||||
/* Get next TCB in from the list. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
||||
|
||||
/* Divide by zero check. */
|
||||
if( ulTotalRunTime > 0UL )
|
||||
{
|
||||
/* Has the task run at all? */
|
||||
if( pxNextTCB->ulRunTimeCounter == 0 )
|
||||
{
|
||||
/* The task has used no CPU time at all. */
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* What percentage of the total run time as the task used?
|
||||
This will always be rounded down to the nearest integer. */
|
||||
ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime;
|
||||
|
||||
if( ulStatsAsPercentage > 0UL )
|
||||
{
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the percentage is zero here then the task has
|
||||
consumed less than 1% of the total run time. */
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter );
|
||||
}
|
||||
}
|
||||
|
||||
strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString );
|
||||
}
|
||||
|
||||
} while( pxNextTCB != pxFirstTCB );
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
||||
|
||||
static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
|
||||
{
|
||||
register unsigned short usCount = 0;
|
||||
|
||||
while( *pucStackByte == tskSTACK_FILL_BYTE )
|
||||
{
|
||||
pucStackByte -= portSTACK_GROWTH;
|
||||
usCount++;
|
||||
}
|
||||
|
||||
usCount /= sizeof( portSTACK_TYPE );
|
||||
|
||||
return usCount;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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 ) usTaskCheckFreeStackSpace( pcEndOfStack );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
|
||||
|
||||
static void prvDeleteTCB( tskTCB *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
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_xTaskGetCurrentTaskHandle == 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_xTaskGetSchedulerState == 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
|
||||
{
|
||||
tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
|
||||
|
||||
if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* Adjust the mutex holder state to account for its new priority. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
|
||||
|
||||
/* If the task being modified is in the ready state it will need to
|
||||
be moved in to a new list. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
||||
{
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Inherit the priority before being moved into the new list. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just inherit the priority. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Disinherit the priority before adding ourselves into the new
|
||||
ready list. */
|
||||
pxTCB->uxPriority = pxTCB->uxBasePriority;
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
||||
void vTaskEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
pxCurrentTCB->uxCriticalNesting++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
||||
void vTaskExitCritical( void )
|
||||
{
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( pxCurrentTCB->uxCriticalNesting > 0 )
|
||||
{
|
||||
pxCurrentTCB->uxCriticalNesting--;
|
||||
|
||||
if( pxCurrentTCB->uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
2323
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/tasks_linux.c
Normal file
2323
flight/PiOS.osx/osx/Libraries/FreeRTOS/Source/tasks_linux.c
Normal file
@ -0,0 +1,2323 @@
|
||||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). 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 exception 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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 "StackMacros.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*
|
||||
* Macro to define the amount of stack available to the idle task.
|
||||
*/
|
||||
#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
/*
|
||||
* Task control block. A task control block (TCB) is allocated to each task,
|
||||
* and stores the context of the task.
|
||||
*/
|
||||
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 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 STRUCT. */
|
||||
#endif
|
||||
|
||||
xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */
|
||||
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */
|
||||
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 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; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
|
||||
#endif
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
unsigned portBASE_TYPE uxCriticalNesting;
|
||||
#endif
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
|
||||
#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; /*< Used for calculating how much CPU time each task is utilising. */
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
#endif
|
||||
|
||||
/*lint -e956 */
|
||||
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 queue when the scheduler is resumed. */
|
||||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
|
||||
PRIVILEGED_DATA static volatile 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 ) 0;
|
||||
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
|
||||
|
||||
#endif
|
||||
|
||||
/* File private variables. --------------------------------*/
|
||||
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0;
|
||||
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;
|
||||
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 uxMissedTicks = ( unsigned portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
||||
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
||||
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
PRIVILEGED_DATA static char pcStatsString[ 50 ] ;
|
||||
PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
|
||||
static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif
|
||||
|
||||
/* 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 ( 0xa5 )
|
||||
|
||||
/*
|
||||
* 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' )
|
||||
|
||||
/*
|
||||
* Macros and private variables used by the trace facility.
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
#define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )
|
||||
PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;
|
||||
PRIVILEGED_DATA static signed char *pcTraceBufferStart;
|
||||
PRIVILEGED_DATA static signed char *pcTraceBufferEnd;
|
||||
PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;
|
||||
static unsigned portBASE_TYPE uxPreviousTask = 255;
|
||||
PRIVILEGED_DATA static char pcStatusString[ 50 ];
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro that writes a trace of scheduler activity to a buffer. This trace
|
||||
* shows which task is running when and is very useful as a debugging tool.
|
||||
* As this macro is called each context switch it is a good idea to undefine
|
||||
* it if not using the facility.
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
#define vWriteTraceToBuffer() \
|
||||
{ \
|
||||
if( xTracing ) \
|
||||
{ \
|
||||
if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \
|
||||
{ \
|
||||
if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
|
||||
{ \
|
||||
uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
|
||||
*( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \
|
||||
pcTraceBuffer += sizeof( unsigned long ); \
|
||||
*( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \
|
||||
pcTraceBuffer += sizeof( unsigned long ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
xTracing = pdFALSE; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define vWriteTraceToBuffer()
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Place the task represented by pxTCB into the appropriate ready queue for
|
||||
* the task. It is inserted at the end of the list. One quirk of this is
|
||||
* that if the task being inserted is at the same priority as the currently
|
||||
* executing task, then it will only be rescheduled after the currently
|
||||
* executing task has been rescheduled.
|
||||
*/
|
||||
#define prvAddTaskToReadyQueue( pxTCB ) \
|
||||
{ \
|
||||
if( pxTCB->uxPriority > uxTopReadyPriority ) \
|
||||
{ \
|
||||
uxTopReadyPriority = pxTCB->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of tasks that are currently delayed to see if
|
||||
* any require waking.
|
||||
*
|
||||
* Tasks are stored in the queue in the order of their wake time - meaning
|
||||
* once one tasks has been found whose timer has not expired we need not look
|
||||
* any further down the list.
|
||||
*/
|
||||
#define prvCheckDelayedTasks() \
|
||||
{ \
|
||||
register tskTCB *pxTCB; \
|
||||
\
|
||||
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
|
||||
{ \
|
||||
if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
vListRemove( &( pxTCB->xGenericListItem ) ); \
|
||||
/* Is the task waiting on an event also? */ \
|
||||
if( pxTCB->xEventListItem.pvContainer ) \
|
||||
{ \
|
||||
vListRemove( &( pxTCB->xEventListItem ) ); \
|
||||
} \
|
||||
prvAddTaskToReadyQueue( pxTCB ); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 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 )
|
||||
|
||||
|
||||
/* 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 ) || ( INCLUDE_vTaskCleanUpResources == 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;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Called from vTaskList. vListTasks details all the tasks currently under
|
||||
* control of the scheduler. The tasks may be in one of a number of lists.
|
||||
* prvListTaskWithinSingleList accepts a list and details the tasks from
|
||||
* within just that list.
|
||||
*
|
||||
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
|
||||
* NORMAL APPLICATION CODE.
|
||||
*/
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) 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 usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*lint +e956 */
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CREATION API documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
|
||||
/* 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 ) != 0x00 )
|
||||
{
|
||||
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 - 1 );
|
||||
pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) );
|
||||
}
|
||||
#else
|
||||
{
|
||||
pxTopOfStack = pxNewTCB->pxStack;
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
{
|
||||
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We are going to manipulate the task queues to add this task to a
|
||||
ready list, so must make sure no interrupts occur. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
uxCurrentNumberOfTasks++;
|
||||
if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
|
||||
{
|
||||
/* As this is the first task it must also be the current task. */
|
||||
pxCurrentTCB = pxNewTCB;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the top priority to make context switching faster. Use
|
||||
the priority in pxNewTCB as this has been capped to a valid value. */
|
||||
if( pxNewTCB->uxPriority > uxTopUsedPriority )
|
||||
{
|
||||
uxTopUsedPriority = pxNewTCB->uxPriority;
|
||||
}
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
{
|
||||
/* Add a counter into the TCB for tracing only. */
|
||||
pxNewTCB->uxTCBNumber = uxTaskNumber;
|
||||
}
|
||||
#endif
|
||||
uxTaskNumber++;
|
||||
|
||||
prvAddTaskToReadyQueue( pxNewTCB );
|
||||
|
||||
xReturn = pdPASS;
|
||||
traceTASK_CREATE( pxNewTCB );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
traceTASK_CREATE_FAILED( pxNewTCB );
|
||||
}
|
||||
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 pxTaskToDelete )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
deleted. */
|
||||
if( pxTaskToDelete == pxCurrentTCB )
|
||||
{
|
||||
pxTaskToDelete = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are deleting ourselves. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
|
||||
|
||||
/* 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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
if( pxTCB->xEventListItem.pvContainer )
|
||||
{
|
||||
vListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
||||
vListInsertEnd( ( xList * ) &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 );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Force a reschedule if we have just deleted the current task. */
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( ( void * ) pxTaskToDelete == NULL )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* TASK CONTROL API documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskDelayUntil == 1 )
|
||||
|
||||
void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Generate the tick time at which the task wants to wake. */
|
||||
xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
|
||||
|
||||
if( xTickCount < *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 > xTickCount ) )
|
||||
{
|
||||
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 > xTickCount ) )
|
||||
{
|
||||
xShouldDelay = pdTRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the wake time ready for the next call. */
|
||||
*pxPreviousWakeTime = xTimeToWake;
|
||||
|
||||
if( xShouldDelay )
|
||||
{
|
||||
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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
|
||||
/* 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( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
/* Force a reschedule if xTaskResumeAll has not already done so, we may
|
||||
have put ourselves to sleep. */
|
||||
if( !xAlreadyYielded )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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 ) 0 )
|
||||
{
|
||||
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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
|
||||
/* 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( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
}
|
||||
|
||||
/* Force a reschedule if xTaskResumeAll has not already done so, we may
|
||||
have put ourselves to sleep. */
|
||||
if( !xAlreadyYielded )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_uxTaskPriorityGet == 1 )
|
||||
|
||||
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
unsigned portBASE_TYPE uxReturn;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* If null is passed in here then we are changing the
|
||||
priority of the calling function. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTask );
|
||||
uxReturn = pxTCB->uxPriority;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskPrioritySet == 1 )
|
||||
|
||||
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE;
|
||||
|
||||
/* Ensure the new priority is valid. */
|
||||
if( uxNewPriority >= configMAX_PRIORITIES )
|
||||
{
|
||||
uxNewPriority = configMAX_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
if( pxTask == pxCurrentTCB )
|
||||
{
|
||||
pxTask = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are changing the
|
||||
priority of the calling function. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTask );
|
||||
|
||||
traceTASK_PRIORITY_SET( pxTask, uxNewPriority );
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
uxCurrentPriority = pxTCB->uxBasePriority;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uxCurrentPriority = pxTCB->uxPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( uxCurrentPriority != uxNewPriority )
|
||||
{
|
||||
/* The priority change may have readied a task of higher
|
||||
priority than the calling task. */
|
||||
if( uxNewPriority > uxCurrentPriority )
|
||||
{
|
||||
if( pxTask != NULL )
|
||||
{
|
||||
/* The priority of another task is being raised. If we
|
||||
were raising the priority of the currently running task
|
||||
there would be no need to switch as it must have already
|
||||
been the highest priority task. */
|
||||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
}
|
||||
else if( pxTask == NULL )
|
||||
{
|
||||
/* Setting our own priority down means there may now be another
|
||||
task of higher priority that is ready to execute. */
|
||||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#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 ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );
|
||||
|
||||
/* 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 queue appropriate to its new priority. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
||||
{
|
||||
/* 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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
|
||||
if( xYieldRequired == pdTRUE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
void vTaskSuspend( xTaskHandle pxTaskToSuspend )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Ensure a yield is performed if the current task is being
|
||||
suspended. */
|
||||
if( pxTaskToSuspend == pxCurrentTCB )
|
||||
{
|
||||
pxTaskToSuspend = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are suspending ourselves. */
|
||||
pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );
|
||||
|
||||
traceTASK_SUSPEND( pxTCB );
|
||||
|
||||
/* Remove task from the ready/delayed list and place in the suspended list. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Is the task waiting on an event also? */
|
||||
if( pxTCB->xEventListItem.pvContainer )
|
||||
{
|
||||
vListRemove( &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
|
||||
vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* We may have just suspended the current task. */
|
||||
if( ( void * ) pxTaskToSuspend == NULL )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
|
||||
{
|
||||
portBASE_TYPE xReturn = pdFALSE;
|
||||
const tskTCB * const pxTCB = ( tskTCB * ) 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 ) ) != pdTRUE )
|
||||
{
|
||||
/* 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 ) ) == pdTRUE )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
|
||||
void vTaskResume( xTaskHandle pxTaskToResume )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
/* Remove the task from whichever list it is currently in, and place
|
||||
it in the ready list. */
|
||||
pxTCB = ( tskTCB * ) pxTaskToResume;
|
||||
|
||||
/* The parameter cannot be NULL as it is impossible to resume the
|
||||
currently executing task. */
|
||||
if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
|
||||
{
|
||||
portENTER_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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
|
||||
|
||||
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
|
||||
{
|
||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||
tskTCB *pxTCB;
|
||||
|
||||
pxTCB = ( tskTCB * ) pxTaskToResume;
|
||||
|
||||
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||
{
|
||||
traceTASK_RESUME_FROM_ISR( pxTCB );
|
||||
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( 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( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
|
||||
return xYieldRequired;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC SCHEDULER CONTROL documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
void vTaskStartScheduler( void )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
/* Add the idle task at the lowest priority. */
|
||||
xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL );
|
||||
|
||||
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.
|
||||
|
||||
STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
|
||||
DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
xSchedulerRunning = pdTRUE;
|
||||
xTickCount = ( portTickType ) 0;
|
||||
|
||||
/* 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() )
|
||||
{
|
||||
/* 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(). */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
signed portBASE_TYPE xTaskResumeAll( void )
|
||||
{
|
||||
register tskTCB *pxTCB;
|
||||
signed portBASE_TYPE xAlreadyYielded = pdFALSE;
|
||||
|
||||
/* 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. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
--uxSchedulerSuspended;
|
||||
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
portBASE_TYPE xYieldRequired = pdFALSE;
|
||||
|
||||
/* Move any readied tasks from the pending list into the
|
||||
appropriate ready list. */
|
||||
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
|
||||
{
|
||||
vListRemove( &( pxTCB->xEventListItem ) );
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( 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 )
|
||||
{
|
||||
xYieldRequired = 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( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
vTaskIncrementTick();
|
||||
--uxMissedTicks;
|
||||
}
|
||||
|
||||
/* As we have processed some ticks it is appropriate to yield
|
||||
to ensure the highest priority task that is ready to run is
|
||||
the task actually running. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
xYieldRequired = pdTRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
|
||||
{
|
||||
xAlreadyYielded = pdTRUE;
|
||||
xMissedYield = pdFALSE;
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xAlreadyYielded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC TASK UTILITIES documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
portTickType xTaskGetTickCount( void )
|
||||
{
|
||||
portTickType xTicks;
|
||||
|
||||
/* Critical section required if running on a 16 bit processor. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
xTicks = xTickCount;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xTicks;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
||||
{
|
||||
/* A critical section is not required because the variables are of type
|
||||
portBASE_TYPE. */
|
||||
return uxCurrentNumberOfTasks;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void vTaskList( signed char *pcWriteBuffer )
|
||||
{
|
||||
unsigned portBASE_TYPE uxQueue;
|
||||
|
||||
/* This is a VERY costly function that should be used for debug only.
|
||||
It leaves interrupts disabled for a LONG time. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Run through all the lists that could potentially contain a TCB and
|
||||
report the task name, state and stack high water mark. */
|
||||
|
||||
pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
|
||||
strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
|
||||
|
||||
uxQueue = uxTopUsedPriority + 1;
|
||||
|
||||
do
|
||||
{
|
||||
uxQueue--;
|
||||
|
||||
if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR );
|
||||
}
|
||||
}while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR );
|
||||
}
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR );
|
||||
}
|
||||
|
||||
#if( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
||||
{
|
||||
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
|
||||
{
|
||||
unsigned portBASE_TYPE uxQueue;
|
||||
unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
|
||||
/* This is a VERY costly function that should be used for debug only.
|
||||
It leaves interrupts disabled for a LONG time. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Run through all the lists that could potentially contain a TCB,
|
||||
generating a table of run timer percentages in the provided
|
||||
buffer. */
|
||||
|
||||
pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
|
||||
strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
|
||||
|
||||
uxQueue = uxTopUsedPriority + 1;
|
||||
|
||||
do
|
||||
{
|
||||
uxQueue--;
|
||||
|
||||
if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime );
|
||||
}
|
||||
}while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime );
|
||||
}
|
||||
|
||||
if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime );
|
||||
}
|
||||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
||||
{
|
||||
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
xTaskResumeAll();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize )
|
||||
{
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
pcTraceBuffer = ( signed char * )pcBuffer;
|
||||
pcTraceBufferStart = pcBuffer;
|
||||
pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE );
|
||||
xTracing = pdTRUE;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
unsigned long ulTaskEndTrace( void )
|
||||
{
|
||||
unsigned long ulBufferLength;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
xTracing = pdFALSE;
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart );
|
||||
|
||||
return ulBufferLength;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
|
||||
* documented in task.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
void vTaskIncrementTick( void )
|
||||
{
|
||||
/* 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. */
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
++xTickCount;
|
||||
if( xTickCount == ( portTickType ) 0 )
|
||||
{
|
||||
xList *pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists.
|
||||
If there are any items in pxDelayedTaskList here then there is
|
||||
an error! */
|
||||
pxTemp = pxDelayedTaskList;
|
||||
pxDelayedTaskList = pxOverflowDelayedTaskList;
|
||||
pxOverflowDelayedTaskList = pxTemp;
|
||||
xNumOfOverflows++;
|
||||
}
|
||||
|
||||
/* See if this tick has made a timeout expire. */
|
||||
prvCheckDelayedTasks();
|
||||
}
|
||||
else
|
||||
{
|
||||
++uxMissedTicks;
|
||||
|
||||
/* The tick hook gets called at regular intervals, even if the
|
||||
scheduler is locked. */
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
{
|
||||
extern void vApplicationTickHook( void );
|
||||
|
||||
vApplicationTickHook();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ( configUSE_TICK_HOOK == 1 )
|
||||
{
|
||||
extern void vApplicationTickHook( void );
|
||||
|
||||
/* Guard against the tick hook being called when the missed tick
|
||||
count is being unwound (when the scheduler is being unlocked. */
|
||||
if( uxMissedTicks == 0 )
|
||||
{
|
||||
vApplicationTickHook();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
traceTASK_INCREMENT_TICK( xTickCount );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
|
||||
|
||||
void vTaskCleanUpResources( void )
|
||||
{
|
||||
unsigned short usQueue;
|
||||
volatile tskTCB *pxTCB;
|
||||
|
||||
usQueue = ( unsigned short ) uxTopUsedPriority + ( unsigned short ) 1;
|
||||
|
||||
/* Remove any TCB's from the ready queues. */
|
||||
do
|
||||
{
|
||||
usQueue--;
|
||||
|
||||
while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
}while( usQueue > ( unsigned short ) tskIDLE_PRIORITY );
|
||||
|
||||
/* Remove any TCB's from the delayed queue. */
|
||||
while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
|
||||
/* Remove any TCB's from the overflow delayed queue. */
|
||||
while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
|
||||
while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList );
|
||||
vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
|
||||
|
||||
prvDeleteTCB( ( tskTCB * ) pxTCB );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
||||
|
||||
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue )
|
||||
{
|
||||
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. */
|
||||
portENTER_CRITICAL();
|
||||
xTCB->pxTaskTag = pxTagValue;
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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. */
|
||||
portENTER_CRITICAL();
|
||||
xReturn = xTCB->pxTaskTag;
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskSwitchContext( void )
|
||||
{
|
||||
if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
/* The scheduler is currently suspended - do not allow a context
|
||||
switch. */
|
||||
xMissedYield = pdTRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
traceTASK_SWITCHED_OUT();
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
{
|
||||
unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
|
||||
|
||||
/* 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. Generally
|
||||
this will be about 1 hour assuming a 1uS timer increment. */
|
||||
pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
|
||||
ulTaskSwitchedInTime = ulTempCounter;
|
||||
}
|
||||
#endif
|
||||
|
||||
taskFIRST_CHECK_FOR_STACK_OVERFLOW();
|
||||
taskSECOND_CHECK_FOR_STACK_OVERFLOW();
|
||||
|
||||
/* Find the highest priority queue that contains ready tasks. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
|
||||
{
|
||||
--uxTopReadyPriority;
|
||||
}
|
||||
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY walks 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 ] ) );
|
||||
|
||||
traceTASK_SWITCHED_IN();
|
||||
vWriteTraceToBuffer();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )
|
||||
{
|
||||
portTickType xTimeToWake;
|
||||
|
||||
/* 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( ( xList * ) pxEventList, ( xListItem * ) &( 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. */
|
||||
vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
|
||||
|
||||
#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( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( 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;
|
||||
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the overflow list. */
|
||||
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( 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;
|
||||
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the overflow list. */
|
||||
vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the current block list. */
|
||||
vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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. */
|
||||
pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
vListRemove( &( pxUnblockedTCB->xEventListItem ) );
|
||||
|
||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||
{
|
||||
vListRemove( &( pxUnblockedTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyQueue( pxUnblockedTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We cannot access the delayed or ready lists, so will hold this
|
||||
task pending until the scheduler is resumed. */
|
||||
vListInsertEnd( ( xList * ) &( 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
|
||||
{
|
||||
pxTimeOut->xOverflowCount = xNumOfOverflows;
|
||||
pxTimeOut->xTimeOnEntering = xTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
|
||||
{
|
||||
portBASE_TYPE xReturn;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
#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 ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
|
||||
{
|
||||
/* 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( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )
|
||||
{
|
||||
/* Not a genuine timeout. Adjust parameters for time remaining. */
|
||||
*pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
|
||||
vTaskSetTimeOutState( pxTimeOut );
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTaskMissedYield( void )
|
||||
{
|
||||
xMissedYield = pdTRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------
|
||||
* 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
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
// call nanosleep for smalles sleep time possible
|
||||
// (depending on kernel settings - around 100 microseconds)
|
||||
// decreases idle thread CPU load from 100 to practically 0
|
||||
struct timespec x;
|
||||
x.tv_sec=1;
|
||||
x.tv_nsec=0;
|
||||
nanosleep(&x,NULL);
|
||||
}
|
||||
} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* File private functions documented at the top of the file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
|
||||
{
|
||||
/* Store the function name in the TCB. */
|
||||
#if configMAX_TASK_NAME_LEN > 1
|
||||
{
|
||||
/* Don't bring strncpy into the build unnecessarily. */
|
||||
strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN );
|
||||
}
|
||||
#endif
|
||||
pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = '\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 >= configMAX_PRIORITIES )
|
||||
{
|
||||
uxPriority = configMAX_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
pxTCB->uxPriority = uxPriority;
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
{
|
||||
pxTCB->uxBasePriority = uxPriority;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
|
||||
listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
{
|
||||
pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
||||
{
|
||||
pxTCB->pxTaskTag = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
{
|
||||
pxTCB->ulRunTimeCounter = 0UL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
{
|
||||
vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
|
||||
}
|
||||
#else
|
||||
{
|
||||
( void ) xRegions;
|
||||
( void ) usStackDepth;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||
|
||||
void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
if( xTaskToModify == pxCurrentTCB )
|
||||
{
|
||||
xTaskToModify = NULL;
|
||||
}
|
||||
|
||||
/* If null is passed in here then we are deleting ourselves. */
|
||||
pxTCB = prvGetTCBFromHandle( xTaskToModify );
|
||||
|
||||
vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
static void prvInitialiseTaskLists( void )
|
||||
{
|
||||
unsigned portBASE_TYPE uxPriority;
|
||||
|
||||
for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ )
|
||||
{
|
||||
vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );
|
||||
}
|
||||
|
||||
vListInitialise( ( xList * ) &xDelayedTaskList1 );
|
||||
vListInitialise( ( xList * ) &xDelayedTaskList2 );
|
||||
vListInitialise( ( xList * ) &xPendingReadyList );
|
||||
|
||||
#if ( INCLUDE_vTaskDelete == 1 )
|
||||
{
|
||||
vListInitialise( ( xList * ) &xTasksWaitingTermination );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( INCLUDE_vTaskSuspend == 1 )
|
||||
{
|
||||
vListInitialise( ( xList * ) &xSuspendedTaskList );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )
|
||||
{
|
||||
vTaskSuspendAll();
|
||||
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
|
||||
xTaskResumeAll();
|
||||
|
||||
if( !xListIsEmpty )
|
||||
{
|
||||
tskTCB *pxTCB;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
--uxCurrentNumberOfTasks;
|
||||
--uxTasksDeleted;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
prvDeleteTCB( pxTCB );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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 );
|
||||
|
||||
if( pxNewTCB->pxStack == NULL )
|
||||
{
|
||||
/* Could not allocate the stack. Delete the allocated TCB. */
|
||||
vPortFree( pxNewTCB );
|
||||
pxNewTCB = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just to help debugging. */
|
||||
memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) );
|
||||
}
|
||||
}
|
||||
|
||||
return pxNewTCB;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||
|
||||
static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus )
|
||||
{
|
||||
volatile tskTCB *pxNextTCB, *pxFirstTCB;
|
||||
unsigned short usStackRemaining;
|
||||
|
||||
/* Write the details of all the TCB's in pxList into the buffer. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
||||
do
|
||||
{
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
||||
#if ( portSTACK_GROWTH > 0 )
|
||||
{
|
||||
usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
|
||||
}
|
||||
#else
|
||||
{
|
||||
usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
|
||||
}
|
||||
#endif
|
||||
|
||||
sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );
|
||||
strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
|
||||
|
||||
} while( pxNextTCB != pxFirstTCB );
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
|
||||
static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime )
|
||||
{
|
||||
volatile tskTCB *pxNextTCB, *pxFirstTCB;
|
||||
unsigned long ulStatsAsPercentage;
|
||||
|
||||
/* Write the run time stats of all the TCB's in pxList into the buffer. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
||||
do
|
||||
{
|
||||
/* Get next TCB in from the list. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
||||
|
||||
/* Divide by zero check. */
|
||||
if( ulTotalRunTime > 0UL )
|
||||
{
|
||||
/* Has the task run at all? */
|
||||
if( pxNextTCB->ulRunTimeCounter == 0 )
|
||||
{
|
||||
/* The task has used no CPU time at all. */
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* What percentage of the total run time as the task used?
|
||||
This will always be rounded down to the nearest integer. */
|
||||
ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime;
|
||||
|
||||
if( ulStatsAsPercentage > 0UL )
|
||||
{
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the percentage is zero here then the task has
|
||||
consumed less than 1% of the total run time. */
|
||||
sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter );
|
||||
}
|
||||
}
|
||||
|
||||
strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString );
|
||||
}
|
||||
|
||||
} while( pxNextTCB != pxFirstTCB );
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
||||
|
||||
static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
|
||||
{
|
||||
register unsigned short usCount = 0;
|
||||
|
||||
while( *pucStackByte == tskSTACK_FILL_BYTE )
|
||||
{
|
||||
pucStackByte -= portSTACK_GROWTH;
|
||||
usCount++;
|
||||
}
|
||||
|
||||
usCount /= sizeof( portSTACK_TYPE );
|
||||
|
||||
return usCount;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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 ) usTaskCheckFreeStackSpace( pcEndOfStack );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
|
||||
|
||||
static void prvDeleteTCB( tskTCB *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
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_xTaskGetCurrentTaskHandle == 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
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_xTaskGetSchedulerState == 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_MUTEXES == 1 )
|
||||
|
||||
void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
|
||||
{
|
||||
tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
|
||||
|
||||
if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
|
||||
{
|
||||
/* Adjust the mutex holder state to account for its new priority. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
|
||||
|
||||
/* If the task being modified is in the ready state it will need to
|
||||
be moved in to a new list. */
|
||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
||||
{
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Inherit the priority before being moved into the new list. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just inherit the priority. */
|
||||
pxTCB->uxPriority = pxCurrentTCB->uxPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#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. */
|
||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||
|
||||
/* Disinherit the priority before adding ourselves into the new
|
||||
ready list. */
|
||||
pxTCB->uxPriority = pxTCB->uxBasePriority;
|
||||
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
|
||||
prvAddTaskToReadyQueue( pxTCB );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
||||
void vTaskEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
pxCurrentTCB->uxCriticalNesting++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||
|
||||
void vTaskExitCritical( void )
|
||||
{
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( pxCurrentTCB->uxCriticalNesting > 0 )
|
||||
{
|
||||
pxCurrentTCB->uxCriticalNesting--;
|
||||
|
||||
if( pxCurrentTCB->uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
522
flight/PiOS.osx/osx/pios_com.c
Normal file
522
flight/PiOS.osx/osx/pios_com.c
Normal file
@ -0,0 +1,522 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_COM COM layer functions
|
||||
* @brief Hardware communication layer
|
||||
* @{
|
||||
*
|
||||
* @file pios_com.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief COM layer functions
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_COM)
|
||||
|
||||
#include "fifo_buffer.h"
|
||||
#include <pios_com_priv.h>
|
||||
|
||||
#if !defined(PIOS_INCLUDE_FREERTOS)
|
||||
#include "pios_delay.h" /* PIOS_DELAY_WaitmS */
|
||||
#endif
|
||||
|
||||
enum pios_com_dev_magic {
|
||||
PIOS_COM_DEV_MAGIC = 0xaa55aa55,
|
||||
};
|
||||
|
||||
struct pios_com_dev {
|
||||
enum pios_com_dev_magic magic;
|
||||
uint32_t lower_id;
|
||||
const struct pios_com_driver * driver;
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
xSemaphoreHandle tx_sem;
|
||||
xSemaphoreHandle rx_sem;
|
||||
#endif
|
||||
|
||||
bool has_rx;
|
||||
bool has_tx;
|
||||
|
||||
t_fifo_buffer rx;
|
||||
t_fifo_buffer tx;
|
||||
};
|
||||
|
||||
static bool PIOS_COM_validate(struct pios_com_dev * com_dev)
|
||||
{
|
||||
return (com_dev && (com_dev->magic == PIOS_COM_DEV_MAGIC));
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
||||
// static struct pios_com_dev * PIOS_COM_alloc(void)
|
||||
//{
|
||||
// struct pios_com_dev * com_dev;
|
||||
//
|
||||
// com_dev = (struct pios_com_dev *)malloc(sizeof(*com_dev));
|
||||
// if (!com_dev) return (NULL);
|
||||
//
|
||||
// com_dev->magic = PIOS_COM_DEV_MAGIC;
|
||||
// return(com_dev);
|
||||
//}
|
||||
#else
|
||||
static struct pios_com_dev pios_com_devs[PIOS_COM_MAX_DEVS];
|
||||
static uint8_t pios_com_num_devs;
|
||||
static uint32_t PIOS_COM_create(void)
|
||||
{
|
||||
struct pios_com_dev * com_dev;
|
||||
|
||||
if (pios_com_num_devs >= PIOS_COM_MAX_DEVS) {
|
||||
return (PIOS_COM_MAX_DEVS+1);
|
||||
}
|
||||
|
||||
com_dev = &pios_com_devs[pios_com_num_devs++];
|
||||
com_dev->magic = PIOS_COM_DEV_MAGIC;
|
||||
|
||||
return (pios_com_num_devs);
|
||||
}
|
||||
static struct pios_com_dev * PIOS_COM_find_dev(uint32_t com_dev_id)
|
||||
{
|
||||
if (!com_dev_id) return NULL;
|
||||
if (com_dev_id>pios_com_num_devs+1) return NULL;
|
||||
return &pios_com_devs[com_dev_id-1];
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint16_t PIOS_COM_TxOutCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield);
|
||||
static uint16_t PIOS_COM_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield);
|
||||
static void PIOS_COM_UnblockRx(struct pios_com_dev * com_dev, bool * need_yield);
|
||||
static void PIOS_COM_UnblockTx(struct pios_com_dev * com_dev, bool * need_yield);
|
||||
|
||||
/**
|
||||
* Initialises COM layer
|
||||
* \param[out] handle
|
||||
* \param[in] driver
|
||||
* \param[in] id
|
||||
* \return < 0 if initialisation failed
|
||||
*/
|
||||
int32_t PIOS_COM_Init(uint32_t * com_id, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t * rx_buffer, uint16_t rx_buffer_len, uint8_t * tx_buffer, uint16_t tx_buffer_len)
|
||||
{
|
||||
PIOS_Assert(com_id);
|
||||
PIOS_Assert(driver);
|
||||
|
||||
bool has_rx = (rx_buffer && rx_buffer_len > 0);
|
||||
bool has_tx = (tx_buffer && tx_buffer_len > 0);
|
||||
PIOS_Assert(has_rx || has_tx);
|
||||
PIOS_Assert(driver->bind_tx_cb || !has_tx);
|
||||
PIOS_Assert(driver->bind_rx_cb || !has_rx);
|
||||
|
||||
uint32_t com_dev_id;
|
||||
struct pios_com_dev * com_dev;
|
||||
|
||||
com_dev_id = PIOS_COM_create();
|
||||
com_dev = PIOS_COM_find_dev(com_dev_id);
|
||||
if (!com_dev) goto out_fail;
|
||||
|
||||
com_dev->driver = driver;
|
||||
com_dev->lower_id = lower_id;
|
||||
|
||||
com_dev->has_rx = has_rx;
|
||||
com_dev->has_tx = has_tx;
|
||||
|
||||
if (has_rx) {
|
||||
fifoBuf_init(&com_dev->rx, rx_buffer, rx_buffer_len);
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
vSemaphoreCreateBinary(com_dev->rx_sem);
|
||||
#endif /* PIOS_INCLUDE_FREERTOS */
|
||||
(com_dev->driver->bind_rx_cb)(lower_id, PIOS_COM_RxInCallback, com_dev_id);
|
||||
if (com_dev->driver->rx_start) {
|
||||
/* Start the receiver */
|
||||
(com_dev->driver->rx_start)(com_dev->lower_id,
|
||||
fifoBuf_getFree(&com_dev->rx));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_tx) {
|
||||
fifoBuf_init(&com_dev->tx, tx_buffer, tx_buffer_len);
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
vSemaphoreCreateBinary(com_dev->tx_sem);
|
||||
#endif /* PIOS_INCLUDE_FREERTOS */
|
||||
(com_dev->driver->bind_tx_cb)(lower_id, PIOS_COM_TxOutCallback, com_dev_id);
|
||||
}
|
||||
|
||||
*com_id = com_dev_id;
|
||||
return(0);
|
||||
|
||||
out_fail:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static void PIOS_COM_UnblockRx(struct pios_com_dev * com_dev, bool * need_yield)
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static signed portBASE_TYPE xHigherPriorityTaskWoken;
|
||||
xSemaphoreGiveFromISR(com_dev->rx_sem, &xHigherPriorityTaskWoken);
|
||||
|
||||
if (xHigherPriorityTaskWoken != pdFALSE) {
|
||||
*need_yield = true;
|
||||
} else {
|
||||
*need_yield = false;
|
||||
}
|
||||
#else
|
||||
*need_yield = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void PIOS_COM_UnblockTx(struct pios_com_dev * com_dev, bool * need_yield)
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
static signed portBASE_TYPE xHigherPriorityTaskWoken;
|
||||
xSemaphoreGiveFromISR(com_dev->tx_sem, &xHigherPriorityTaskWoken);
|
||||
|
||||
if (xHigherPriorityTaskWoken != pdFALSE) {
|
||||
*need_yield = true;
|
||||
} else {
|
||||
*need_yield = false;
|
||||
}
|
||||
#else
|
||||
*need_yield = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint16_t PIOS_COM_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
|
||||
{
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(context);
|
||||
|
||||
bool valid = PIOS_COM_validate(com_dev);
|
||||
PIOS_Assert(valid);
|
||||
PIOS_Assert(com_dev->has_rx);
|
||||
|
||||
PIOS_IRQ_Disable();
|
||||
uint16_t bytes_into_fifo = fifoBuf_putData(&com_dev->rx, buf, buf_len);
|
||||
PIOS_IRQ_Enable();
|
||||
|
||||
if (bytes_into_fifo > 0) {
|
||||
/* Data has been added to the buffer */
|
||||
PIOS_COM_UnblockRx(com_dev, need_yield);
|
||||
}
|
||||
|
||||
if (headroom) {
|
||||
*headroom = fifoBuf_getFree(&com_dev->rx);
|
||||
}
|
||||
|
||||
return (bytes_into_fifo);
|
||||
}
|
||||
|
||||
static uint16_t PIOS_COM_TxOutCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
|
||||
{
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(context);
|
||||
|
||||
bool valid = PIOS_COM_validate(com_dev);
|
||||
PIOS_Assert(valid);
|
||||
PIOS_Assert(buf);
|
||||
PIOS_Assert(buf_len);
|
||||
PIOS_Assert(com_dev->has_tx);
|
||||
|
||||
PIOS_IRQ_Disable();
|
||||
uint16_t bytes_from_fifo = fifoBuf_getData(&com_dev->tx, buf, buf_len);
|
||||
PIOS_IRQ_Enable();
|
||||
|
||||
if (bytes_from_fifo > 0) {
|
||||
/* More space has been made in the buffer */
|
||||
PIOS_COM_UnblockTx(com_dev, need_yield);
|
||||
}
|
||||
|
||||
if (headroom) {
|
||||
*headroom = fifoBuf_getUsed(&com_dev->tx);
|
||||
}
|
||||
|
||||
return (bytes_from_fifo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the port speed without re-initializing
|
||||
* \param[in] port COM port
|
||||
* \param[in] baud Requested baud rate
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_ChangeBaud(uint32_t com_id, uint32_t baud)
|
||||
{
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(com_id);
|
||||
|
||||
if (!PIOS_COM_validate(com_dev)) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Invoke the driver function if it exists */
|
||||
if (com_dev->driver->set_baud) {
|
||||
com_dev->driver->set_baud(com_dev->lower_id, baud);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a package over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] buffer character buffer
|
||||
* \param[in] len buffer length
|
||||
* \return -1 if port not available
|
||||
* \return -2 if non-blocking mode activated: buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendBufferNonBlocking(uint32_t com_id, const uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(com_id);
|
||||
|
||||
if (!PIOS_COM_validate(com_dev)) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
PIOS_Assert(com_dev->has_tx);
|
||||
|
||||
if (len >= fifoBuf_getFree(&com_dev->tx)) {
|
||||
/* Buffer cannot accept all requested bytes (retry) */
|
||||
return -2;
|
||||
}
|
||||
|
||||
PIOS_IRQ_Disable();
|
||||
uint16_t bytes_into_fifo = fifoBuf_putData(&com_dev->tx, buffer, len);
|
||||
PIOS_IRQ_Enable();
|
||||
|
||||
if (bytes_into_fifo > 0) {
|
||||
/* More data has been put in the tx buffer, make sure the tx is started */
|
||||
if (com_dev->driver->tx_start) {
|
||||
com_dev->driver->tx_start(com_dev->lower_id,
|
||||
fifoBuf_getUsed(&com_dev->tx));
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a package over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] buffer character buffer
|
||||
* \param[in] len buffer length
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendBuffer(uint32_t com_id, const uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(com_id);
|
||||
|
||||
if (!PIOS_COM_validate(com_dev)) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
PIOS_Assert(com_dev->has_tx);
|
||||
|
||||
int32_t rc;
|
||||
do {
|
||||
rc = PIOS_COM_SendBufferNonBlocking(com_id, buffer, len);
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
if (rc == -2) {
|
||||
/* Make sure the transmitter is running while we wait */
|
||||
if (com_dev->driver->tx_start) {
|
||||
(com_dev->driver->tx_start)(com_dev->lower_id,
|
||||
fifoBuf_getUsed(&com_dev->tx));
|
||||
}
|
||||
if (xSemaphoreTake(com_dev->tx_sem, portMAX_DELAY) != pdTRUE) {
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} while (rc == -2);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a single character over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] c character
|
||||
* \return -1 if port not available
|
||||
* \return -2 buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendCharNonBlocking(uint32_t com_id, char c)
|
||||
{
|
||||
return PIOS_COM_SendBufferNonBlocking(com_id, (uint8_t *)&c, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a single character over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] c character
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendChar(uint32_t com_id, char c)
|
||||
{
|
||||
return PIOS_COM_SendBuffer(com_id, (uint8_t *)&c, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a string over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] str zero-terminated string
|
||||
* \return -1 if port not available
|
||||
* \return -2 buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendStringNonBlocking(uint32_t com_id, const char *str)
|
||||
{
|
||||
return PIOS_COM_SendBufferNonBlocking(com_id, (uint8_t *)str, (uint16_t)strlen(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a string over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] str zero-terminated string
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendString(uint32_t com_id, const char *str)
|
||||
{
|
||||
return PIOS_COM_SendBuffer(com_id, (uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a formatted string (-> printf) over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] *format zero-terminated format string - 128 characters supported maximum!
|
||||
* \param[in] ... optional arguments,
|
||||
* 128 characters supported maximum!
|
||||
* \return -2 if non-blocking mode activated: buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendFormattedStringNonBlocking(uint32_t com_id, const char *format, ...)
|
||||
{
|
||||
uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later!
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf((char *)buffer, format, args);
|
||||
return PIOS_COM_SendBufferNonBlocking(com_id, buffer, (uint16_t)strlen((char *)buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a formatted string (-> printf) over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] *format zero-terminated format string - 128 characters supported maximum!
|
||||
* \param[in] ... optional arguments,
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendFormattedString(uint32_t com_id, const char *format, ...)
|
||||
{
|
||||
uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later!
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf((char *)buffer, format, args);
|
||||
return PIOS_COM_SendBuffer(com_id, buffer, (uint16_t)strlen((char *)buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer bytes from port buffers into another buffer
|
||||
* \param[in] port COM port
|
||||
* \returns Byte from buffer
|
||||
*/
|
||||
uint16_t PIOS_COM_ReceiveBuffer(uint32_t com_id, uint8_t * buf, uint16_t buf_len, uint32_t timeout_ms)
|
||||
{
|
||||
PIOS_Assert(buf);
|
||||
PIOS_Assert(buf_len);
|
||||
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(com_id);
|
||||
|
||||
if (!PIOS_COM_validate(com_dev)) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
PIOS_Assert(com_dev->has_rx);
|
||||
|
||||
check_again:
|
||||
PIOS_IRQ_Disable();
|
||||
uint16_t bytes_from_fifo = fifoBuf_getData(&com_dev->rx, buf, buf_len);
|
||||
PIOS_IRQ_Enable();
|
||||
|
||||
if (bytes_from_fifo == 0 && timeout_ms > 0) {
|
||||
/* No more bytes in receive buffer */
|
||||
/* Make sure the receiver is running while we wait */
|
||||
if (com_dev->driver->rx_start) {
|
||||
/* Notify the lower layer that there is now room in the rx buffer */
|
||||
(com_dev->driver->rx_start)(com_dev->lower_id,
|
||||
fifoBuf_getFree(&com_dev->rx));
|
||||
}
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
if (xSemaphoreTake(com_dev->rx_sem, timeout_ms / portTICK_RATE_MS) == pdTRUE) {
|
||||
/* Make sure we don't come back here again */
|
||||
timeout_ms = 0;
|
||||
goto check_again;
|
||||
}
|
||||
#else
|
||||
PIOS_DELAY_WaitmS(1);
|
||||
timeout_ms--;
|
||||
goto check_again;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return received byte */
|
||||
return (bytes_from_fifo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes waiting in the buffer
|
||||
* \param[in] port COM port
|
||||
* \return Number of bytes used in buffer
|
||||
*/
|
||||
int32_t PIOS_COM_ReceiveBufferUsed(uint32_t com_id)
|
||||
{
|
||||
struct pios_com_dev * com_dev = PIOS_COM_find_dev(com_id);
|
||||
|
||||
if (!PIOS_COM_validate(com_dev)) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
|
||||
PIOS_Assert(com_dev->has_rx);
|
||||
return (fifoBuf_getUsed(&com_dev->rx));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
332
flight/PiOS.osx/osx/pios_com.c.old
Normal file
332
flight/PiOS.osx/osx/pios_com.c.old
Normal file
@ -0,0 +1,332 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_com.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief COM layer functions
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_COM COM layer functions
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_COM)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
//#include <pios_com_priv.h>
|
||||
#define NUM_FIFOS 16
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
int fifos_in[NUM_FIFOS];
|
||||
int fifos_out[NUM_FIFOS];
|
||||
|
||||
int buffer_fill[NUM_FIFOS];
|
||||
char buffer[NUM_FIFOS][BUFFER_SIZE];
|
||||
|
||||
|
||||
static int find_com_dev_by_id (uint8_t port)
|
||||
{
|
||||
if (port >= NUM_FIFOS) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get a handle for the device configuration */
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises COM layer
|
||||
* \param[in] mode currently only mode 0 supported
|
||||
* \return < 0 if initialisation failed
|
||||
*/
|
||||
int32_t PIOS_COM_Init(void)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
char filename[]="/tmp/OpenPlotCOMPort66666666.out";
|
||||
int32_t t;
|
||||
for (t=0;t<NUM_FIFOS;t++) {
|
||||
sprintf(filename,"/tmp/OpenPlotCOMPort%i.in",t);
|
||||
mknod(filename,S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO,0);
|
||||
fifos_in[t]=open(filename,O_RDONLY);
|
||||
|
||||
sprintf(filename,"/tmp/OpenPlotCOMPort%i.out",t);
|
||||
mknod(filename,S_IFIFO | S_IRWXU | S_IRWXG | S_IRWXO,0);
|
||||
fifos_out[t]=open(filename,O_RDONLY);
|
||||
|
||||
buffer_fill[t]=0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the port speed without re-initializing
|
||||
* \param[in] port COM port
|
||||
* \param[in] baud Requested baud rate
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_ChangeBaud(uint8_t port, uint32_t baud)
|
||||
{
|
||||
// struct pios_com_dev * com_dev;
|
||||
|
||||
int com_dev;
|
||||
com_dev = find_com_dev_by_id (port);
|
||||
|
||||
if (com_dev==-1) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Invoke the driver function if it exists */
|
||||
// if (com_dev->driver->set_baud) {
|
||||
// com_dev->driver->set_baud(com_dev->id, baud);
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a package over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] buffer character buffer
|
||||
* \param[in] len buffer length
|
||||
* \return -1 if port not available
|
||||
* \return -2 if non-blocking mode activated: buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendBufferNonBlocking(uint8_t port, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
int com_dev;
|
||||
int opts;
|
||||
|
||||
com_dev = find_com_dev_by_id (port);
|
||||
|
||||
if (com_dev==-1) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Invoke the driver function if it exists */
|
||||
//if (com_dev->driver->tx_nb) {
|
||||
// return com_dev->driver->tx_nb(com_dev->id, buffer, len);
|
||||
// }
|
||||
opts = fcntl(fifos_out[com_dev],F_GETFL);
|
||||
opts = opts | O_NONBLOCK;
|
||||
fcntl(fifos_out[com_dev],F_SETFL, opts);
|
||||
write(fifos_out[com_dev],buffer,len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a package over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] buffer character buffer
|
||||
* \param[in] len buffer length
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendBuffer(uint8_t port, uint8_t *buffer, uint16_t len)
|
||||
{
|
||||
int com_dev;
|
||||
int opts;
|
||||
|
||||
com_dev = find_com_dev_by_id (port);
|
||||
|
||||
if (com_dev==-1) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Invoke the driver function if it exists */
|
||||
//if (com_dev->driver->tx_nb) {
|
||||
// return com_dev->driver->tx_nb(com_dev->id, buffer, len);
|
||||
// }
|
||||
opts = fcntl(fifos_out[com_dev],F_GETFL);
|
||||
opts = opts & ~O_NONBLOCK;
|
||||
fcntl(fifos_out[com_dev],F_SETFL, opts);
|
||||
write(fifos_out[com_dev],buffer,len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a single character over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] c character
|
||||
* \return -1 if port not available
|
||||
* \return -2 buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendCharNonBlocking(uint8_t port, char c)
|
||||
{
|
||||
return PIOS_COM_SendBufferNonBlocking(port, (uint8_t *)&c, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a single character over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] c character
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendChar(uint8_t port, char c)
|
||||
{
|
||||
return PIOS_COM_SendBuffer(port, (uint8_t *)&c, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a string over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] str zero-terminated string
|
||||
* \return -1 if port not available
|
||||
* \return -2 buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendStringNonBlocking(uint8_t port, char *str)
|
||||
{
|
||||
return PIOS_COM_SendBufferNonBlocking(port, (uint8_t *)str, (uint16_t)strlen(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a string over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] str zero-terminated string
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendString(uint8_t port, char *str)
|
||||
{
|
||||
return PIOS_COM_SendBuffer(port, (uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a formatted string (-> printf) over given port
|
||||
* \param[in] port COM port
|
||||
* \param[in] *format zero-terminated format string - 128 characters supported maximum!
|
||||
* \param[in] ... optional arguments,
|
||||
* 128 characters supported maximum!
|
||||
* \return -2 if non-blocking mode activated: buffer is full
|
||||
* caller should retry until buffer is free again
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendFormattedStringNonBlocking(uint8_t port, char *format, ...)
|
||||
{
|
||||
uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later!
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf((char *)buffer, format, args);
|
||||
return PIOS_COM_SendBufferNonBlocking(port, buffer, (uint16_t)strlen((char *)buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a formatted string (-> printf) over given port
|
||||
* (blocking function)
|
||||
* \param[in] port COM port
|
||||
* \param[in] *format zero-terminated format string - 128 characters supported maximum!
|
||||
* \param[in] ... optional arguments,
|
||||
* \return -1 if port not available
|
||||
* \return 0 on success
|
||||
*/
|
||||
int32_t PIOS_COM_SendFormattedString(uint8_t port, char *format, ...)
|
||||
{
|
||||
uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later!
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vsprintf((char *)buffer, format, args);
|
||||
return PIOS_COM_SendBuffer(port, buffer, (uint16_t)strlen((char *)buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer bytes from port buffers into another buffer
|
||||
* \param[in] port COM port
|
||||
* \returns Byte from buffer
|
||||
*/
|
||||
uint8_t PIOS_COM_ReceiveBuffer(uint8_t port)
|
||||
{
|
||||
int com_dev;
|
||||
uint8_t b;
|
||||
|
||||
com_dev = find_com_dev_by_id (port);
|
||||
|
||||
if (com_dev==-1) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read one byte from buffer */
|
||||
b=buffer[com_dev][0];
|
||||
memmove(&buffer[com_dev][0],&buffer[com_dev][1],BUFFER_SIZE-1);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes waiting in the buffer
|
||||
* \param[in] port COM port
|
||||
* \return Number of bytes used in buffer
|
||||
*/
|
||||
int32_t PIOS_COM_ReceiveBufferUsed(uint8_t port)
|
||||
{
|
||||
int com_dev,opts;
|
||||
ssize_t read_bytes;
|
||||
|
||||
com_dev = find_com_dev_by_id (port);
|
||||
|
||||
if (com_dev==-1) {
|
||||
/* Undefined COM port for this board (see pios_board.c) */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fill buffer */
|
||||
opts = fcntl(fifos_out[com_dev],F_GETFL);
|
||||
opts = opts | O_NONBLOCK;
|
||||
fcntl(fifos_out[com_dev],F_SETFL, opts);
|
||||
read_bytes=read(fifos_in[com_dev],buffer[com_dev]+buffer_fill[com_dev],BUFFER_SIZE-buffer_fill[com_dev]);
|
||||
if (read_bytes<0) {
|
||||
read_bytes=0;
|
||||
}
|
||||
buffer_fill[com_dev]+=read_bytes;
|
||||
return buffer_fill[com_dev];
|
||||
|
||||
}
|
||||
|
||||
#endif
|
74
flight/PiOS.osx/osx/pios_crc.c
Normal file
74
flight/PiOS.osx/osx/pios_crc.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* pios_crc.c
|
||||
* OpenPilotOSX
|
||||
*
|
||||
* Created by James Cotton on 6/4/11.
|
||||
* Copyright 2011 OpenPilot. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
// CRC lookup table
|
||||
static const uint8_t crc_table[256] = {
|
||||
0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
|
||||
0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
|
||||
0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
|
||||
0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
|
||||
0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
|
||||
0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
|
||||
0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
|
||||
0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
|
||||
0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
|
||||
0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
|
||||
0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
|
||||
0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
|
||||
0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
|
||||
0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
|
||||
0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
|
||||
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the crc value with new data.
|
||||
*
|
||||
* Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/
|
||||
* using the configuration:
|
||||
* Width = 8
|
||||
* Poly = 0x07
|
||||
* XorIn = 0x00
|
||||
* ReflectIn = False
|
||||
* XorOut = 0x00
|
||||
* ReflectOut = False
|
||||
* Algorithm = table-driven
|
||||
*
|
||||
* \param crc The current crc value.
|
||||
* \param data Pointer to a buffer of \a data_len bytes.
|
||||
* \param length Number of bytes in the \a data buffer.
|
||||
* \return The updated crc value.
|
||||
*/
|
||||
uint8_t PIOS_CRC_updateByte(uint8_t crc, const uint8_t data)
|
||||
{
|
||||
return crc_table[crc ^ data];
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Update a CRC with a data buffer
|
||||
* @param[in] crc Starting CRC value
|
||||
* @param[in] data Data buffer
|
||||
* @param[in] length Number of bytes to process
|
||||
* @returns Updated CRC
|
||||
*/
|
||||
uint8_t PIOS_CRC_updateCRC(uint8_t crc, const uint8_t* data, int32_t length)
|
||||
{
|
||||
// use registers for speed
|
||||
register int32_t len = length;
|
||||
register uint8_t crc8 = crc;
|
||||
register const uint8_t *p = data;
|
||||
|
||||
while (len--)
|
||||
crc8 = crc_table[crc8 ^ *p++];
|
||||
|
||||
return crc8;
|
||||
}
|
||||
|
96
flight/PiOS.osx/osx/pios_debug.c
Normal file
96
flight/PiOS.osx/osx/pios_debug.c
Normal file
@ -0,0 +1,96 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @defgroup PIOS_DEBUG Debugging Functions
|
||||
* @brief Debugging functionality
|
||||
* @{
|
||||
*
|
||||
* @file pios_debug.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Debugging Functions
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
// Global variables
|
||||
const char *PIOS_DEBUG_AssertMsg = "ASSERT FAILED";
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/**
|
||||
* Initialise Debug-features
|
||||
*/
|
||||
void PIOS_DEBUG_Init(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug-pin high
|
||||
* \param pin 0 for S1 output
|
||||
*/
|
||||
void PIOS_DEBUG_PinHigh(uint8_t Pin)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set debug-pin low
|
||||
* \param pin 0 for S1 output
|
||||
*/
|
||||
void PIOS_DEBUG_PinLow(uint8_t Pin)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void PIOS_DEBUG_PinValue8Bit(uint8_t value)
|
||||
{
|
||||
}
|
||||
|
||||
void PIOS_DEBUG_PinValue4BitL(uint8_t value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Report a serious error and halt
|
||||
*/
|
||||
void PIOS_DEBUG_Panic(const char *msg)
|
||||
{
|
||||
#ifdef PIOS_COM_DEBUG
|
||||
register int *lr asm("lr"); // Link-register holds the PC of the caller
|
||||
PIOS_COM_SendFormattedStringNonBlocking(PIOS_COM_DEBUG, "\r%s @0x%x\r", msg, lr);
|
||||
#endif
|
||||
|
||||
// tell the user whats going on on commandline too
|
||||
fprintf(stderr,"CRITICAL ERROR: %s\n",msg);
|
||||
|
||||
// this helps debugging: causing a div by zero allows a backtrace
|
||||
// and/or ends execution
|
||||
int b = 0;
|
||||
int a = (2/b);
|
||||
b=a;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
114
flight/PiOS.osx/osx/pios_delay.c
Normal file
114
flight/PiOS.osx/osx/pios_delay.c
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_delay.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
||||
* @brief Delay Functions
|
||||
* - Provides a micro-second granular delay using a TIM
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_DELAY Delay Functions
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
#include "time.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_DELAY)
|
||||
|
||||
/**
|
||||
* Initialises the Timer used by PIOS_DELAY functions<BR>
|
||||
* This is called from pios.c as part of the main() function
|
||||
* at system start up.
|
||||
* \return < 0 if initialisation failed
|
||||
*/
|
||||
#include <time.h>
|
||||
|
||||
int32_t PIOS_DELAY_Init(void)
|
||||
{
|
||||
// stub
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a specific number of uS<BR>
|
||||
* Example:<BR>
|
||||
* \code
|
||||
* // Wait for 500 uS
|
||||
* PIOS_DELAY_Wait_uS(500);
|
||||
* \endcode
|
||||
* \param[in] uS delay (1..65535 microseconds)
|
||||
* \return < 0 on errors
|
||||
*/
|
||||
int32_t PIOS_DELAY_WaituS(uint32_t uS)
|
||||
{
|
||||
struct timespec wait,rest;
|
||||
wait.tv_sec=0;
|
||||
wait.tv_nsec=1000*uS;
|
||||
while (!nanosleep(&wait,&rest)) {
|
||||
wait=rest;
|
||||
}
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Waits for a specific number of mS<BR>
|
||||
* Example:<BR>
|
||||
* \code
|
||||
* // Wait for 500 mS
|
||||
* PIOS_DELAY_Wait_mS(500);
|
||||
* \endcode
|
||||
* \param[in] mS delay (1..65535 milliseconds)
|
||||
* \return < 0 on errors
|
||||
*/
|
||||
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
|
||||
{
|
||||
struct timespec wait,rest;
|
||||
wait.tv_sec=mS/1000;
|
||||
wait.tv_nsec=(mS%1000)*1000000;
|
||||
while (!nanosleep(&wait,&rest)) {
|
||||
wait=rest;
|
||||
}
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t PIOS_DELAY_GetRaw()
|
||||
{
|
||||
// struct timespec time;
|
||||
// uint32_t raw_us;
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t PIOS_DELAY_DiffuS(uint32_t rapec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
69
flight/PiOS.osx/osx/pios_irq.c
Normal file
69
flight/PiOS.osx/osx/pios_irq.c
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_IRQ IRQ Setup Functions
|
||||
* @brief STM32 Hardware code to enable and disable interrupts
|
||||
* @{
|
||||
*
|
||||
* @file pios_irq.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
||||
* @brief IRQ Enable/Disable routines
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_IRQ)
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/**
|
||||
* Disables all interrupts (nested)
|
||||
* \return < 0 On errors
|
||||
*/
|
||||
int32_t PIOS_IRQ_Disable(void)
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
taskENTER_CRITICAL();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables all interrupts (nested)
|
||||
* \return < 0 on errors
|
||||
* \return -1 on nesting errors (PIOS_IRQ_Disable() hasn't been called before)
|
||||
*/
|
||||
int32_t PIOS_IRQ_Enable(void)
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
taskEXIT_CRITICAL();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
86
flight/PiOS.osx/osx/pios_led.c
Normal file
86
flight/PiOS.osx/osx/pios_led.c
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_led.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief LED functions, init, toggle, on & off.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_LED LED Functions
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_LED)
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
|
||||
/* Local Variables */
|
||||
static uint8_t LED_GPIO[PIOS_LED_NUM];
|
||||
|
||||
|
||||
static inline void PIOS_SetLED(uint32_t LED,uint8_t stat) {
|
||||
printf("PIOS: LED %i status %i\n",LED,stat);
|
||||
LED_GPIO[LED]=stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises all the LED's
|
||||
*/
|
||||
void PIOS_LED_Init(void)
|
||||
{
|
||||
for(int LEDNum = 0; LEDNum < PIOS_LED_NUM; LEDNum++) {
|
||||
LED_GPIO[LEDNum]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turn on LED
|
||||
* \param[in] LED LED Name (LED1, LED2)
|
||||
*/
|
||||
void PIOS_LED_On(uint32_t led)
|
||||
{
|
||||
PIOS_SetLED(led,1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turn off LED
|
||||
* \param[in] LED LED Name (LED1, LED2)
|
||||
*/
|
||||
void PIOS_LED_Off(uint32_t led)
|
||||
{
|
||||
PIOS_SetLED(led,0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Toggle LED on/off
|
||||
* \param[in] LED LED Name (LED1, LED2)
|
||||
*/
|
||||
void PIOS_LED_Toggle(uint32_t led)
|
||||
{
|
||||
PIOS_SetLED(led,LED_GPIO[led]?0:1);
|
||||
}
|
||||
|
||||
#endif
|
100
flight/PiOS.osx/osx/pios_rcvr.c
Normal file
100
flight/PiOS.osx/osx/pios_rcvr.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_RCVR)
|
||||
|
||||
#include <pios_rcvr_priv.h>
|
||||
|
||||
enum pios_rcvr_dev_magic {
|
||||
PIOS_RCVR_DEV_MAGIC = 0x99aabbcc,
|
||||
};
|
||||
|
||||
struct pios_rcvr_dev {
|
||||
enum pios_rcvr_dev_magic magic;
|
||||
uint32_t lower_id;
|
||||
const struct pios_rcvr_driver * driver;
|
||||
};
|
||||
|
||||
static bool PIOS_RCVR_validate(struct pios_rcvr_dev * rcvr_dev)
|
||||
{
|
||||
return (rcvr_dev->magic == PIOS_RCVR_DEV_MAGIC);
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
||||
static struct pios_rcvr_dev * PIOS_RCVR_alloc(void)
|
||||
{
|
||||
struct pios_rcvr_dev * rcvr_dev;
|
||||
|
||||
rcvr_dev = (struct pios_rcvr_dev *)malloc(sizeof(*rcvr_dev));
|
||||
if (!rcvr_dev) return (NULL);
|
||||
|
||||
rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC;
|
||||
return(rcvr_dev);
|
||||
}
|
||||
#else
|
||||
static struct pios_rcvr_dev pios_rcvr_devs[PIOS_RCVR_MAX_DEVS];
|
||||
static uint8_t pios_rcvr_num_devs;
|
||||
static struct pios_rcvr_dev * PIOS_RCVR_alloc(void)
|
||||
{
|
||||
struct pios_rcvr_dev * rcvr_dev;
|
||||
|
||||
if (pios_rcvr_num_devs >= PIOS_RCVR_MAX_DEVS) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
rcvr_dev = &pios_rcvr_devs[pios_rcvr_num_devs++];
|
||||
rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC;
|
||||
|
||||
return (rcvr_dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialises RCVR layer
|
||||
* \param[out] handle
|
||||
* \param[in] driver
|
||||
* \param[in] id
|
||||
* \return < 0 if initialisation failed
|
||||
*/
|
||||
int32_t PIOS_RCVR_Init(uint32_t * rcvr_id, const struct pios_rcvr_driver * driver, const uint32_t lower_id)
|
||||
{
|
||||
PIOS_DEBUG_Assert(rcvr_id);
|
||||
PIOS_DEBUG_Assert(driver);
|
||||
|
||||
struct pios_rcvr_dev * rcvr_dev;
|
||||
|
||||
rcvr_dev = (struct pios_rcvr_dev *) PIOS_RCVR_alloc();
|
||||
if (!rcvr_dev) goto out_fail;
|
||||
|
||||
rcvr_dev->driver = driver;
|
||||
rcvr_dev->lower_id = lower_id;
|
||||
|
||||
|
||||
*rcvr_id = pios_rcvr_num_devs - 1;
|
||||
|
||||
return(0);
|
||||
|
||||
out_fail:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel)
|
||||
{
|
||||
struct pios_rcvr_dev * rcvr_dev = &pios_rcvr_devs[rcvr_id];
|
||||
|
||||
if (!PIOS_RCVR_validate(rcvr_dev)) {
|
||||
/* Undefined RCVR port for this board (see pios_board.c) */
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
PIOS_DEBUG_Assert(rcvr_dev->driver->read);
|
||||
|
||||
return rcvr_dev->driver->read(rcvr_dev->lower_id, channel);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
300
flight/PiOS.osx/osx/pios_sdcard.c
Normal file
300
flight/PiOS.osx/osx/pios_sdcard.c
Normal file
@ -0,0 +1,300 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_sdcard.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief Sets up basic system hardware, functions are called from Main.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_SDCARD SDCard Functions
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_SDCARD)
|
||||
|
||||
|
||||
/**
|
||||
* Initialises SPI pins and peripheral to access MMC/SD Card
|
||||
* \param[in] mode currently only mode 0 supported
|
||||
* \return < 0 if initialisation failed
|
||||
*/
|
||||
int32_t PIOS_SDCARD_Init(void)
|
||||
{
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connects to SD Card
|
||||
* \return < 0 if initialisation sequence failed
|
||||
*/
|
||||
int32_t PIOS_SDCARD_PowerOn(void)
|
||||
{
|
||||
return 0; /* Status should be 0 if nothing went wrong! */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disconnects from SD Card
|
||||
* \return < 0 on errors
|
||||
*/
|
||||
int32_t PIOS_SDCARD_PowerOff(void)
|
||||
{
|
||||
return 0; // no error
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If SD card was previously available: Checks if the SD Card is still
|
||||
* available by sending the STATUS command.<BR>
|
||||
* This takes ca. 10 uS
|
||||
*
|
||||
* If SD card was previously not available: Checks if the SD Card is
|
||||
* available by sending the IDLE command at low speed.<BR>
|
||||
* This takes ca. 500 uS!<BR>
|
||||
* Once we got a positive response, SDCARD_PowerOn() will be
|
||||
* called by this function to initialize the card completely.
|
||||
*
|
||||
* Example for Connection/Disconnection detection:
|
||||
* \code
|
||||
* // this function is called each second from a low-priority task
|
||||
* // If multiple tasks are accessing the SD card, add a semaphore/mutex
|
||||
* // to avoid IO access collisions with other tasks!
|
||||
* u8 sdcard_available;
|
||||
* int32_t CheckSDCard(void)
|
||||
* {
|
||||
* // check if SD card is available
|
||||
* // High speed access if the card was previously available
|
||||
* u8 prev_sdcard_available = sdcard_available;
|
||||
* sdcard_available = PIOS_SDCARD_CheckAvailable(prev_sdcard_available);
|
||||
*
|
||||
* if(sdcard_available && !prev_sdcard_available) {
|
||||
* // SD Card has been connected
|
||||
*
|
||||
* // now it's possible to read/write sectors
|
||||
*
|
||||
* } else if( !sdcard_available && prev_sdcard_available ) {
|
||||
* // SD Card has been disconnected
|
||||
*
|
||||
* // here you can notify your application about this state
|
||||
* }
|
||||
*
|
||||
* return 0; // no error
|
||||
* }
|
||||
* \endcode
|
||||
* \param[in] was_available should only be set if the SD card was previously available
|
||||
* \return 0 if no response from SD Card
|
||||
* \return 1 if SD card is accessible
|
||||
*/
|
||||
int32_t PIOS_SDCARD_CheckAvailable(uint8_t was_available)
|
||||
{
|
||||
return 1; /* 1 = available, 0 = not available. */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends command to SD card
|
||||
* \param[in] cmd SD card command
|
||||
* \param[in] addr 32bit address
|
||||
* \param[in] crc precalculated CRC
|
||||
* \return >= 0x00 if command has been sent successfully (contains received byte)
|
||||
* \return -1 if no response from SD Card (timeout)
|
||||
*/
|
||||
int32_t PIOS_SDCARD_SendSDCCmd(uint8_t cmd, uint32_t addr, uint8_t crc)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads 512 bytes from selected sector
|
||||
* \param[in] sector 32bit sector
|
||||
* \param[in] *buffer pointer to 512 byte buffer
|
||||
* \return 0 if whole sector has been successfully read
|
||||
* \return -error if error occured during read operation:<BR>
|
||||
* <UL>
|
||||
* <LI>Bit 0 - In idle state if 1
|
||||
* <LI>Bit 1 - Erase Reset if 1
|
||||
* <LI>Bit 2 - Illgal Command if 1
|
||||
* <LI>Bit 3 - Com CRC Error if 1
|
||||
* <LI>Bit 4 - Erase Sequence Error if 1
|
||||
* <LI>Bit 5 - Address Error if 1
|
||||
* <LI>Bit 6 - Parameter Error if 1
|
||||
* <LI>Bit 7 - Not used, always '0'
|
||||
* </UL>
|
||||
* \return -256 if timeout during command has been sent
|
||||
* \return -257 if timeout while waiting for start token
|
||||
*/
|
||||
int32_t PIOS_SDCARD_SectorRead(uint32_t sector, uint8_t *buffer)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes 512 bytes into selected sector
|
||||
* \param[in] sector 32bit sector
|
||||
* \param[in] *buffer pointer to 512 byte buffer
|
||||
* \return 0 if whole sector has been successfully read
|
||||
* \return -error if error occured during read operation:<BR>
|
||||
* <UL>
|
||||
* <LI>Bit 0 - In idle state if 1
|
||||
* <LI>Bit 1 - Erase Reset if 1
|
||||
* <LI>Bit 2 - Illgal Command if 1
|
||||
* <LI>Bit 3 - Com CRC Error if 1
|
||||
* <LI>Bit 4 - Erase Sequence Error if 1
|
||||
* <LI>Bit 5 - Address Error if 1
|
||||
* <LI>Bit 6 - Parameter Error if 1
|
||||
* <LI>Bit 7 - Not used, always '0'
|
||||
* </UL>
|
||||
* \return -256 if timeout during command has been sent
|
||||
* \return -257 if write operation not accepted
|
||||
* \return -258 if timeout during write operation
|
||||
*/
|
||||
int32_t PIOS_SDCARD_SectorWrite(uint32_t sector, uint8_t *buffer)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads the CID informations from SD Card
|
||||
* \param[in] *cid pointer to buffer which holds the CID informations
|
||||
* \return 0 if the informations haven been successfully read
|
||||
* \return -error if error occured during read operation
|
||||
* \return -256 if timeout during command has been sent
|
||||
* \return -257 if timeout while waiting for start token
|
||||
*/
|
||||
int32_t PIOS_SDCARD_CIDRead(SDCARDCidTypeDef *cid)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the CSD informations from SD Card
|
||||
* \param[in] *csd pointer to buffer which holds the CSD informations
|
||||
* \return 0 if the informations haven been successfully read
|
||||
* \return -error if error occured during read operation
|
||||
* \return -256 if timeout during command has been sent
|
||||
* \return -257 if timeout while waiting for start token
|
||||
*/
|
||||
int32_t PIOS_SDCARD_CSDRead(SDCARDCsdTypeDef *csd)
|
||||
{
|
||||
return -256;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to write a startup log to the SDCard
|
||||
* return 0 No errors
|
||||
* return -1 Error deleting file
|
||||
* return -2 Error opening file
|
||||
* return -3 Error writing file
|
||||
*/
|
||||
int32_t PIOS_SDCARD_StartupLog(void)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the SD card has been mounted
|
||||
* @return 0 if no
|
||||
* @return 1 if yes
|
||||
*/
|
||||
int32_t PIOS_SDCARD_IsMounted()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounts the file system
|
||||
* param[in] CreateStartupLog 1 = True, 0 = False
|
||||
* return 0 No errors
|
||||
* return -1 SDCard not available
|
||||
* return -2 Cannot find first partition
|
||||
* return -3 No volume information
|
||||
* return -4 Error writing startup log file
|
||||
*/
|
||||
int32_t PIOS_SDCARD_MountFS(uint32_t CreateStartupLog)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounts the file system
|
||||
* return Amount of free bytes
|
||||
*/
|
||||
int32_t PIOS_SDCARD_GetFree(void)
|
||||
{
|
||||
return 10240;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from file
|
||||
* return 0 No error
|
||||
* return -1 DFS_ReadFile failed
|
||||
* return -2 Less bytes read than expected
|
||||
*/
|
||||
//int32_t PIOS_SDCARD_ReadBuffer(PFILEINFO fileinfo, uint8_t *buffer, uint32_t len)
|
||||
//{
|
||||
/* No error */
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
/**
|
||||
* Read a line from file
|
||||
* returns Number of bytes read
|
||||
*/
|
||||
//int32_t PIOS_SDCARD_ReadLine(PFILEINFO fileinfo, uint8_t *buffer, uint32_t max_len)
|
||||
//{
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
/**
|
||||
* Copy a file
|
||||
* WARNING: This will overwrite the destination file even if it exists
|
||||
* param[in] *Source Path to file to copy
|
||||
* param[in] *Destination Path to destination file
|
||||
* return 0 No errors
|
||||
* return -1 Source file doesn't exist
|
||||
* return -2 Failed to create destination file
|
||||
* return -3 DFS_ReadFile failed
|
||||
* return -4 DFS_WriteFile failed
|
||||
*/
|
||||
int32_t PIOS_SDCARD_FileCopy(char *Source, char *Destination)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file
|
||||
* param[in] *Filename File to delete
|
||||
* return 0 No errors
|
||||
* return -1 Error deleting file
|
||||
*/
|
||||
int32_t PIOS_SDCARD_FileDelete(char *Filename)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
74
flight/PiOS.osx/osx/pios_servo.c
Normal file
74
flight/PiOS.osx/osx/pios_servo.c
Normal file
@ -0,0 +1,74 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_SERVO RC Servo Functions
|
||||
* @brief Code to do set RC servo output
|
||||
* @{
|
||||
*
|
||||
* @file pios_servo.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief RC Servo routines (STM32 dependent)
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_SERVO)
|
||||
|
||||
/* Private Function Prototypes */
|
||||
|
||||
/* Local Variables */
|
||||
static volatile uint16_t ServoPosition[PIOS_SERVO_NUM_TIMERS];
|
||||
|
||||
/**
|
||||
* Initialise Servos
|
||||
*/
|
||||
void PIOS_Servo_Init(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servo update rate (Max 500Hz)
|
||||
* \param[in] onetofour Rate for outputs 1 to 4 (Hz)
|
||||
* \param[in] fivetoeight Rate for outputs 5 to 8 (Hz)
|
||||
*/
|
||||
void PIOS_Servo_SetHz(uint16_t * banks, uint8_t num_banks)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set servo position
|
||||
* \param[in] Servo Servo number (0-7)
|
||||
* \param[in] Position Servo position in milliseconds
|
||||
*/
|
||||
void PIOS_Servo_Set(uint8_t Servo, uint16_t Position)
|
||||
{
|
||||
#ifndef PIOS_ENABLE_DEBUG_PINS
|
||||
/* Make sure servo exists */
|
||||
if (Servo < PIOS_SERVO_NUM_OUTPUTS) {
|
||||
/* Update the position */
|
||||
ServoPosition[Servo] = Position;
|
||||
|
||||
}
|
||||
#endif // PIOS_ENABLE_DEBUG_PINS
|
||||
}
|
||||
|
||||
#endif
|
101
flight/PiOS.osx/osx/pios_sim.c
Normal file
101
flight/PiOS.osx/osx/pios_sim.c
Normal file
@ -0,0 +1,101 @@
|
||||
|
||||
#include "pios.h"
|
||||
#include "pios_sim_priv.h"
|
||||
#include "sim_model.h"
|
||||
|
||||
struct pios_sim_state pios_sim_state = {
|
||||
.accels = {0, 0, 0},
|
||||
.gyros = {0, 0, 0},
|
||||
.mag = {0, 0, 0},
|
||||
.baro = {0},
|
||||
.q = {1, 0, 0, 0},
|
||||
.velocity = {0, 0, 0},
|
||||
.position = {0, 0, 0},
|
||||
.actuator = {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the model in the external library
|
||||
* @returns 0 for success, -1 if fails to initialize external library
|
||||
*/
|
||||
int PIOS_SIM_Init()
|
||||
{
|
||||
if (sim_model_init() != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step the model simulation in the external library
|
||||
* @returns 0 for success, -1 for failure to step external library
|
||||
*/
|
||||
int PIOS_SIM_Step(float dT)
|
||||
{
|
||||
if (sim_model_step(dT, &pios_sim_state) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the actuator inputs to the model
|
||||
* @param[in] actuator pointer to an array of actuators to set
|
||||
* @param[in] nchannels number of channels that are valid coming in
|
||||
*/
|
||||
void PIOS_SIM_SetActuator(float * actuator, int nchannels)
|
||||
{
|
||||
for (int i = 0; i < NELEMENTS(pios_sim_state.actuator) && i < nchannels; i++)
|
||||
pios_sim_state.actuator[i] = actuator[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the accelerometer data from the simulation model
|
||||
* @param[out] pointer to store the accelerometer data in
|
||||
*/
|
||||
void PIOS_SIM_GetAccels(float * accels)
|
||||
{
|
||||
for (int i = 0; i < NELEMENTS(pios_sim_state.accels); i++)
|
||||
accels[i] = pios_sim_state.accels[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the gyro data from the simulation model
|
||||
* @param[out] pointer to store the gyro data in
|
||||
*/
|
||||
void PIOS_SIM_GetGyros(float * gyros)
|
||||
{
|
||||
for (int i = 0; i < NELEMENTS(pios_sim_state.accels); i++)
|
||||
gyros[i] = pios_sim_state.gyros[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current attitude from the simulation model
|
||||
* @param[out] quat pointer to store the quaternion attitude in
|
||||
*/
|
||||
void PIOS_SIM_GetAttitude(float * q)
|
||||
{
|
||||
for (int i = 0; i < NELEMENTS(pios_sim_state.q); i++)
|
||||
q[i] = pios_sim_state.q[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current positiom from the simulation model
|
||||
* @param[out] position pointer to store the current position in (cm in NED
|
||||
* frame)
|
||||
*/
|
||||
void PIOS_SIM_GetVelocity(float * velocity)
|
||||
{
|
||||
for (int i = 0; i < NELEMENTS(pios_sim_state.velocity); i++)
|
||||
velocity[i] = pios_sim_state.velocity[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current positiom from the simulation model
|
||||
* @param[out] position pointer to store the current position in (cm in NED
|
||||
* frame)
|
||||
*/
|
||||
void PIOS_SIM_GetPosition(float * position)
|
||||
{
|
||||
for (int i = 0; i < NELEMENTS(pios_sim_state.position); i++)
|
||||
position[i] = pios_sim_state.position[i];
|
||||
}
|
165
flight/PiOS.osx/osx/pios_sys.c
Normal file
165
flight/PiOS.osx/osx/pios_sys.c
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_sys.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
||||
* @brief Sets up basic system hardware, functions are called from Main.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_SYS System Functions
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_SYS)
|
||||
|
||||
|
||||
/* Private Function Prototypes */
|
||||
void NVIC_Configuration(void);
|
||||
void SysTick_Handler(void);
|
||||
|
||||
/* Local Macros */
|
||||
#define MEM8(addr) (*((volatile uint8_t *)(addr)))
|
||||
|
||||
/**
|
||||
* Initialises all system peripherals
|
||||
*/
|
||||
void PIOS_SYS_Init(void)
|
||||
{
|
||||
|
||||
/**
|
||||
* stub
|
||||
*/
|
||||
printf("PIOS_SYS_Init\n");
|
||||
|
||||
/* Initialise Basic NVIC */
|
||||
NVIC_Configuration();
|
||||
|
||||
#if defined(PIOS_INCLUDE_LED)
|
||||
/* Initialise LEDs */
|
||||
PIOS_LED_Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown PIOS and reset the microcontroller:<BR>
|
||||
* <UL>
|
||||
* <LI>Disable all RTOS tasks
|
||||
* <LI>Disable all interrupts
|
||||
* <LI>Turn off all board LEDs
|
||||
* <LI>Reset STM32
|
||||
* </UL>
|
||||
* \return < 0 if reset failed
|
||||
*/
|
||||
int32_t PIOS_SYS_Reset(void)
|
||||
{
|
||||
/**
|
||||
* stub
|
||||
*/
|
||||
printf("PIOS_SYS_Reset\n");
|
||||
/* Disable all RTOS tasks */
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
/* port specific FreeRTOS function to disable tasks (nested) */
|
||||
portENTER_CRITICAL();
|
||||
#endif
|
||||
|
||||
|
||||
while(1);
|
||||
|
||||
/* We will never reach this point */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the serial number as a string
|
||||
* param[out] str pointer to a string which can store at least 32 digits + zero terminator!
|
||||
* (24 digits returned for STM32)
|
||||
* return < 0 if feature not supported
|
||||
*/
|
||||
int32_t PIOS_SYS_SerialNumberGet(char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Stored in the so called "electronic signature" */
|
||||
for(i=0; i<24; ++i) {
|
||||
//uint8_t b = MEM8(0x1ffff7e8 + (i/2));
|
||||
//if( !(i & 1) )
|
||||
//b >>= 4;
|
||||
//b &= 0x0f;
|
||||
|
||||
//str[i] = ((b > 9) ? ('A'-10) : '0') + b;
|
||||
str[i]='6';
|
||||
}
|
||||
str[i] = 0;
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Vector Table base location and SysTick
|
||||
*/
|
||||
void NVIC_Configuration(void)
|
||||
{
|
||||
/**
|
||||
* stub
|
||||
*/
|
||||
printf("NVIC_Configuration\n");
|
||||
/* Set the Vector Table base address as specified in .ld file */
|
||||
//NVIC_SetVectorTable(PIOS_NVIC_VECTTAB_FLASH, 0x0);
|
||||
|
||||
/* 4 bits for Interrupt priorities so no sub priorities */
|
||||
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
|
||||
|
||||
/* Configure HCLK clock as SysTick clock source. */
|
||||
//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
|
||||
}
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
/**
|
||||
* Reports the name of the source file and the source line number
|
||||
* where the assert_param error has occurred.
|
||||
* \param[in] file pointer to the source file name
|
||||
* \param[in] line assert_param error line source number
|
||||
* \retval None
|
||||
*/
|
||||
void assert_failed(uint8_t* file, uint32_t line)
|
||||
{
|
||||
/* When serial debugging is implemented, use something like this. */
|
||||
/* printf("Wrong parameters value: file %s on line %d\r\n", file, line); */
|
||||
printf("Wrong parameters value: file %s on line %d\r\n", file, line);
|
||||
|
||||
/* Setup the LEDs to Alternate */
|
||||
PIOS_LED_On(LED1);
|
||||
PIOS_LED_Off(LED2);
|
||||
|
||||
/* Infinite loop */
|
||||
while (1)
|
||||
{
|
||||
PIOS_LED_Toggle(LED1);
|
||||
PIOS_LED_Toggle(LED2);
|
||||
for(int i = 0; i < 1000000; i++);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
244
flight/PiOS.osx/osx/pios_udp.c
Normal file
244
flight/PiOS.osx/osx/pios_udp.c
Normal file
@ -0,0 +1,244 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_udp.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
||||
* @brief UDP commands. Inits UDPs, controls UDPs & Interupt handlers.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_UDP UDP Functions
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/* Project Includes */
|
||||
#include "pios.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_UDP)
|
||||
|
||||
#include <signal.h>
|
||||
#include <pios_udp_priv.h>
|
||||
|
||||
/* We need a list of UDP devices */
|
||||
|
||||
#define PIOS_UDP_MAX_DEV 256
|
||||
static int8_t pios_udp_num_devices = 0;
|
||||
|
||||
static pios_udp_dev pios_udp_devices[PIOS_UDP_MAX_DEV];
|
||||
|
||||
|
||||
|
||||
/* Provide a COM driver */
|
||||
static void PIOS_UDP_ChangeBaud(uint32_t udp_id, uint32_t baud);
|
||||
static void PIOS_UDP_RegisterRxCallback(uint32_t udp_id, pios_com_callback rx_in_cb, uint32_t context);
|
||||
static void PIOS_UDP_RegisterTxCallback(uint32_t udp_id, pios_com_callback tx_out_cb, uint32_t context);
|
||||
static void PIOS_UDP_TxStart(uint32_t udp_id, uint16_t tx_bytes_avail);
|
||||
static void PIOS_UDP_RxStart(uint32_t udp_id, uint16_t rx_bytes_avail);
|
||||
|
||||
const struct pios_com_driver pios_udp_com_driver = {
|
||||
.set_baud = PIOS_UDP_ChangeBaud,
|
||||
.tx_start = PIOS_UDP_TxStart,
|
||||
.rx_start = PIOS_UDP_RxStart,
|
||||
.bind_tx_cb = PIOS_UDP_RegisterTxCallback,
|
||||
.bind_rx_cb = PIOS_UDP_RegisterRxCallback,
|
||||
};
|
||||
|
||||
|
||||
static pios_udp_dev * find_udp_dev_by_id (uint8_t udp)
|
||||
{
|
||||
if (udp >= pios_udp_num_devices) {
|
||||
/* Undefined UDP port for this board (see pios_board.c) */
|
||||
PIOS_Assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get a handle for the device configuration */
|
||||
return &(pios_udp_devices[udp]);
|
||||
}
|
||||
|
||||
/**
|
||||
* RxThread
|
||||
*/
|
||||
void * PIOS_UDP_RxThread(void * udp_dev_n)
|
||||
{
|
||||
|
||||
/* needed because of FreeRTOS.posix scheduling */
|
||||
sigset_t set;
|
||||
sigfillset(&set);
|
||||
sigprocmask(SIG_BLOCK, &set, NULL);
|
||||
|
||||
pios_udp_dev * udp_dev = (pios_udp_dev*) udp_dev_n;
|
||||
|
||||
/**
|
||||
* com devices never get closed except by application "reboot"
|
||||
* we also never give up our mutex except for waiting
|
||||
*/
|
||||
while(1) {
|
||||
|
||||
/**
|
||||
* receive
|
||||
*/
|
||||
int received;
|
||||
udp_dev->clientLength=sizeof(udp_dev->client);
|
||||
if ((received = recvfrom(udp_dev->socket,
|
||||
&udp_dev->rx_buffer,
|
||||
PIOS_UDP_RX_BUFFER_SIZE,
|
||||
0,
|
||||
(struct sockaddr *) &udp_dev->client,
|
||||
(socklen_t*)&udp_dev->clientLength)) >= 0)
|
||||
{
|
||||
|
||||
/* copy received data to buffer if possible */
|
||||
/* we do NOT buffer data locally. If the com buffer can't receive, data is discarded! */
|
||||
/* (thats what the USART driver does too!) */
|
||||
bool rx_need_yield = false;
|
||||
if (udp_dev->rx_in_cb) {
|
||||
(void) (udp_dev->rx_in_cb)(udp_dev->rx_in_context, udp_dev->rx_buffer, received, NULL, &rx_need_yield);
|
||||
}
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
if (rx_need_yield) {
|
||||
vPortYieldFromISR();
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_FREERTOS */
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open UDP socket
|
||||
*/
|
||||
int32_t PIOS_UDP_Init(uint32_t * udp_id, const struct pios_udp_cfg * cfg)
|
||||
{
|
||||
|
||||
pios_udp_dev * udp_dev = &pios_udp_devices[pios_udp_num_devices];
|
||||
|
||||
pios_udp_num_devices++;
|
||||
|
||||
|
||||
/* initialize */
|
||||
udp_dev->rx_in_cb = NULL;
|
||||
udp_dev->tx_out_cb = NULL;
|
||||
udp_dev->cfg=cfg;
|
||||
|
||||
/* assign socket */
|
||||
udp_dev->socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
memset(&udp_dev->server,0,sizeof(udp_dev->server));
|
||||
memset(&udp_dev->client,0,sizeof(udp_dev->client));
|
||||
udp_dev->server.sin_family = AF_INET;
|
||||
udp_dev->server.sin_addr.s_addr = inet_addr(udp_dev->cfg->ip);
|
||||
udp_dev->server.sin_port = htons(udp_dev->cfg->port);
|
||||
int res= bind(udp_dev->socket, (struct sockaddr *)&udp_dev->server,sizeof(udp_dev->server));
|
||||
|
||||
/* Create transmit thread for this connection */
|
||||
pthread_create(&udp_dev->rxThread, NULL, PIOS_UDP_RxThread, (void*)udp_dev);
|
||||
|
||||
printf("udp dev %i - socket %i opened - result %i\n",pios_udp_num_devices-1,udp_dev->socket,res);
|
||||
|
||||
*udp_id = pios_udp_num_devices-1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void PIOS_UDP_ChangeBaud(uint32_t udp_id, uint32_t baud)
|
||||
{
|
||||
/**
|
||||
* doesn't apply!
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void PIOS_UDP_RxStart(uint32_t udp_id, uint16_t rx_bytes_avail)
|
||||
{
|
||||
/**
|
||||
* lazy!
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
static void PIOS_UDP_TxStart(uint32_t udp_id, uint16_t tx_bytes_avail)
|
||||
{
|
||||
pios_udp_dev * udp_dev = find_udp_dev_by_id(udp_id);
|
||||
|
||||
PIOS_Assert(udp_dev);
|
||||
|
||||
int32_t length,len,rem;
|
||||
|
||||
/**
|
||||
* we send everything directly whenever notified of data to send (lazy!)
|
||||
*/
|
||||
if (udp_dev->tx_out_cb) {
|
||||
while (tx_bytes_avail>0) {
|
||||
bool tx_need_yield = false;
|
||||
length = (udp_dev->tx_out_cb)(udp_dev->tx_out_context, udp_dev->tx_buffer, PIOS_UDP_RX_BUFFER_SIZE, NULL, &tx_need_yield);
|
||||
rem = length;
|
||||
while (rem>0) {
|
||||
len = sendto(udp_dev->socket, udp_dev->tx_buffer, length, 0,
|
||||
(struct sockaddr *) &udp_dev->client,
|
||||
sizeof(udp_dev->client));
|
||||
if (len<=0) {
|
||||
rem=0;
|
||||
} else {
|
||||
rem -= len;
|
||||
}
|
||||
}
|
||||
tx_bytes_avail -= length;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void PIOS_UDP_RegisterRxCallback(uint32_t udp_id, pios_com_callback rx_in_cb, uint32_t context)
|
||||
{
|
||||
pios_udp_dev * udp_dev = find_udp_dev_by_id(udp_id);
|
||||
|
||||
PIOS_Assert(udp_dev);
|
||||
|
||||
/*
|
||||
* Order is important in these assignments since ISR uses _cb
|
||||
* field to determine if it's ok to dereference _cb and _context
|
||||
*/
|
||||
udp_dev->rx_in_context = context;
|
||||
udp_dev->rx_in_cb = rx_in_cb;
|
||||
}
|
||||
|
||||
static void PIOS_UDP_RegisterTxCallback(uint32_t udp_id, pios_com_callback tx_out_cb, uint32_t context)
|
||||
{
|
||||
pios_udp_dev * udp_dev = find_udp_dev_by_id(udp_id);
|
||||
|
||||
PIOS_Assert(udp_dev);
|
||||
|
||||
/*
|
||||
* Order is important in these assignments since ISR uses _cb
|
||||
* field to determine if it's ok to dereference _cb and _context
|
||||
*/
|
||||
udp_dev->tx_out_context = context;
|
||||
udp_dev->tx_out_cb = tx_out_cb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
123
flight/PiOS.osx/osx/pios_wdg.c
Normal file
123
flight/PiOS.osx/osx/pios_wdg.c
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @addtogroup PIOS PIOS Core hardware abstraction layer
|
||||
* @{
|
||||
* @addtogroup PIOS_WDG Watchdog Functions
|
||||
* @brief PIOS Comamnds to initialize and clear watchdog timer
|
||||
* @{
|
||||
*
|
||||
* @file pios_spi.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
||||
* @brief Hardware Abstraction Layer for SPI ports of STM32
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @notes
|
||||
*
|
||||
* The PIOS Watchdog provides a HAL to initialize a watchdog
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "pios.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the watchdog timer for a specified timeout
|
||||
*
|
||||
* It is important to note that this function returns the achieved timeout
|
||||
* for this hardware. For hardware indendence this should be checked when
|
||||
* scheduling updates. Other hardware dependent details may need to be
|
||||
* considered such as a window time which sets a minimum update time,
|
||||
* and this function should return a recommended delay for clearing.
|
||||
*
|
||||
* For the STM32 nominal clock rate is 32 khz, but for the maximum clock rate of
|
||||
* 60 khz and a prescalar of 4 yields a clock rate of 15 khz. The delay that is
|
||||
* set in the watchdog assumes the nominal clock rate, but the delay for FreeRTOS
|
||||
* to use is 75% of the minimal delay.
|
||||
*
|
||||
* @param[in] delayMs The delay period in ms
|
||||
* @returns Maximum recommended delay between updates
|
||||
*/
|
||||
void PIOS_WDG_Init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a module against the watchdog
|
||||
*
|
||||
* There are two ways to use PIOS WDG: this is for when
|
||||
* multiple modules must be monitored. In this case they
|
||||
* must first register against the watchdog system and
|
||||
* only when all of the modules have been updated with the
|
||||
* watchdog be cleared. Each module must have its own
|
||||
* bit in the 16 bit
|
||||
*
|
||||
* @param[in] flag the bit this module wants to use
|
||||
* @returns True if that bit is unregistered
|
||||
*/
|
||||
bool PIOS_WDG_RegisterFlag(uint16_t flag_requested)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function called by modules to indicate they are still running
|
||||
*
|
||||
* This function will set this flag in the active flags register (which is
|
||||
* a backup regsiter) and if all the registered flags are set will clear
|
||||
* the watchdog and set only this flag in the backup register
|
||||
*
|
||||
* @param[in] flag the flag to set
|
||||
* @return true if the watchdog cleared, false if flags are pending
|
||||
*/
|
||||
bool PIOS_WDG_UpdateFlag(uint16_t flag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the flags that were set at bootup
|
||||
*
|
||||
* This is used for diagnostics, if only one flag not set this
|
||||
* was likely the module that wasn't running before reset
|
||||
*
|
||||
* @return The active flags register from bootup
|
||||
*/
|
||||
uint16_t PIOS_WDG_GetBootupFlags()
|
||||
{
|
||||
return (uint16_t) 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the currently active flags
|
||||
*
|
||||
* For external monitoring
|
||||
*
|
||||
* @return The active flags register
|
||||
*/
|
||||
uint16_t PIOS_WDG_GetActiveFlags()
|
||||
{
|
||||
return (uint16_t) 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the watchdog timer
|
||||
*
|
||||
* This function must be called at the appropriate delay to prevent a reset event occuring
|
||||
*/
|
||||
void PIOS_WDG_Clear(void)
|
||||
{
|
||||
}
|
76
flight/PiOS.osx/pios.h
Normal file
76
flight/PiOS.osx/pios.h
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Main PiOS header.
|
||||
* - Central header for the project.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PIOS_H
|
||||
#define PIOS_H
|
||||
|
||||
/* PIOS Feature Selection */
|
||||
#include "pios_config_posix.h"
|
||||
#include <pios_posix.h>
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
/* FreeRTOS Includes */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#define vPortInitialiseBlocks();
|
||||
#endif
|
||||
|
||||
/* C Lib Includes */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Generic initcall infrastructure */
|
||||
#include "pios_initcall.h"
|
||||
|
||||
/* PIOS Board Specific Device Configuration */
|
||||
#include "pios_board_posix.h"
|
||||
|
||||
/* PIOS Hardware Includes (posix) */
|
||||
#include <pios_sys.h>
|
||||
#include <pios_delay.h>
|
||||
#include <pios_led.h>
|
||||
#include <pios_sdcard.h>
|
||||
#include <pios_udp.h>
|
||||
#include <pios_com.h>
|
||||
#include <pios_servo.h>
|
||||
#include <pios_wdg.h>
|
||||
#include <pios_debug.h>
|
||||
#include <pios_crc.h>
|
||||
#include <pios_rcvr.h>
|
||||
#include <pios_irq.h>
|
||||
#include <pios_sim.h>
|
||||
|
||||
#define NELEMENTS(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
#endif /* PIOS_H */
|
646
flight/Revolution/Makefile.osx
Normal file
646
flight/Revolution/Makefile.osx
Normal file
@ -0,0 +1,646 @@
|
||||
#####
|
||||
# Project: Revolution
|
||||
#
|
||||
#
|
||||
# Makefile for OpenPilot project build PiOS and the AP.
|
||||
#
|
||||
# The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2012.
|
||||
#
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#####
|
||||
|
||||
|
||||
# Set developer code and compile options
|
||||
# Set to YES to compile for debugging
|
||||
DEBUG ?= YES
|
||||
|
||||
# Set to YES to use the Servo output pins for debugging via scope or logic analyser
|
||||
ENABLE_DEBUG_PINS ?= NO
|
||||
|
||||
# Set to Yes to enable the AUX UART which is mapped on the S1 (Tx) and S2 (Rx) servo outputs
|
||||
ENABLE_AUX_UART ?= NO
|
||||
|
||||
#
|
||||
USE_BOOTLOADER ?= NO
|
||||
|
||||
|
||||
# Set to YES when using Code Sourcery toolchain
|
||||
CODE_SOURCERY ?= NO
|
||||
|
||||
# Toolchain prefix (i.e arm-elf- -> arm-elf-gcc.exe)
|
||||
TCHAIN_PREFIX ?= ""
|
||||
|
||||
# Remove command is different for Code Sourcery on Windows
|
||||
REMOVE_CMD ?= rm
|
||||
|
||||
FLASH_TOOL = OPENOCD
|
||||
|
||||
# YES enables -mthumb option to flags for source-files listed
|
||||
# in SRC and CPPSRC
|
||||
USE_THUMB_MODE = YES
|
||||
|
||||
# List of modules to include
|
||||
MODULES = Telemetry Actuator Stabilization ManualControl FlightPlan SimulatedAttitude
|
||||
|
||||
# MCU name, submodel and board
|
||||
# - MCU used for compiler-option (-mtune)
|
||||
# - MODEL used for linker-script name (-T) and passed as define
|
||||
# - BOARD just passed as define (optional)
|
||||
MCU = i686
|
||||
#CHIP = STM32F103RET
|
||||
#BOARD = STM3210E_OP
|
||||
MODEL = HD
|
||||
ifeq ($(USE_BOOTLOADER), YES)
|
||||
BOOT_MODEL = $(MODEL)_BL
|
||||
|
||||
else
|
||||
BOOT_MODEL = $(MODEL)_NB
|
||||
endif
|
||||
|
||||
# Directory for output files (lst, obj, dep, elf, sym, map, hex, bin etc.)
|
||||
OUTDIR = ../../build/sim_osx
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = Revolution
|
||||
|
||||
# Paths
|
||||
OPSYSTEM = ./System
|
||||
OPSYSTEMINC = $(OPSYSTEM)/inc
|
||||
OPUAVTALK = ../UAVTalk
|
||||
OPUAVTALKINC = $(OPUAVTALK)/inc
|
||||
OPUAVOBJ = ../UAVObjects
|
||||
OPUAVOBJINC = $(OPUAVOBJ)/inc
|
||||
OPTESTS = ./Tests
|
||||
OPMODULEDIR = ../Modules
|
||||
FLIGHTLIB = ../Libraries
|
||||
FLIGHTLIBINC = $(FLIGHTLIB)/inc
|
||||
PIOS = ../PiOS.osx
|
||||
PIOSINC = $(PIOS)/inc
|
||||
PIOSPOSIX = $(PIOS)/osx
|
||||
APPLIBDIR = $(PIOSPOSIX)/Libraries
|
||||
RTOSDIR = $(APPLIBDIR)/FreeRTOS
|
||||
RTOSSRCDIR = $(RTOSDIR)/Source
|
||||
RTOSINCDIR = $(RTOSSRCDIR)/include
|
||||
DOXYGENDIR = ../Doc/Doxygen
|
||||
PYMITE = $(FLIGHTLIB)/PyMite
|
||||
PYMITELIB = $(PYMITE)/lib
|
||||
PYMITEPLAT = $(PYMITE)/platform/openpilot_sitl
|
||||
PYMITETOOLS = $(PYMITE)/tools
|
||||
PYMITEVM = $(PYMITE)/vm
|
||||
PYMITEINC = $(PYMITEVM)
|
||||
PYMITEINC += $(PYMITEPLAT)
|
||||
PYMITEINC += $(OUTDIR)
|
||||
FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib
|
||||
FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans
|
||||
|
||||
UAVOBJSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight
|
||||
UAVOBJPYTHONSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/python
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
# use file-extension c for "c-only"-files
|
||||
|
||||
MODNAMES = $(notdir ${MODULES})
|
||||
|
||||
ifndef TESTAPP
|
||||
|
||||
## PyMite files
|
||||
SRC += $(OUTDIR)/pmlib_img.c
|
||||
SRC += $(OUTDIR)/pmlib_nat.c
|
||||
SRC += $(OUTDIR)/pmlibusr_img.c
|
||||
SRC += $(OUTDIR)/pmlibusr_nat.c
|
||||
SRC += $(wildcard ${PYMITEVM}/*.c)
|
||||
SRC += $(wildcard ${PYMITEPLAT}/*.c)
|
||||
|
||||
## MODULES
|
||||
SRC += ${foreach MOD, ${MODULES}, ${wildcard ${OPMODULEDIR}/${MOD}/*.c}}
|
||||
SRC += ${OUTDIR}/InitMods.c
|
||||
## OPENPILOT CORE:
|
||||
SRC += ${OPMODULEDIR}/System/systemmod.c
|
||||
SRC += $(OPSYSTEM)/revolution.c
|
||||
SRC += $(OPSYSTEM)/pios_board_posix.c
|
||||
SRC += $(OPSYSTEM)/alarms.c
|
||||
SRC += $(OPUAVTALK)/uavtalk.c
|
||||
SRC += $(OPUAVOBJ)/uavobjectmanager.c
|
||||
SRC += $(OPUAVOBJ)/eventdispatcher.c
|
||||
SRC += $(UAVOBJSYNTHDIR)/uavobjectsinit.c
|
||||
else
|
||||
## TESTCODE
|
||||
SRC += $(OPTESTS)/test_common.c
|
||||
SRC += $(OPTESTS)/$(TESTAPP).c
|
||||
endif
|
||||
|
||||
|
||||
|
||||
## UAVOBJECTS
|
||||
ifndef TESTAPP
|
||||
#include $(UAVOBJSYNTHDIR)/Makefile.inc
|
||||
include ./UAVObjects.inc
|
||||
SRC += $(UAVOBJSRC)
|
||||
CFLAGS_UAVOBJECTS = $(UAVOBJDEFINE)
|
||||
endif
|
||||
|
||||
## PIOS Hardware (posix)
|
||||
SRC += $(PIOSPOSIX)/pios_crc.c
|
||||
SRC += $(PIOSPOSIX)/pios_sys.c
|
||||
SRC += $(PIOSPOSIX)/pios_led.c
|
||||
SRC += $(PIOSPOSIX)/pios_irq.c
|
||||
SRC += $(PIOSPOSIX)/pios_delay.c
|
||||
SRC += $(PIOSPOSIX)/pios_sdcard.c
|
||||
SRC += $(PIOSPOSIX)/pios_udp.c
|
||||
SRC += $(PIOSPOSIX)/pios_com.c
|
||||
SRC += $(PIOSPOSIX)/pios_servo.c
|
||||
SRC += $(PIOSPOSIX)/pios_wdg.c
|
||||
SRC += $(PIOSPOSIX)/pios_debug.c
|
||||
|
||||
SRC += $(PIOSPOSIX)/pios_rcvr.c
|
||||
SRC += $(PIOSPOSIX)/pios_sim.c
|
||||
|
||||
## Libraries for flight calculations
|
||||
SRC += $(FLIGHTLIB)/fifo_buffer.c
|
||||
SRC += $(FLIGHTLIB)/WorldMagModel.c
|
||||
SRC += $(FLIGHTLIB)/CoordinateConversions.c
|
||||
SRC += $(FLIGHTLIB)/taskmonitor.c
|
||||
|
||||
## RTOS and RTOS Portable
|
||||
SRC += $(RTOSSRCDIR)/list.c
|
||||
SRC += $(RTOSSRCDIR)/queue.c
|
||||
UNAME := $(shell uname)
|
||||
SRC += $(RTOSSRCDIR)/task.c
|
||||
SRC += $(RTOSSRCDIR)/portable/GCC/Posix/port.c
|
||||
SRC += $(RTOSSRCDIR)/portable/MemMang/heap_3.c
|
||||
|
||||
|
||||
|
||||
# List C source files here which must be compiled in ARM-Mode (no -mthumb).
|
||||
# use file-extension c for "c-only"-files
|
||||
## just for testing, timer.c could be compiled in thumb-mode too
|
||||
SRCARM =
|
||||
|
||||
# List C++ source files here.
|
||||
# use file-extension .cpp for C++-files (not .C)
|
||||
CPPSRC =
|
||||
|
||||
# List C++ source files here which must be compiled in ARM-Mode.
|
||||
# use file-extension .cpp for C++-files (not .C)
|
||||
#CPPSRCARM = $(TARGET).cpp
|
||||
CPPSRCARM =
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
EXTRAINCDIRS = $(OPSYSTEM)
|
||||
EXTRAINCDIRS += $(OPSYSTEMINC)
|
||||
EXTRAINCDIRS += $(OPUAVTALK)
|
||||
EXTRAINCDIRS += $(OPUAVTALKINC)
|
||||
EXTRAINCDIRS += $(OPUAVOBJ)
|
||||
EXTRAINCDIRS += $(OPUAVOBJINC)
|
||||
EXTRAINCDIRS += $(UAVOBJSYNTHDIR)
|
||||
EXTRAINCDIRS += $(PIOS)
|
||||
EXTRAINCDIRS += $(PIOSINC)
|
||||
EXTRAINCDIRS += $(FLIGHTLIBINC)
|
||||
EXTRAINCDIRS += $(PIOSPOSIX)
|
||||
EXTRAINCDIRS += $(RTOSINCDIR)
|
||||
EXTRAINCDIRS += $(APPLIBDIR)
|
||||
EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/Posix
|
||||
EXTRAINCDIRS += $(PYMITEINC)
|
||||
|
||||
EXTRAINCDIRS += ${foreach MOD, ${MODULES}, $(OPMODULEDIR)/${MOD}/inc} ${OPMODULEDIR}/System/inc
|
||||
|
||||
|
||||
# List any extra directories to look for library files here.
|
||||
# Also add directories where the linker should search for
|
||||
# includes from linker-script to the list
|
||||
# Each directory must be seperated by a space.
|
||||
EXTRA_LIBDIRS =
|
||||
|
||||
# Extra Libraries
|
||||
# Each library-name must be seperated by a space.
|
||||
# i.e. to link with libxyz.a, libabc.a and libefsl.a:
|
||||
# EXTRA_LIBS = xyz abc efsl
|
||||
# for newlib-lpc (file: libnewlibc-lpc.a):
|
||||
# EXTRA_LIBS = newlib-lpc
|
||||
EXTRA_LIBS =
|
||||
|
||||
# Path to Linker-Scripts
|
||||
LINKERSCRIPTPATH = $(PIOSSTM32F10X)
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
|
||||
ifeq ($(DEBUG),YES)
|
||||
OPT = 0
|
||||
else
|
||||
OPT = s
|
||||
endif
|
||||
|
||||
# Output format. (can be ihex or binary or both)
|
||||
# binary to create a load-image in raw-binary format i.e. for SAM-BA,
|
||||
# ihex to create a load-image in Intel hex format
|
||||
#LOADFORMAT = ihex
|
||||
#LOADFORMAT = binary
|
||||
LOADFORMAT = both
|
||||
|
||||
# Debugging format.
|
||||
#DEBUGF = dwarf-2
|
||||
|
||||
# Place project-specific -D (define) and/or
|
||||
# -U options for C here.
|
||||
ifeq ($(ENABLE_DEBUG_PINS), YES)
|
||||
CDEFS += -DPIOS_ENABLE_DEBUG_PINS
|
||||
endif
|
||||
ifeq ($(ENABLE_AUX_UART), YES)
|
||||
CDEFS += -DPIOS_ENABLE_AUX_UART
|
||||
endif
|
||||
ifeq ($(USE_BOOTLOADER), YES)
|
||||
CDEFS += -DUSE_BOOTLOADER
|
||||
endif
|
||||
|
||||
|
||||
|
||||
# Compiler flag to set the C Standard level.
|
||||
# c89 - "ANSI" C
|
||||
# gnu89 - c89 plus GCC extensions
|
||||
# c99 - ISO C99 standard (not yet fully implemented)
|
||||
# gnu99 - c99 plus GCC extensions
|
||||
CSTANDARD = -std=gnu99
|
||||
|
||||
#-----
|
||||
|
||||
# Compiler flags.
|
||||
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
#
|
||||
# Flags for C and C++ (arm-elf-gcc/arm-elf-g++)
|
||||
|
||||
ifeq ($(DEBUG),YES)
|
||||
CFLAGS = -g$(DEBUGF) -DDEBUG
|
||||
endif
|
||||
|
||||
CFLAGS += $(CFLAGS_UAVOBJECTS)
|
||||
CFLAGS += -DARCH_POSIX
|
||||
CFLAGS += -O$(OPT)
|
||||
CFLAGS += -mtune=$(MCU)
|
||||
CFLAGS += $(CDEFS)
|
||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -I.
|
||||
|
||||
CFLAGS += -fomit-frame-pointer
|
||||
ifeq ($(CODE_SOURCERY), YES)
|
||||
CFLAGS += -fpromote-loop-indices
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Werror
|
||||
# Compiler flags to generate dependency files:
|
||||
CFLAGS += -MD -MP -MF $(OUTDIR)/dep/$(@F).d
|
||||
|
||||
# flags only for C
|
||||
#CONLYFLAGS += -Wnested-externs
|
||||
CONLYFLAGS += $(CSTANDARD)
|
||||
|
||||
# Assembler flags.
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -ahlns: create listing
|
||||
ASFLAGS = -mtune=$(MCU) -I. -x assembler-with-cpp
|
||||
ASFLAGS += $(ADEFS)
|
||||
ASFLAGS += -Wa,-adhlns=$(addprefix $(OUTDIR)/, $(notdir $(addsuffix .lst, $(basename $<))))
|
||||
ASFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
|
||||
MATH_LIB = -lm
|
||||
|
||||
# Linker flags.
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS += -lpthread
|
||||
LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS))
|
||||
LDFLAGS += -lc
|
||||
LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS))
|
||||
LDFLAGS += $(MATH_LIB)
|
||||
LDFLAGS += -lc -lgcc
|
||||
|
||||
# To include simulation model
|
||||
LDFLAGS += -L$(OUTDIR)
|
||||
LDFLAGS += -lsimmodel
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
CC = $(TCHAIN_PREFIX)gcc
|
||||
CPP = $(TCHAIN_PREFIX)g++
|
||||
AR = $(TCHAIN_PREFIX)ar
|
||||
OBJCOPY = $(TCHAIN_PREFIX)objcopy
|
||||
OBJDUMP = $(TCHAIN_PREFIX)objdump
|
||||
SIZE = $(TCHAIN_PREFIX)size
|
||||
NM = $(TCHAIN_PREFIX)nm
|
||||
REMOVE = $(REMOVE_CMD) -f
|
||||
PYTHON = python
|
||||
###SHELL = sh
|
||||
###COPY = cp
|
||||
|
||||
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = ${quote}-------- begin (mode: $(RUN_MODE)) --------${quote}
|
||||
MSG_END = ${quote}-------- end --------${quote}
|
||||
MSG_MODINIT = ${quote}**** Generating ModInit.c${quote}
|
||||
MSG_SIZE_BEFORE = ${quote}Size before:${quote}
|
||||
MSG_SIZE_AFTER = ${quote}Size after build:${quote}
|
||||
MSG_LOAD_FILE = ${quote}Creating load file:${quote}
|
||||
MSG_EXTENDED_LISTING = ${quote}Creating Extended Listing/Disassembly:${quote}
|
||||
MSG_SYMBOL_TABLE = ${quote}Creating Symbol Table:${quote}
|
||||
MSG_LINKING = ${quote}**** Linking :${quote}
|
||||
MSG_COMPILING = ${quote}**** Compiling C :${quote}
|
||||
MSG_COMPILING_ARM = ${quote}**** Compiling C (ARM-only):${quote}
|
||||
MSG_COMPILINGCPP = ${quote}Compiling C++ :${quote}
|
||||
MSG_COMPILINGCPP_ARM = ${quote}Compiling C++ (ARM-only):${quote}
|
||||
MSG_ASSEMBLING = ${quote}**** Assembling:${quote}
|
||||
MSG_ASSEMBLING_ARM = ${quote}****Assembling (ARM-only):${quote}
|
||||
MSG_CLEANING = ${quote}Cleaning project:${quote}
|
||||
MSG_FORMATERROR = ${quote}Can not handle output-format${quote}
|
||||
MSG_ASMFROMC = ${quote}Creating asm-File from C-Source:${quote}
|
||||
MSG_ASMFROMC_ARM = ${quote}Creating asm-File from C-Source (ARM-only):${quote}
|
||||
MSG_PYMITEINIT = ${quote}**** Generating PyMite intermediate code${quote}
|
||||
|
||||
# List of all source files.
|
||||
ALLSRC = $(ASRCARM) $(ASRC) $(SRCARM) $(SRC) $(CPPSRCARM) $(CPPSRC)
|
||||
# List of all source files without directory and file-extension.
|
||||
ALLSRCBASE = $(notdir $(basename $(ALLSRC)))
|
||||
|
||||
# Define all object files.
|
||||
ALLOBJ = $(addprefix $(OUTDIR)/, $(addsuffix .o, $(ALLSRCBASE)))
|
||||
|
||||
# Define all listing files (used for make clean).
|
||||
LSTFILES = $(addprefix $(OUTDIR)/, $(addsuffix .lst, $(ALLSRCBASE)))
|
||||
# Define all depedency-files (used for make clean).
|
||||
DEPFILES = $(addprefix $(OUTDIR)/dep/, $(addsuffix .o.d, $(ALLSRCBASE)))
|
||||
|
||||
elf: $(OUTDIR)/$(TARGET).elf
|
||||
lss: $(OUTDIR)/$(TARGET).lss
|
||||
sym: $(OUTDIR)/$(TARGET).sym
|
||||
hex: $(OUTDIR)/$(TARGET).hex
|
||||
bin: $(OUTDIR)/$(TARGET).bin
|
||||
|
||||
# Default target.
|
||||
#all: begin gccversion sizebefore build sizeafter finished end
|
||||
#all: begin gencode gccversion build sizeafter finished end
|
||||
all: elf
|
||||
|
||||
ifeq ($(LOADFORMAT),ihex)
|
||||
build: elf hex lss sym
|
||||
else
|
||||
ifeq ($(LOADFORMAT),binary)
|
||||
build: elf bin lss sym
|
||||
else
|
||||
ifeq ($(LOADFORMAT),both)
|
||||
build: elf hex bin lss sym
|
||||
else
|
||||
$(error "$(MSG_FORMATERROR) $(FORMAT)")
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Test if quotes are needed for the echo-command
|
||||
result = ${shell echo "test"}
|
||||
ifeq (${result}, test)
|
||||
quote = '
|
||||
else
|
||||
quote =
|
||||
endif
|
||||
|
||||
# Generate intermediate code
|
||||
gencode: ${OUTDIR}/InitMods.c ${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h
|
||||
|
||||
# Generate code for module initialization
|
||||
${OUTDIR}/InitMods.c: Makefile.osx
|
||||
@echo ${MSG_MODINIT}
|
||||
@echo ${quote}// Autogenerated file${quote} > ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}${foreach MOD, ${MODNAMES}, extern unsigned int ${MOD}Initialize(void);}${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}${foreach MOD, ${MODNAMES}, extern unsigned int ${MOD}Start(void);}${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}void InitModules() {${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}${foreach MOD, ${MODNAMES}, ${MOD}Initialize();}${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}}${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}void StartModules() {${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}${foreach MOD, ${MODNAMES}, ${MOD}Start();}${quote} >> ${OUTDIR}/InitMods.c
|
||||
@echo ${quote}}${quote} >> ${OUTDIR}/InitMods.c
|
||||
|
||||
# Generate code for PyMite
|
||||
${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h: $(wildcard ${PYMITELIB}/*.py) $(wildcard ${PYMITEPLAT}/*.py) $(wildcard ${FLIGHTPLANLIB}/*.py) $(wildcard ${FLIGHTPLANS}/*.py) $(wildcard $(UAVOBJPYTHONSYNTHDIR)/*.py)
|
||||
@echo ${MSG_PYMITEINIT}
|
||||
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -s --memspace=flash -o $(OUTDIR)/pmlib_img.c --native-file=$(OUTDIR)/pmlib_nat.c $(PYMITELIB)/list.py $(PYMITELIB)/dict.py $(PYMITELIB)/__bi.py $(PYMITELIB)/sys.py $(PYMITELIB)/string.py $(wildcard $(FLIGHTPLANLIB)/*.py) $(wildcard $(UAVOBJPYTHONSYNTHDIR)/*.py)
|
||||
@$(PYTHON) $(PYMITETOOLS)/pmGenPmFeatures.py $(PYMITEPLAT)/pmfeatures.py > $(OUTDIR)/pmfeatures.h
|
||||
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -u -o $(OUTDIR)/pmlibusr_img.c --native-file=$(OUTDIR)/pmlibusr_nat.c $(FLIGHTPLANS)/test.py
|
||||
|
||||
# Eye candy.
|
||||
begin:
|
||||
## @echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
finished:
|
||||
## @echo $(MSG_ERRORS_NONE)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
## @echo
|
||||
|
||||
# Display sizes of sections.
|
||||
ELFSIZE = $(SIZE) -A $(OUTDIR)/$(TARGET).elf
|
||||
##ELFSIZE = $(SIZE) --format=Berkeley --common $(OUTDIR)/$(TARGET).elf
|
||||
sizebefore:
|
||||
# @if [ -f $(OUTDIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
|
||||
|
||||
sizeafter:
|
||||
# @if [ -f $(OUTDIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
|
||||
@echo $(MSG_SIZE_AFTER)
|
||||
$(ELFSIZE)
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
# @echo $(ALLOBJ)
|
||||
|
||||
# Program the device.
|
||||
ifeq ($(USE_BOOTLOADER), YES)
|
||||
# Program the device with OP Upload Tool".
|
||||
program: $(OUTDIR)/$(TARGET).bin
|
||||
@echo ${quote}Programming with OP Upload Tool${quote}
|
||||
../../ground/src/experimental/upload-build-desktop/debug/OPUploadTool -d 0 -p $(OUTDIR)/$(TARGET).bin
|
||||
else
|
||||
ifeq ($(FLASH_TOOL),OPENOCD)
|
||||
# Program the device with Dominic Rath's OPENOCD in "batch-mode", needs cfg and "reset-script".
|
||||
program: $(OUTDIR)/$(TARGET).elf
|
||||
@echo ${quote}Programming with OPENOCD${quote}
|
||||
$(OOCD_EXE) $(OOCD_CL)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Create final output file (.hex) from ELF output file.
|
||||
%.hex: %.elf
|
||||
## @echo
|
||||
@echo $(MSG_LOAD_FILE) $@
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
# Create final output file (.bin) from ELF output file.
|
||||
%.bin: %.elf
|
||||
## @echo
|
||||
@echo $(MSG_LOAD_FILE) $@
|
||||
$(OBJCOPY) -O binary $< $@
|
||||
|
||||
# Create extended listing file/disassambly from ELF output file.
|
||||
# using objdump testing: option -C
|
||||
%.lss: %.elf
|
||||
## @echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -S -C -r $< > $@
|
||||
# $(OBJDUMP) -x -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
## @echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
$(NM) -n $< > $@
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(ALLOBJ)
|
||||
%.elf: $(ALLOBJ)
|
||||
@echo $(MSG_LINKING) $@
|
||||
# use $(CC) for C-only projects or $(CPP) for C++-projects:
|
||||
$(CC) $(THUMB) $(CFLAGS) $(ALLOBJ) --output $@ $(LDFLAGS)
|
||||
# $(CPP) $(THUMB) $(CFLAGS) $(ALLOBJ) --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
define ASSEMBLE_TEMPLATE
|
||||
$(OUTDIR)/$(notdir $(basename $(1))).o : $(1)
|
||||
## @echo
|
||||
@echo $(MSG_ASSEMBLING) $$< to $$@
|
||||
$(CC) -c $(THUMB) $$(ASFLAGS) $$< -o $$@
|
||||
endef
|
||||
$(foreach src, $(ASRC), $(eval $(call ASSEMBLE_TEMPLATE, $(src))))
|
||||
|
||||
# Assemble: create object files from assembler source files. ARM-only
|
||||
define ASSEMBLE_ARM_TEMPLATE
|
||||
$(OUTDIR)/$(notdir $(basename $(1))).o : $(1)
|
||||
## @echo
|
||||
@echo $(MSG_ASSEMBLING_ARM) $$< to $$@
|
||||
$(CC) -c $$(ASFLAGS) $$< -o $$@
|
||||
endef
|
||||
$(foreach src, $(ASRCARM), $(eval $(call ASSEMBLE_ARM_TEMPLATE, $(src))))
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
define COMPILE_C_TEMPLATE
|
||||
$(OUTDIR)/$(notdir $(basename $(1))).o : $(1)
|
||||
## @echo
|
||||
@echo $(MSG_COMPILING) $$< to $$@
|
||||
$(CC) -c $(THUMB) $$(CFLAGS) $$(CONLYFLAGS) $$< -o $$@
|
||||
endef
|
||||
$(foreach src, $(SRC), $(eval $(call COMPILE_C_TEMPLATE, $(src))))
|
||||
|
||||
# Compile: create object files from C source files. ARM-only
|
||||
define COMPILE_C_ARM_TEMPLATE
|
||||
$(OUTDIR)/$(notdir $(basename $(1))).o : $(1)
|
||||
## @echo
|
||||
@echo $(MSG_COMPILING_ARM) $$< to $$@
|
||||
$(CC) -c $$(CFLAGS) $$(CONLYFLAGS) $$< -o $$@
|
||||
endef
|
||||
$(foreach src, $(SRCARM), $(eval $(call COMPILE_C_ARM_TEMPLATE, $(src))))
|
||||
|
||||
|
||||
# Compile: create object files from C++ source files.
|
||||
define COMPILE_CPP_TEMPLATE
|
||||
$(OUTDIR)/$(notdir $(basename $(1))).o : $(1)
|
||||
## @echo
|
||||
@echo $(MSG_COMPILINGCPP) $$< to $$@
|
||||
$(CC) -c $(THUMB) $$(CFLAGS) $$(CPPFLAGS) $$< -o $$@
|
||||
endef
|
||||
$(foreach src, $(CPPSRC), $(eval $(call COMPILE_CPP_TEMPLATE, $(src))))
|
||||
|
||||
# Compile: create object files from C++ source files. ARM-only
|
||||
define COMPILE_CPP_ARM_TEMPLATE
|
||||
$(OUTDIR)/$(notdir $(basename $(1))).o : $(1)
|
||||
## @echo
|
||||
@echo $(MSG_COMPILINGCPP_ARM) $$< to $$@
|
||||
$(CC) -c $$(CFLAGS) $$(CPPFLAGS) $$< -o $$@
|
||||
endef
|
||||
$(foreach src, $(CPPSRCARM), $(eval $(call COMPILE_CPP_ARM_TEMPLATE, $(src))))
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files. ARM/Thumb
|
||||
$(SRC:.c=.s) : %.s : %.c
|
||||
@echo $(MSG_ASMFROMC) $< to $@
|
||||
$(CC) $(THUMB) -S $(CFLAGS) $(CONLYFLAGS) $< -o $@
|
||||
|
||||
# Compile: create assembler files from C source files. ARM only
|
||||
$(SRCARM:.c=.s) : %.s : %.c
|
||||
@echo $(MSG_ASMFROMC_ARM) $< to $@
|
||||
$(CC) -S $(CFLAGS) $(CONLYFLAGS) $< -o $@
|
||||
|
||||
# Generate Doxygen documents
|
||||
docs:
|
||||
doxygen $(DOXYGENDIR)/doxygen.cfg
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list finished end
|
||||
|
||||
clean_list :
|
||||
## @echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(OUTDIR)/$(TARGET).map
|
||||
$(REMOVE) $(OUTDIR)/$(TARGET).elf
|
||||
$(REMOVE) $(OUTDIR)/$(TARGET).hex
|
||||
$(REMOVE) $(OUTDIR)/$(TARGET).bin
|
||||
$(REMOVE) $(OUTDIR)/$(TARGET).sym
|
||||
$(REMOVE) $(OUTDIR)/$(TARGET).lss
|
||||
$(REMOVE) $(wildcard $(OUTDIR)/*.c)
|
||||
$(REMOVE) $(wildcard $(OUTDIR)/*.h)
|
||||
$(REMOVE) $(ALLOBJ)
|
||||
$(REMOVE) $(LSTFILES)
|
||||
$(REMOVE) $(DEPFILES)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRCARM:.c=.s)
|
||||
$(REMOVE) $(CPPSRC:.cpp=.s)
|
||||
$(REMOVE) $(CPPSRCARM:.cpp=.s)
|
||||
|
||||
|
||||
# Create output files directory
|
||||
# all known MS Windows OS define the ComSpec environment variable
|
||||
ifdef ComSpec
|
||||
$(shell md $(OUTDIR) 2>NUL)
|
||||
else
|
||||
$(shell mkdir $(OUTDIR) 2>/dev/null)
|
||||
endif
|
||||
|
||||
# Include the dependency files.
|
||||
ifdef ComSpec
|
||||
-include $(shell md $(OUTDIR)\dep 2>NUL) $(wildcard $(OUTDIR)/dep/*)
|
||||
else
|
||||
-include $(shell mkdir $(OUTDIR) 2>/dev/null) $(shell mkdir $(OUTDIR)/dep 2>/dev/null) $(wildcard $(OUTDIR)/dep/*)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all begin finish end sizebefore sizeafter gccversion \
|
||||
build elf hex bin lss sym clean clean_list program gencode
|
||||
|
83
flight/Revolution/System/inc/pios_board_posix.h
Normal file
83
flight/Revolution/System/inc/pios_board_posix.h
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Defines board hardware for the OpenPilot Version 1.1 hardware.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PIOS_BOARD_H
|
||||
#define PIOS_BOARD_H
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------
|
||||
// PIOS_LED
|
||||
//------------------------
|
||||
#define PIOS_LED_ALARM 0
|
||||
#define PIOS_LED_HEARTBEAT 1
|
||||
#define PIOS_LED_NUM 2
|
||||
|
||||
//-------------------------
|
||||
// COM
|
||||
//
|
||||
// See also pios_board_posix.c
|
||||
//-------------------------
|
||||
//#define PIOS_USART_TX_BUFFER_SIZE 256
|
||||
#define PIOS_COM_BUFFER_SIZE 1024
|
||||
#define PIOS_COM_MAX_DEVS 255
|
||||
#define PIOS_UDP_RX_BUFFER_SIZE PIOS_COM_BUFFER_SIZE
|
||||
|
||||
extern uint32_t pios_com_telem_rf_id;
|
||||
extern uint32_t pios_com_telem_usb_id;
|
||||
extern uint32_t pios_com_gps_id;
|
||||
extern uint32_t pios_com_aux_id;
|
||||
extern uint32_t pios_com_spectrum_id;
|
||||
|
||||
#define PIOS_COM_TELEM_RF (pios_com_telem_rf_id)
|
||||
#define PIOS_COM_TELEM_USB (pios_com_telem_usb_id)
|
||||
#define PIOS_COM_GPS (pios_com_gps_id)
|
||||
|
||||
#ifdef PIOS_ENABLE_AUX_UART
|
||||
#define PIOS_COM_AUX (pios_com_aux_id)
|
||||
#define PIOS_COM_DEBUG (PIOS_COM_AUX
|
||||
#endif
|
||||
|
||||
/**
|
||||
* glue macros for file IO
|
||||
* STM32 uses DOSFS for file IO
|
||||
*/
|
||||
#define PIOS_FOPEN_READ(filename,file) (file=fopen((char*)filename,"r"))==NULL
|
||||
|
||||
#define PIOS_FOPEN_WRITE(filename,file) (file=fopen((char*)filename,"w"))==NULL
|
||||
|
||||
#define PIOS_FREAD(file,bufferadr,length,resultadr) (*resultadr=fread((uint8_t*)bufferadr,1,length,*file)) != length
|
||||
|
||||
#define PIOS_FWRITE(file,bufferadr,length,resultadr) *resultadr=fwrite((uint8_t*)bufferadr,1,length,*file)
|
||||
|
||||
|
||||
|
||||
#define PIOS_FCLOSE(file) fclose(file)
|
||||
|
||||
#define PIOS_FUNLINK(file) unlink((char*)filename)
|
||||
|
||||
#endif /* PIOS_BOARD_H */
|
75
flight/Revolution/System/inc/pios_config_posix.h
Normal file
75
flight/Revolution/System/inc/pios_config_posix.h
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_config.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief PiOS configuration header.
|
||||
* Central compile time config for the project.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PIOS_CONFIG_POSIX_H
|
||||
#define PIOS_CONFIG_POSIX_H
|
||||
|
||||
|
||||
/* Enable/Disable PiOS Modules */
|
||||
#define PIOS_INCLUDE_SYS
|
||||
#define PIOS_INCLUDE_DELAY
|
||||
#define PIOS_INCLUDE_LED
|
||||
#define PIOS_INCLUDE_SDCARD
|
||||
#define PIOS_INCLUDE_FREERTOS
|
||||
#define PIOS_INCLUDE_COM
|
||||
#define PIOS_INCLUDE_GPS
|
||||
#define PIOS_INCLUDE_IRQ
|
||||
#define PIOS_INCLUDE_TELEMETRY_RF
|
||||
#define PIOS_INCLUDE_UDP
|
||||
#define PIOS_INCLUDE_SERVO
|
||||
#define PIOS_INCLUDE_RCVR
|
||||
|
||||
#define PIOS_RCVR_MAX_CHANNELS 12
|
||||
#define PIOS_RCVR_MAX_DEVS 3
|
||||
|
||||
/* Defaults for Logging */
|
||||
#define LOG_FILENAME "PIOS.LOG"
|
||||
#define STARTUP_LOG_ENABLED 1
|
||||
|
||||
/* COM Module */
|
||||
#define GPS_BAUDRATE 19200
|
||||
#define TELEM_BAUDRATE 19200
|
||||
#define AUXUART_ENABLED 0
|
||||
#define AUXUART_BAUDRATE 19200
|
||||
|
||||
#define TELEM_QUEUE_SIZE 20
|
||||
#define PIOS_TELEM_STACK_SIZE 2048
|
||||
|
||||
/* Stabilization options */
|
||||
#define PIOS_QUATERNION_STABILIZATION
|
||||
|
||||
/* GPS options */
|
||||
#define PIOS_GPS_SETS_HOMELOCATION
|
||||
|
||||
#define HEAP_LIMIT_WARNING 4000
|
||||
#define HEAP_LIMIT_CRITICAL 1000
|
||||
#define IRQSTACK_LIMIT_WARNING 150
|
||||
#define IRQSTACK_LIMIT_CRITICAL 80
|
||||
#define CPULOAD_LIMIT_WARNING 80
|
||||
#define CPULOAD_LIMIT_CRITICAL 95
|
||||
|
||||
#endif /* PIOS_CONFIG_POSIX_H */
|
183
flight/Revolution/System/pios_board_posix.c
Normal file
183
flight/Revolution/System/pios_board_posix.c
Normal file
@ -0,0 +1,183 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Defines board specific static initializers for hardware for the OpenPilot board.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <pios.h>
|
||||
#include <pios_udp_priv.h>
|
||||
#include <pios_com_priv.h>
|
||||
#include <openpilot.h>
|
||||
#include <uavobjectsinit.h>
|
||||
|
||||
#include "attituderaw.h"
|
||||
#include "attitudeactual.h"
|
||||
#include "positionactual.h"
|
||||
#include "velocityactual.h"
|
||||
#include "manualcontrolsettings.h"
|
||||
|
||||
#include "pios_rcvr_priv.h"
|
||||
|
||||
struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[PIOS_RCVR_MAX_CHANNELS];
|
||||
uint32_t pios_rcvr_max_channel;
|
||||
|
||||
void Stack_Change() {
|
||||
}
|
||||
|
||||
void Stack_Change_Weak() {
|
||||
}
|
||||
|
||||
|
||||
const struct pios_udp_cfg pios_udp_telem_cfg = {
|
||||
.ip = "0.0.0.0",
|
||||
.port = 9000,
|
||||
};
|
||||
const struct pios_udp_cfg pios_udp_gps_cfg = {
|
||||
.ip = "0.0.0.0",
|
||||
.port = 9001,
|
||||
};
|
||||
const struct pios_udp_cfg pios_udp_debug_cfg = {
|
||||
.ip = "0.0.0.0",
|
||||
.port = 9002,
|
||||
};
|
||||
|
||||
#ifdef PIOS_COM_AUX
|
||||
/*
|
||||
* AUX USART
|
||||
*/
|
||||
const struct pios_udp_cfg pios_udp_aux_cfg = {
|
||||
.ip = "0.0.0.0",
|
||||
.port = 9003,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define PIOS_COM_TELEM_RF_RX_BUF_LEN 192
|
||||
#define PIOS_COM_TELEM_RF_TX_BUF_LEN 192
|
||||
#define PIOS_COM_GPS_RX_BUF_LEN 96
|
||||
|
||||
/*
|
||||
* Board specific number of devices.
|
||||
*/
|
||||
/*
|
||||
struct pios_udp_dev pios_udp_devs[] = {
|
||||
#define PIOS_UDP_TELEM 0
|
||||
{
|
||||
.cfg = &pios_udp0_cfg,
|
||||
},
|
||||
#define PIOS_UDP_GPS 1
|
||||
{
|
||||
.cfg = &pios_udp1_cfg,
|
||||
},
|
||||
#define PIOS_UDP_LOCAL 2
|
||||
{
|
||||
.cfg = &pios_udp2_cfg,
|
||||
},
|
||||
#ifdef PIOS_COM_AUX
|
||||
#define PIOS_UDP_AUX 3
|
||||
{
|
||||
.cfg = &pios_udp3_cfg,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint8_t pios_udp_num_devices = NELEMENTS(pios_udp_devs);
|
||||
*/
|
||||
/*
|
||||
* COM devices
|
||||
*/
|
||||
|
||||
/*
|
||||
* Board specific number of devices.
|
||||
*/
|
||||
extern const struct pios_com_driver pios_serial_com_driver;
|
||||
extern const struct pios_com_driver pios_udp_com_driver;
|
||||
|
||||
uint32_t pios_com_telem_rf_id;
|
||||
uint32_t pios_com_telem_usb_id;
|
||||
uint32_t pios_com_gps_id;
|
||||
uint32_t pios_com_aux_id;
|
||||
uint32_t pios_com_spectrum_id;
|
||||
uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE];
|
||||
|
||||
/**
|
||||
* PIOS_Board_Init()
|
||||
* initializes all the core systems on this specific hardware
|
||||
* called from System/openpilot.c
|
||||
*/
|
||||
void PIOS_Board_Init(void) {
|
||||
|
||||
/* Delay system */
|
||||
PIOS_DELAY_Init();
|
||||
|
||||
/* Initialize UAVObject libraries */
|
||||
EventDispatcherInitialize();
|
||||
UAVObjInitialize();
|
||||
UAVObjectsInitializeAll();
|
||||
|
||||
/* Initialize the alarms library */
|
||||
AlarmsInitialize();
|
||||
|
||||
/* Initialize the task monitor library */
|
||||
TaskMonitorInitialize();
|
||||
|
||||
#if defined(PIOS_INCLUDE_COM)
|
||||
#if defined(PIOS_INCLUDE_TELEMETRY_RF)
|
||||
{
|
||||
uint32_t pios_udp_telem_rf_id;
|
||||
if (PIOS_UDP_Init(&pios_udp_telem_rf_id, &pios_udp_telem_cfg)) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
|
||||
uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_RF_RX_BUF_LEN);
|
||||
uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_RF_TX_BUF_LEN);
|
||||
PIOS_Assert(rx_buffer);
|
||||
PIOS_Assert(tx_buffer);
|
||||
if (PIOS_COM_Init(&pios_com_telem_rf_id, &pios_udp_com_driver, pios_udp_telem_rf_id,
|
||||
rx_buffer, PIOS_COM_TELEM_RF_RX_BUF_LEN,
|
||||
tx_buffer, PIOS_COM_TELEM_RF_TX_BUF_LEN)) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_TELEMETRY_RF */
|
||||
|
||||
#if defined(PIOS_INCLUDE_GPS)
|
||||
{
|
||||
uint32_t pios_udp_gps_id;
|
||||
if (PIOS_UDP_Init(&pios_udp_gps_id, &pios_udp_gps_cfg)) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_GPS_RX_BUF_LEN);
|
||||
PIOS_Assert(rx_buffer);
|
||||
if (PIOS_COM_Init(&pios_com_gps_id, &pios_udp_com_driver, pios_udp_gps_id,
|
||||
rx_buffer, PIOS_COM_GPS_RX_BUF_LEN,
|
||||
NULL, 0)) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_GPS */
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
Loading…
x
Reference in New Issue
Block a user